Full Code of getredash/redash for AI

master fc1b23fda7a5 cached
1155 files
5.7 MB
1.5M tokens
4438 symbols
1 requests
Download .txt
Showing preview only (6,155K chars total). Download the full file or copy to clipboard to get everything.
Repository: getredash/redash
Branch: master
Commit: fc1b23fda7a5
Files: 1155
Total size: 5.7 MB

Directory structure:
gitextract_b07d1bqv/

├── .ci/
│   ├── Dockerfile.cypress
│   ├── compose.ci.yaml
│   ├── compose.cypress.yaml
│   ├── docker_build
│   ├── pack
│   └── update_version
├── .coveragerc
├── .dockerignore
├── .editorconfig
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── ---bug_report.md
│   │   └── --anything_else.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── config.yml
│   ├── weekly-digest.yml
│   └── workflows/
│       ├── ci.yml
│       ├── periodic-snapshot.yml
│       ├── preview-image.yml
│       └── restyled.yml
├── .gitignore
├── .npmrc
├── .nvmrc
├── .pre-commit-config.yaml
├── .restyled.yaml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── LICENSE.borders
├── Makefile
├── README.md
├── SECURITY.md
├── bin/
│   ├── docker-entrypoint
│   ├── get_changes.py
│   ├── release_manager.py
│   └── run
├── client/
│   ├── .babelrc
│   ├── .eslintignore
│   ├── .eslintrc.js
│   ├── .gitignore
│   ├── app/
│   │   ├── .eslintrc.js
│   │   ├── __tests__/
│   │   │   ├── enzyme_setup.js
│   │   │   └── mocks.js
│   │   ├── assets/
│   │   │   ├── css/
│   │   │   │   └── login.css
│   │   │   ├── images/
│   │   │   │   └── illustrations/
│   │   │   │       └── readme.md
│   │   │   ├── less/
│   │   │   │   ├── STYLING-README.md
│   │   │   │   ├── ant.less
│   │   │   │   ├── inc/
│   │   │   │   │   ├── 404.less
│   │   │   │   │   ├── ace-editor.less
│   │   │   │   │   ├── alert.less
│   │   │   │   │   ├── ant-variables.less
│   │   │   │   │   ├── base.less
│   │   │   │   │   ├── bootstrap-overrides.less
│   │   │   │   │   ├── breadcrumb.less
│   │   │   │   │   ├── button.less
│   │   │   │   │   ├── carousel.less
│   │   │   │   │   ├── chart.less
│   │   │   │   │   ├── dropdown.less
│   │   │   │   │   ├── edit-in-place.less
│   │   │   │   │   ├── flex.less
│   │   │   │   │   ├── font.less
│   │   │   │   │   ├── form.less
│   │   │   │   │   ├── generics.less
│   │   │   │   │   ├── header.less
│   │   │   │   │   ├── ie-warning.less
│   │   │   │   │   ├── jumbotron.less
│   │   │   │   │   ├── label.less
│   │   │   │   │   ├── less-plugins/
│   │   │   │   │   │   └── for.less
│   │   │   │   │   ├── list-group.less
│   │   │   │   │   ├── list.less
│   │   │   │   │   ├── login.less
│   │   │   │   │   ├── media.less
│   │   │   │   │   ├── messages.less
│   │   │   │   │   ├── misc.less
│   │   │   │   │   ├── mixins.less
│   │   │   │   │   ├── modal.less
│   │   │   │   │   ├── panel.less
│   │   │   │   │   ├── photos.less
│   │   │   │   │   ├── popover.less
│   │   │   │   │   ├── pricing-table.less
│   │   │   │   │   ├── print.less
│   │   │   │   │   ├── profile.less
│   │   │   │   │   ├── progress-bar.less
│   │   │   │   │   ├── schema-browser.less
│   │   │   │   │   ├── sidebar.less
│   │   │   │   │   ├── table.less
│   │   │   │   │   ├── tile.less
│   │   │   │   │   ├── tooltips.less
│   │   │   │   │   ├── variables.less
│   │   │   │   │   ├── visualizations/
│   │   │   │   │   │   ├── box.less
│   │   │   │   │   │   ├── map.less
│   │   │   │   │   │   ├── misc.less
│   │   │   │   │   │   └── pivot-table.less
│   │   │   │   │   ├── well.less
│   │   │   │   │   └── widgets.less
│   │   │   │   ├── main.less
│   │   │   │   ├── redash/
│   │   │   │   │   ├── css-logo.less
│   │   │   │   │   ├── loading-indicator.less
│   │   │   │   │   ├── query.less
│   │   │   │   │   ├── redash-table.less
│   │   │   │   │   └── tags-control.less
│   │   │   │   └── server.less
│   │   │   └── robots.txt
│   │   ├── components/
│   │   │   ├── AceEditorInput.jsx
│   │   │   ├── AceEditorInput.less
│   │   │   ├── ApplicationArea/
│   │   │   │   ├── ApplicationLayout/
│   │   │   │   │   ├── DesktopNavbar.jsx
│   │   │   │   │   ├── DesktopNavbar.less
│   │   │   │   │   ├── MobileNavbar.jsx
│   │   │   │   │   ├── MobileNavbar.less
│   │   │   │   │   ├── VersionInfo.jsx
│   │   │   │   │   ├── index.jsx
│   │   │   │   │   └── index.less
│   │   │   │   ├── ErrorMessage.jsx
│   │   │   │   ├── ErrorMessage.less
│   │   │   │   ├── ErrorMessage.test.js
│   │   │   │   ├── ErrorMessageDetails.jsx
│   │   │   │   ├── Router.jsx
│   │   │   │   ├── handleNavigationIntent.js
│   │   │   │   ├── index.jsx
│   │   │   │   ├── navigateTo.js
│   │   │   │   ├── routeWithApiKeySession.jsx
│   │   │   │   └── routeWithUserSession.tsx
│   │   │   ├── BeaconConsent.jsx
│   │   │   ├── BigMessage.jsx
│   │   │   ├── CodeBlock.jsx
│   │   │   ├── CodeBlock.less
│   │   │   ├── Collapse.jsx
│   │   │   ├── CreateSourceDialog.jsx
│   │   │   ├── DateInput.jsx
│   │   │   ├── DateRangeInput.jsx
│   │   │   ├── DateTimeInput.jsx
│   │   │   ├── DateTimeRangeInput.jsx
│   │   │   ├── DialogWrapper.d.ts
│   │   │   ├── DialogWrapper.jsx
│   │   │   ├── DynamicComponent.jsx
│   │   │   ├── EditInPlace.jsx
│   │   │   ├── EditParameterSettingsDialog.jsx
│   │   │   ├── EditParameterSettingsDialog.less
│   │   │   ├── EditVisualizationButton/
│   │   │   │   ├── QueryControlDropdown.jsx
│   │   │   │   ├── QueryResultsLink.jsx
│   │   │   │   └── index.jsx
│   │   │   ├── EmailSettingsWarning.jsx
│   │   │   ├── FavoritesControl.jsx
│   │   │   ├── Filters.jsx
│   │   │   ├── HelpTrigger.jsx
│   │   │   ├── HelpTrigger.less
│   │   │   ├── InputWithCopy.jsx
│   │   │   ├── Link.tsx
│   │   │   ├── NoTaggedObjectsFound.jsx
│   │   │   ├── PageHeader/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── Paginator.jsx
│   │   │   ├── ParameterApplyButton.jsx
│   │   │   ├── ParameterMappingInput.jsx
│   │   │   ├── ParameterMappingInput.less
│   │   │   ├── ParameterValueInput.jsx
│   │   │   ├── ParameterValueInput.less
│   │   │   ├── Parameters.jsx
│   │   │   ├── Parameters.less
│   │   │   ├── PermissionsEditorDialog/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── PlainButton.less
│   │   │   ├── PlainButton.tsx
│   │   │   ├── PreviewCard.jsx
│   │   │   ├── QueryBasedParameterInput.jsx
│   │   │   ├── QueryLink.jsx
│   │   │   ├── QueryLink.less
│   │   │   ├── QuerySelector.jsx
│   │   │   ├── Resizable/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── SelectItemsDialog.jsx
│   │   │   ├── SelectItemsDialog.less
│   │   │   ├── SelectWithVirtualScroll.tsx
│   │   │   ├── SettingsWrapper.jsx
│   │   │   ├── TagsList.less
│   │   │   ├── TagsList.tsx
│   │   │   ├── TimeAgo.jsx
│   │   │   ├── Timer.jsx
│   │   │   ├── Tooltip.tsx
│   │   │   ├── UserGroups.jsx
│   │   │   ├── UserGroups.less
│   │   │   ├── admin/
│   │   │   │   ├── Layout.jsx
│   │   │   │   ├── RQStatus.jsx
│   │   │   │   ├── StatusBlock.jsx
│   │   │   │   └── layout.less
│   │   │   ├── cards-list/
│   │   │   │   ├── CardsList.less
│   │   │   │   └── CardsList.tsx
│   │   │   ├── dashboards/
│   │   │   │   ├── AddWidgetDialog.jsx
│   │   │   │   ├── AutoHeightController.js
│   │   │   │   ├── CreateDashboardDialog.jsx
│   │   │   │   ├── DashboardGrid.jsx
│   │   │   │   ├── EditParameterMappingsDialog.jsx
│   │   │   │   ├── ExpandedWidgetDialog.jsx
│   │   │   │   ├── TextboxDialog.jsx
│   │   │   │   ├── TextboxDialog.less
│   │   │   │   ├── dashboard-grid.less
│   │   │   │   └── dashboard-widget/
│   │   │   │       ├── RestrictedWidget.jsx
│   │   │   │       ├── TextboxWidget.jsx
│   │   │   │       ├── VisualizationWidget.jsx
│   │   │   │       ├── Widget.jsx
│   │   │   │       ├── Widget.less
│   │   │   │       └── index.js
│   │   │   ├── dynamic-form/
│   │   │   │   ├── DynamicForm.jsx
│   │   │   │   ├── DynamicForm.less
│   │   │   │   ├── DynamicFormField.jsx
│   │   │   │   ├── dynamicFormHelper.js
│   │   │   │   ├── fields/
│   │   │   │   │   ├── AceEditorField.jsx
│   │   │   │   │   ├── CheckboxField.jsx
│   │   │   │   │   ├── ContentField.jsx
│   │   │   │   │   ├── FileField.jsx
│   │   │   │   │   ├── InputField.jsx
│   │   │   │   │   ├── NumberField.jsx
│   │   │   │   │   ├── SelectField.jsx
│   │   │   │   │   ├── TextAreaField.jsx
│   │   │   │   │   └── index.js
│   │   │   │   └── getFieldLabel.js
│   │   │   ├── dynamic-parameters/
│   │   │   │   ├── DateParameter.jsx
│   │   │   │   ├── DateRangeParameter.jsx
│   │   │   │   ├── DynamicButton.jsx
│   │   │   │   ├── DynamicButton.less
│   │   │   │   ├── DynamicDatePicker.jsx
│   │   │   │   ├── DynamicDateRangePicker.jsx
│   │   │   │   └── DynamicParameters.less
│   │   │   ├── empty-state/
│   │   │   │   ├── EmptyState.d.ts
│   │   │   │   ├── EmptyState.jsx
│   │   │   │   └── empty-state.less
│   │   │   ├── groups/
│   │   │   │   ├── CreateGroupDialog.jsx
│   │   │   │   ├── DeleteGroupButton.jsx
│   │   │   │   ├── DetailsPageSidebar.jsx
│   │   │   │   ├── GroupName.jsx
│   │   │   │   └── ListItemAddon.jsx
│   │   │   ├── items-list/
│   │   │   │   ├── ItemsList.tsx
│   │   │   │   ├── classes/
│   │   │   │   │   ├── ItemsFetcher.js
│   │   │   │   │   ├── ItemsSource.d.ts
│   │   │   │   │   ├── ItemsSource.js
│   │   │   │   │   ├── Paginator.js
│   │   │   │   │   ├── Sorter.js
│   │   │   │   │   └── StateStorage.js
│   │   │   │   ├── components/
│   │   │   │   │   ├── EmptyState.jsx
│   │   │   │   │   ├── ItemsTable.jsx
│   │   │   │   │   ├── LoadingState.jsx
│   │   │   │   │   └── Sidebar.jsx
│   │   │   │   └── hooks/
│   │   │   │       └── useItemsListExtraActions.js
│   │   │   ├── layouts/
│   │   │   │   ├── ContentWithSidebar.jsx
│   │   │   │   └── content-with-sidebar.less
│   │   │   ├── proptypes.js
│   │   │   ├── queries/
│   │   │   │   ├── AddToDashboardDialog.jsx
│   │   │   │   ├── ApiKeyDialog/
│   │   │   │   │   ├── index.jsx
│   │   │   │   │   └── index.less
│   │   │   │   ├── EmbedQueryDialog.jsx
│   │   │   │   ├── EmbedQueryDialog.less
│   │   │   │   ├── QueryEditor/
│   │   │   │   │   ├── AutoLimitCheckbox.jsx
│   │   │   │   │   ├── AutocompleteToggle.jsx
│   │   │   │   │   ├── QueryEditorControls.jsx
│   │   │   │   │   ├── QueryEditorControls.less
│   │   │   │   │   ├── ace.js
│   │   │   │   │   ├── index.jsx
│   │   │   │   │   └── index.less
│   │   │   │   ├── ScheduleDialog.css
│   │   │   │   ├── ScheduleDialog.jsx
│   │   │   │   ├── ScheduleDialog.test.js
│   │   │   │   ├── SchedulePhrase.jsx
│   │   │   │   ├── SchemaBrowser.jsx
│   │   │   │   ├── __snapshots__/
│   │   │   │   │   └── ScheduleDialog.test.js.snap
│   │   │   │   ├── add-to-dashboard-dialog.less
│   │   │   │   └── editor-components/
│   │   │   │       ├── databricks/
│   │   │   │       │   ├── DatabricksSchemaBrowser.jsx
│   │   │   │       │   ├── DatabricksSchemaBrowser.less
│   │   │   │       │   └── useDatabricksSchema.js
│   │   │   │       ├── editorComponents.js
│   │   │   │       └── index.js
│   │   │   ├── query-snippets/
│   │   │   │   └── QuerySnippetDialog.jsx
│   │   │   ├── tags-control/
│   │   │   │   ├── EditTagsDialog.jsx
│   │   │   │   └── TagsControl.jsx
│   │   │   └── visualizations/
│   │   │       ├── EditVisualizationDialog.jsx
│   │   │       ├── EditVisualizationDialog.less
│   │   │       ├── VisualizationName.jsx
│   │   │       ├── VisualizationName.less
│   │   │       ├── VisualizationRenderer.jsx
│   │   │       └── visualizationComponents.jsx
│   │   ├── config/
│   │   │   ├── antd-spinner.jsx
│   │   │   ├── dashboard-grid-options.js
│   │   │   └── index.js
│   │   ├── extensions/
│   │   │   └── .gitkeep
│   │   ├── index.html
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── accessibility.ts
│   │   │   ├── calculateTextWidth.ts
│   │   │   ├── hooks/
│   │   │   │   ├── useFullscreenHandler.js
│   │   │   │   ├── useImmutableCallback.js
│   │   │   │   ├── useLazyRef.ts
│   │   │   │   ├── useSearchResults.js
│   │   │   │   └── useUniqueId.ts
│   │   │   ├── localOptions.js
│   │   │   ├── pagination/
│   │   │   │   ├── index.js
│   │   │   │   └── paginator.js
│   │   │   ├── queryFormat.test.js
│   │   │   ├── queryFormat.ts
│   │   │   ├── useQueryResultData.js
│   │   │   └── utils.js
│   │   ├── multi_org.html
│   │   ├── pages/
│   │   │   ├── admin/
│   │   │   │   ├── Jobs.jsx
│   │   │   │   ├── OutdatedQueries.jsx
│   │   │   │   ├── SystemStatus.jsx
│   │   │   │   └── system-status.less
│   │   │   ├── alert/
│   │   │   │   ├── Alert.jsx
│   │   │   │   ├── AlertEdit.jsx
│   │   │   │   ├── AlertNew.jsx
│   │   │   │   ├── AlertView.jsx
│   │   │   │   └── components/
│   │   │   │       ├── AlertDestinations.jsx
│   │   │   │       ├── AlertDestinations.less
│   │   │   │       ├── Criteria.jsx
│   │   │   │       ├── Criteria.less
│   │   │   │       ├── HorizontalFormItem.jsx
│   │   │   │       ├── MenuButton.jsx
│   │   │   │       ├── NotificationTemplate.jsx
│   │   │   │       ├── NotificationTemplate.less
│   │   │   │       ├── Query.jsx
│   │   │   │       ├── Query.less
│   │   │   │       ├── Rearm.jsx
│   │   │   │       ├── Rearm.less
│   │   │   │       ├── Title.jsx
│   │   │   │       └── Title.less
│   │   │   ├── alerts/
│   │   │   │   └── AlertsList.jsx
│   │   │   ├── dashboards/
│   │   │   │   ├── DashboardList.jsx
│   │   │   │   ├── DashboardPage.jsx
│   │   │   │   ├── DashboardPage.less
│   │   │   │   ├── PublicDashboardPage.jsx
│   │   │   │   ├── PublicDashboardPage.less
│   │   │   │   ├── components/
│   │   │   │   │   ├── DashboardHeader.jsx
│   │   │   │   │   ├── DashboardHeader.less
│   │   │   │   │   ├── DashboardListEmptyState.tsx
│   │   │   │   │   └── ShareDashboardDialog.jsx
│   │   │   │   ├── dashboard-list.css
│   │   │   │   └── hooks/
│   │   │   │       ├── useDashboard.js
│   │   │   │       ├── useDataSources.js
│   │   │   │       ├── useDuplicateDashboard.js
│   │   │   │       ├── useEditModeHandler.js
│   │   │   │       └── useRefreshRateHandler.js
│   │   │   ├── data-sources/
│   │   │   │   ├── DataSourcesList.jsx
│   │   │   │   └── EditDataSource.jsx
│   │   │   ├── destinations/
│   │   │   │   ├── DestinationsList.jsx
│   │   │   │   └── EditDestination.jsx
│   │   │   ├── groups/
│   │   │   │   ├── GroupDataSources.jsx
│   │   │   │   ├── GroupMembers.jsx
│   │   │   │   └── GroupsList.jsx
│   │   │   ├── home/
│   │   │   │   ├── Home.jsx
│   │   │   │   ├── Home.less
│   │   │   │   └── components/
│   │   │   │       └── FavoritesList.jsx
│   │   │   ├── index.js
│   │   │   ├── queries/
│   │   │   │   ├── QuerySource.jsx
│   │   │   │   ├── QuerySource.less
│   │   │   │   ├── QueryView.jsx
│   │   │   │   ├── QueryView.less
│   │   │   │   ├── VisualizationEmbed.jsx
│   │   │   │   ├── components/
│   │   │   │   │   ├── QueryExecutionMetadata.jsx
│   │   │   │   │   ├── QueryExecutionMetadata.less
│   │   │   │   │   ├── QueryExecutionStatus.jsx
│   │   │   │   │   ├── QueryMetadata.jsx
│   │   │   │   │   ├── QueryMetadata.less
│   │   │   │   │   ├── QueryPageHeader.jsx
│   │   │   │   │   ├── QueryPageHeader.less
│   │   │   │   │   ├── QuerySourceAlerts.jsx
│   │   │   │   │   ├── QuerySourceAlerts.less
│   │   │   │   │   ├── QuerySourceDropdown.jsx
│   │   │   │   │   ├── QuerySourceDropdownItem.jsx
│   │   │   │   │   ├── QuerySourceTypeIcon.jsx
│   │   │   │   │   ├── QueryViewButton.jsx
│   │   │   │   │   ├── QueryVisualizationTabs.jsx
│   │   │   │   │   ├── QueryVisualizationTabs.less
│   │   │   │   │   └── wrapQueryPage.jsx
│   │   │   │   └── hooks/
│   │   │   │       ├── useAddNewParameterDialog.js
│   │   │   │       ├── useAddToDashboardDialog.js
│   │   │   │       ├── useAddVisualizationDialog.js
│   │   │   │       ├── useApiKeyDialog.js
│   │   │   │       ├── useArchiveQuery.jsx
│   │   │   │       ├── useAutoLimitFlags.js
│   │   │   │       ├── useAutocompleteFlags.js
│   │   │   │       ├── useDataSourceSchema.js
│   │   │   │       ├── useDeleteVisualization.js
│   │   │   │       ├── useDuplicateQuery.js
│   │   │   │       ├── useEditScheduleDialog.js
│   │   │   │       ├── useEditVisualizationDialog.js
│   │   │   │       ├── useEmbedDialog.js
│   │   │   │       ├── usePermissionsEditorDialog.js
│   │   │   │       ├── usePublishQuery.js
│   │   │   │       ├── useQuery.js
│   │   │   │       ├── useQueryDataSources.js
│   │   │   │       ├── useQueryExecute.js
│   │   │   │       ├── useQueryFlags.js
│   │   │   │       ├── useQueryParameters.js
│   │   │   │       ├── useRenameQuery.js
│   │   │   │       ├── useUnpublishQuery.js
│   │   │   │       ├── useUnsavedChangesAlert.js
│   │   │   │       ├── useUpdateQuery.jsx
│   │   │   │       ├── useUpdateQueryDescription.js
│   │   │   │       ├── useUpdateQueryTags.js
│   │   │   │       └── useVisualizationTabHandler.js
│   │   │   ├── queries-list/
│   │   │   │   ├── QueriesList.jsx
│   │   │   │   ├── QueriesListEmptyState.jsx
│   │   │   │   └── queries-list.css
│   │   │   ├── query-snippets/
│   │   │   │   ├── QuerySnippetsList.jsx
│   │   │   │   └── QuerySnippetsList.less
│   │   │   ├── settings/
│   │   │   │   ├── OrganizationSettings.jsx
│   │   │   │   ├── components/
│   │   │   │   │   ├── AuthSettings/
│   │   │   │   │   │   ├── GoogleLoginSettings.jsx
│   │   │   │   │   │   ├── PasswordLoginSettings.jsx
│   │   │   │   │   │   ├── SAMLSettings.jsx
│   │   │   │   │   │   └── index.jsx
│   │   │   │   │   ├── GeneralSettings/
│   │   │   │   │   │   ├── BeaconConsentSettings.jsx
│   │   │   │   │   │   ├── FeatureFlagsSettings.jsx
│   │   │   │   │   │   ├── FormatSettings.jsx
│   │   │   │   │   │   ├── PlotlySettings.jsx
│   │   │   │   │   │   └── index.jsx
│   │   │   │   │   └── prop-types.js
│   │   │   │   └── hooks/
│   │   │   │       └── useOrganizationSettings.js
│   │   │   └── users/
│   │   │       ├── UserProfile.jsx
│   │   │       ├── UsersList.jsx
│   │   │       ├── components/
│   │   │       │   ├── ApiKeyForm.jsx
│   │   │       │   ├── CreateUserDialog.jsx
│   │   │       │   ├── EditableUserProfile.jsx
│   │   │       │   ├── PasswordForm/
│   │   │       │   │   ├── ChangePasswordDialog.jsx
│   │   │       │   │   ├── PasswordLinkAlert.jsx
│   │   │       │   │   ├── PasswordResetForm.jsx
│   │   │       │   │   ├── ResendInvitationForm.jsx
│   │   │       │   │   └── index.jsx
│   │   │       │   ├── ReadOnlyUserProfile.jsx
│   │   │       │   ├── ReadOnlyUserProfile.test.js
│   │   │       │   ├── ToggleUserForm.jsx
│   │   │       │   ├── UserInfoForm.jsx
│   │   │       │   └── __snapshots__/
│   │   │       │       └── ReadOnlyUserProfile.test.js.snap
│   │   │       ├── hooks/
│   │   │       │   └── useUserGroups.js
│   │   │       └── settings.less
│   │   ├── redash-font/
│   │   │   ├── style.less
│   │   │   └── variables.less
│   │   ├── services/
│   │   │   ├── KeyboardShortcuts.js
│   │   │   ├── alert-subscription.js
│   │   │   ├── alert.js
│   │   │   ├── auth.js
│   │   │   ├── auth.test.js
│   │   │   ├── axios.js
│   │   │   ├── dashboard.js
│   │   │   ├── data-source.js
│   │   │   ├── databricks-data-source.js
│   │   │   ├── destination.js
│   │   │   ├── getTags.js
│   │   │   ├── group.js
│   │   │   ├── location.js
│   │   │   ├── notification.d.ts
│   │   │   ├── notification.js
│   │   │   ├── notifications.js
│   │   │   ├── offline-listener.js
│   │   │   ├── organizationSettings.js
│   │   │   ├── organizationStatus.js
│   │   │   ├── parameters/
│   │   │   │   ├── DateParameter.js
│   │   │   │   ├── DateRangeParameter.js
│   │   │   │   ├── EnumParameter.js
│   │   │   │   ├── NumberParameter.js
│   │   │   │   ├── Parameter.js
│   │   │   │   ├── QueryBasedDropdownParameter.js
│   │   │   │   ├── TextParameter.js
│   │   │   │   ├── TextPatternParameter.js
│   │   │   │   ├── index.js
│   │   │   │   └── tests/
│   │   │   │       ├── DateParameter.test.js
│   │   │   │       ├── DateRangeParameter.test.js
│   │   │   │       ├── EnumParameter.test.js
│   │   │   │       ├── NumberParameter.test.js
│   │   │   │       ├── Parameter.test.js
│   │   │   │       ├── QueryBasedDropdownParameter.test.js
│   │   │   │       ├── TextParameter.test.js
│   │   │   │       └── TextPatternParameter.test.js
│   │   │   ├── policy/
│   │   │   │   ├── DefaultPolicy.js
│   │   │   │   └── index.js
│   │   │   ├── query-result.js
│   │   │   ├── query-result.test.js
│   │   │   ├── query-snippet.js
│   │   │   ├── query.js
│   │   │   ├── recordEvent.js
│   │   │   ├── resizeObserver.js
│   │   │   ├── restoreSession.jsx
│   │   │   ├── routes.ts
│   │   │   ├── sanitize.js
│   │   │   ├── settingsMenu.js
│   │   │   ├── settingsMenu.test.js
│   │   │   ├── url.js
│   │   │   ├── user.js
│   │   │   ├── utils.js
│   │   │   ├── visualization.js
│   │   │   └── widget.js
│   │   ├── styles/
│   │   │   ├── formStyle.less
│   │   │   └── formStyle.ts
│   │   ├── unsupported.html
│   │   ├── unsupportedRedirect.js
│   │   └── version.json
│   ├── cypress/
│   │   ├── .eslintrc.js
│   │   ├── cypress.js
│   │   ├── integration/
│   │   │   ├── alert/
│   │   │   │   ├── create_alert_spec.js
│   │   │   │   ├── edit_alert_spec.js
│   │   │   │   └── view_alert_spec.js
│   │   │   ├── dashboard/
│   │   │   │   ├── dashboard_list.js
│   │   │   │   ├── dashboard_spec.js
│   │   │   │   ├── dashboard_tags_spec.js
│   │   │   │   ├── filters_spec.js
│   │   │   │   ├── grid_compliant_widgets_spec.js
│   │   │   │   ├── parameter_spec.js
│   │   │   │   ├── sharing_spec.js
│   │   │   │   ├── textbox_spec.js
│   │   │   │   └── widget_spec.js
│   │   │   ├── data-source/
│   │   │   │   ├── create_data_source_spec.js
│   │   │   │   └── edit_data_source_spec.js
│   │   │   ├── destination/
│   │   │   │   └── create_destination_spec.js
│   │   │   ├── embed/
│   │   │   │   └── share_embed_spec.js
│   │   │   ├── group/
│   │   │   │   ├── edit_group_spec.js
│   │   │   │   └── group_list_spec.js
│   │   │   ├── query/
│   │   │   │   ├── create_query_spec.js
│   │   │   │   ├── filters_spec.js
│   │   │   │   ├── parameter_spec.js
│   │   │   │   └── query_tags_spec.js
│   │   │   ├── query-snippets/
│   │   │   │   └── create_query_snippet_spec.js
│   │   │   ├── settings/
│   │   │   │   ├── organization_settings_spec.js
│   │   │   │   └── settings_tabs_spec.js
│   │   │   ├── user/
│   │   │   │   ├── create_user_spec.js
│   │   │   │   ├── edit_profile_spec.js
│   │   │   │   ├── login_spec.js
│   │   │   │   ├── logout_spec.js
│   │   │   │   └── user_list_spec.js
│   │   │   └── visualizations/
│   │   │       ├── box_plot_spec.js
│   │   │       ├── chart_spec.js
│   │   │       ├── choropleth_spec.js
│   │   │       ├── cohort_spec.js
│   │   │       ├── counter_spec.js
│   │   │       ├── edit_visualization_dialog_spec.js
│   │   │       ├── funnel_spec.js
│   │   │       ├── map_spec.js
│   │   │       ├── pivot_spec.js
│   │   │       ├── sankey_sunburst_spec.js
│   │   │       ├── table/
│   │   │       │   ├── .mocks/
│   │   │       │   │   ├── all-cell-types.js
│   │   │       │   │   ├── large-dataset.js
│   │   │       │   │   ├── multi-column-sort.js
│   │   │       │   │   └── search-in-data.js
│   │   │       │   └── table_spec.js
│   │   │       └── word_cloud_spec.js
│   │   ├── seed-data.js
│   │   ├── support/
│   │   │   ├── commands.js
│   │   │   ├── dashboard/
│   │   │   │   └── index.js
│   │   │   ├── index.js
│   │   │   ├── parameters.js
│   │   │   ├── redash-api/
│   │   │   │   └── index.js
│   │   │   ├── tags/
│   │   │   │   └── index.js
│   │   │   └── visualizations/
│   │   │       ├── chart.js
│   │   │       └── table.js
│   │   └── tsconfig.json
│   ├── prettier.config.js
│   └── tsconfig.json
├── codecov.yml
├── compose.yaml
├── cypress.config.js
├── manage.py
├── migrations/
│   ├── 0001_warning.py
│   ├── README
│   ├── alembic.ini
│   ├── env.py
│   ├── script.py.mako
│   └── versions/
│       ├── 0ec979123ba4_.py
│       ├── 0f740a081d20_inline_tags.py
│       ├── 1038c2174f5d_make_case_insensitive_hash_of_query_text.py
│       ├── 1655999df5e3_default_alert_selector.py
│       ├── 1daa601d3ae5_add_columns_for_disabled_users.py
│       ├── 5ec5c84ba61e_.py
│       ├── 640888ce445d_.py
│       ├── 65fc9ede4746_add_is_draft_status_to_queries_and_.py
│       ├── 6b5be7e0a0ef_.py
│       ├── 71477dadd6ef_favorites_unique_constraint.py
│       ├── 7205816877ec_change_type_of_json_fields_from_varchar_.py
│       ├── 73beceabb948_bring_back_null_schedule.py
│       ├── 7671dca4e604_.py
│       ├── 7ce5925f832b_create_sqlalchemy_searchable_expressions.py
│       ├── 89bc7873a3e0_fix_multiple_heads.py
│       ├── 969126bd800f_.py
│       ├── 98af61feea92_add_encrypted_options_to_data_sources.py
│       ├── 9e8c841d1a30_fix_hash.py
│       ├── a92d92aa678e_inline_tags.py
│       ├── d1eae8b9893e_.py
│       ├── d4c798575877_create_favorites.py
│       ├── d7d747033183_encrypt_alert_destinations.py
│       ├── db0aca1ebd32_12_column_dashboard_layout.py
│       ├── e5c7a4e2df4d_remove_query_tracker_keys.py
│       ├── e7004224f284_add_org_id_to_favorites.py
│       ├── e7f8a917aa8e_add_user_details_json_column.py
│       └── fd4fc850d7ea_.py
├── netlify.toml
├── package.json
├── pnpm-workspace.yaml
├── pyproject.toml
├── pytest.ini
├── redash/
│   ├── __init__.py
│   ├── app.py
│   ├── authentication/
│   │   ├── __init__.py
│   │   ├── account.py
│   │   ├── google_oauth.py
│   │   ├── jwt_auth.py
│   │   ├── ldap_auth.py
│   │   ├── org_resolving.py
│   │   ├── remote_user_auth.py
│   │   └── saml_auth.py
│   ├── cli/
│   │   ├── __init__.py
│   │   ├── data_sources.py
│   │   ├── database.py
│   │   ├── groups.py
│   │   ├── organization.py
│   │   ├── queries.py
│   │   ├── rq.py
│   │   └── users.py
│   ├── destinations/
│   │   ├── __init__.py
│   │   ├── asana.py
│   │   ├── chatwork.py
│   │   ├── datadog.py
│   │   ├── discord.py
│   │   ├── email.py
│   │   ├── hangoutschat.py
│   │   ├── mattermost.py
│   │   ├── microsoft_teams_webhook.py
│   │   ├── pagerduty.py
│   │   ├── slack.py
│   │   ├── webex.py
│   │   └── webhook.py
│   ├── handlers/
│   │   ├── __init__.py
│   │   ├── admin.py
│   │   ├── alerts.py
│   │   ├── api.py
│   │   ├── authentication.py
│   │   ├── base.py
│   │   ├── dashboards.py
│   │   ├── data_sources.py
│   │   ├── databricks.py
│   │   ├── destinations.py
│   │   ├── embed.py
│   │   ├── events.py
│   │   ├── favorites.py
│   │   ├── groups.py
│   │   ├── organization.py
│   │   ├── permissions.py
│   │   ├── queries.py
│   │   ├── query_results.py
│   │   ├── query_snippets.py
│   │   ├── settings.py
│   │   ├── setup.py
│   │   ├── static.py
│   │   ├── users.py
│   │   ├── visualizations.py
│   │   ├── webpack.py
│   │   └── widgets.py
│   ├── metrics/
│   │   ├── __init__.py
│   │   ├── database.py
│   │   └── request.py
│   ├── models/
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── changes.py
│   │   ├── mixins.py
│   │   ├── organizations.py
│   │   ├── parameterized_query.py
│   │   ├── types.py
│   │   └── users.py
│   ├── monitor.py
│   ├── permissions.py
│   ├── query_runner/
│   │   ├── __init__.py
│   │   ├── amazon_elasticsearch.py
│   │   ├── arango.py
│   │   ├── athena.py
│   │   ├── axibase_tsd.py
│   │   ├── azure_kusto.py
│   │   ├── big_query.py
│   │   ├── big_query_gce.py
│   │   ├── cass.py
│   │   ├── clickhouse.py
│   │   ├── cloudwatch.py
│   │   ├── cloudwatch_insights.py
│   │   ├── corporate_memory.py
│   │   ├── couchbase.py
│   │   ├── csv.py
│   │   ├── databend.py
│   │   ├── databricks.py
│   │   ├── db2.py
│   │   ├── dgraph.py
│   │   ├── drill.py
│   │   ├── druid.py
│   │   ├── duckdb.py
│   │   ├── e6data.py
│   │   ├── elasticsearch.py
│   │   ├── elasticsearch2.py
│   │   ├── exasol.py
│   │   ├── excel.py
│   │   ├── files/
│   │   │   ├── rds-combined-ca-bundle.pem
│   │   │   └── redshift-ca-bundle.crt
│   │   ├── google_analytics.py
│   │   ├── google_analytics4.py
│   │   ├── google_search_console.py
│   │   ├── google_spanner.py
│   │   ├── google_spreadsheets.py
│   │   ├── graphite.py
│   │   ├── hive_ds.py
│   │   ├── ignite.py
│   │   ├── impala_ds.py
│   │   ├── influx_db.py
│   │   ├── influx_db_v2.py
│   │   ├── jql.py
│   │   ├── json_ds.py
│   │   ├── kylin.py
│   │   ├── memsql_ds.py
│   │   ├── mongodb.py
│   │   ├── mssql.py
│   │   ├── mssql_odbc.py
│   │   ├── mysql.py
│   │   ├── nz.py
│   │   ├── oracle.py
│   │   ├── pg.py
│   │   ├── phoenix.py
│   │   ├── pinot.py
│   │   ├── presto.py
│   │   ├── prometheus.py
│   │   ├── python.py
│   │   ├── query_results.py
│   │   ├── risingwave.py
│   │   ├── rockset.py
│   │   ├── salesforce.py
│   │   ├── script.py
│   │   ├── snowflake.py
│   │   ├── sparql_endpoint.py
│   │   ├── sqlite.py
│   │   ├── tinybird.py
│   │   ├── treasuredata.py
│   │   ├── trino.py
│   │   ├── uptycs.py
│   │   ├── url.py
│   │   ├── vertica.py
│   │   ├── yandex_disk.py
│   │   └── yandex_metrica.py
│   ├── security.py
│   ├── serializers/
│   │   ├── __init__.py
│   │   └── query_result.py
│   ├── settings/
│   │   ├── __init__.py
│   │   ├── dynamic_settings.py
│   │   ├── helpers.py
│   │   └── organization.py
│   ├── tasks/
│   │   ├── __init__.py
│   │   ├── alerts.py
│   │   ├── databricks.py
│   │   ├── failure_report.py
│   │   ├── general.py
│   │   ├── queries/
│   │   │   ├── __init__.py
│   │   │   ├── execution.py
│   │   │   └── maintenance.py
│   │   ├── schedule.py
│   │   └── worker.py
│   ├── templates/
│   │   ├── _includes/
│   │   │   ├── signed_out_tail.html
│   │   │   └── tail.html
│   │   ├── emails/
│   │   │   ├── alert.html
│   │   │   ├── failures.html
│   │   │   ├── failures.txt
│   │   │   ├── invite.html
│   │   │   ├── invite.txt
│   │   │   ├── layout.html
│   │   │   ├── reset.html
│   │   │   ├── reset.txt
│   │   │   ├── reset_disabled.html
│   │   │   ├── reset_disabled.txt
│   │   │   ├── verify.html
│   │   │   └── verify.txt
│   │   ├── error.html
│   │   ├── forgot.html
│   │   ├── invite.html
│   │   ├── layouts/
│   │   │   └── signed_out.html
│   │   ├── login.html
│   │   ├── reset.html
│   │   ├── setup.html
│   │   └── verify.html
│   ├── utils/
│   │   ├── __init__.py
│   │   ├── configuration.py
│   │   ├── human_time.py
│   │   ├── pandas.py
│   │   ├── query_order.py
│   │   ├── requests_session.py
│   │   └── sentry.py
│   ├── version_check.py
│   ├── worker.py
│   └── wsgi.py
├── scripts/
│   └── README.md
├── setup/
│   └── README.md
├── tests/
│   ├── __init__.py
│   ├── destinations/
│   │   └── test_webhook.py
│   ├── factories.py
│   ├── handlers/
│   │   ├── __init__.py
│   │   ├── test_alerts.py
│   │   ├── test_authentication.py
│   │   ├── test_dashboards.py
│   │   ├── test_data_sources.py
│   │   ├── test_destinations.py
│   │   ├── test_embed.py
│   │   ├── test_favorites.py
│   │   ├── test_groups.py
│   │   ├── test_order_results.py
│   │   ├── test_paginate.py
│   │   ├── test_permissions.py
│   │   ├── test_queries.py
│   │   ├── test_query_results.py
│   │   ├── test_query_snippets.py
│   │   ├── test_settings.py
│   │   ├── test_users.py
│   │   ├── test_visualizations.py
│   │   └── test_widgets.py
│   ├── metrics/
│   │   ├── __init__.py
│   │   ├── test_database.py
│   │   └── test_request.py
│   ├── models/
│   │   ├── __init__.py
│   │   ├── test_alerts.py
│   │   ├── test_api_keys.py
│   │   ├── test_changes.py
│   │   ├── test_dashboards.py
│   │   ├── test_data_sources.py
│   │   ├── test_parameterized_query.py
│   │   ├── test_permissions.py
│   │   ├── test_queries.py
│   │   ├── test_query_results.py
│   │   └── test_users.py
│   ├── query_runner/
│   │   ├── __init__.py
│   │   ├── test_athena.py
│   │   ├── test_azure_kusto.py
│   │   ├── test_basequeryrunner.py
│   │   ├── test_basesql_queryrunner.py
│   │   ├── test_bigquery.py
│   │   ├── test_cass.py
│   │   ├── test_clickhouse.py
│   │   ├── test_databricks.py
│   │   ├── test_drill.py
│   │   ├── test_duckdb.py
│   │   ├── test_e6data.py
│   │   ├── test_elasticsearch2.py
│   │   ├── test_google_analytics4.py
│   │   ├── test_google_search_console.py
│   │   ├── test_google_spreadsheets.py
│   │   ├── test_http.py
│   │   ├── test_ignite.py
│   │   ├── test_influx_db.py
│   │   ├── test_influx_db_v2.py
│   │   ├── test_jql.py
│   │   ├── test_json_ds.py
│   │   ├── test_mongodb.py
│   │   ├── test_oracle.py
│   │   ├── test_pg.py
│   │   ├── test_prometheus.py
│   │   ├── test_python.py
│   │   ├── test_query_results.py
│   │   ├── test_script.py
│   │   ├── test_tinybird.py
│   │   ├── test_trino.py
│   │   ├── test_utils.py
│   │   ├── test_yandex_disk.py
│   │   └── test_yandex_metrica.py
│   ├── serializers/
│   │   ├── __init__.py
│   │   └── test_query_results.py
│   ├── tasks/
│   │   ├── __init__.py
│   │   ├── test_alerts.py
│   │   ├── test_empty_schedule.py
│   │   ├── test_failure_report.py
│   │   ├── test_queries.py
│   │   ├── test_refresh_queries.py
│   │   ├── test_refresh_schemas.py
│   │   ├── test_schedule.py
│   │   └── test_worker.py
│   ├── test_authentication.py
│   ├── test_cli.py
│   ├── test_configuration.py
│   ├── test_handlers.py
│   ├── test_migrations.py
│   ├── test_models.py
│   ├── test_monitor.py
│   ├── test_permissions.py
│   ├── test_utils.py
│   └── utils/
│       ├── __init__.py
│       └── test_json_dumps.py
├── viz-lib/
│   ├── .babelrc
│   ├── .gitignore
│   ├── CHANGELOG.md
│   ├── README.md
│   ├── __tests__/
│   │   ├── enzyme_setup.js
│   │   └── mocks.js
│   ├── package.json
│   ├── prettier.config.js
│   ├── src/
│   │   ├── components/
│   │   │   ├── ColorPicker/
│   │   │   │   ├── Input.tsx
│   │   │   │   ├── Label.tsx
│   │   │   │   ├── Swatch.tsx
│   │   │   │   ├── index.less
│   │   │   │   ├── index.tsx
│   │   │   │   ├── input.less
│   │   │   │   ├── label.less
│   │   │   │   ├── swatch.less
│   │   │   │   └── utils.ts
│   │   │   ├── ErrorBoundary.tsx
│   │   │   ├── HtmlContent.tsx
│   │   │   ├── TextAlignmentSelect/
│   │   │   │   ├── index.less
│   │   │   │   └── index.tsx
│   │   │   ├── json-view-interactive/
│   │   │   │   ├── JsonViewInteractive.tsx
│   │   │   │   └── json-view-interactive.less
│   │   │   ├── sortable/
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.less
│   │   │   └── visualizations/
│   │   │       └── editor/
│   │   │           ├── ContextHelp.tsx
│   │   │           ├── Section.less
│   │   │           ├── Section.tsx
│   │   │           ├── Switch.less
│   │   │           ├── Switch.tsx
│   │   │           ├── TextArea.less
│   │   │           ├── TextArea.tsx
│   │   │           ├── context-help.less
│   │   │           ├── control-label.less
│   │   │           ├── createTabbedEditor.tsx
│   │   │           ├── index.ts
│   │   │           └── withControlLabel.tsx
│   │   ├── index.ts
│   │   ├── lib/
│   │   │   ├── chooseTextColorForBackground.ts
│   │   │   ├── hooks/
│   │   │   │   └── useMemoWithDeepCompare.ts
│   │   │   ├── referenceCountingCache.ts
│   │   │   ├── utils.ts
│   │   │   └── value-format.tsx
│   │   ├── services/
│   │   │   ├── resizeObserver.ts
│   │   │   └── sanitize.ts
│   │   └── visualizations/
│   │       ├── ColorPalette.ts
│   │       ├── Editor.tsx
│   │       ├── Renderer.tsx
│   │       ├── box-plot/
│   │       │   ├── Editor.tsx
│   │       │   ├── Renderer.tsx
│   │       │   ├── d3box.ts
│   │       │   ├── index.ts
│   │       │   └── renderer.less
│   │       ├── chart/
│   │       │   ├── Editor/
│   │       │   │   ├── AxisSettings.tsx
│   │       │   │   ├── ChartTypeSelect.tsx
│   │       │   │   ├── ColorsSettings.test.tsx
│   │       │   │   ├── ColorsSettings.tsx
│   │       │   │   ├── ColumnMappingSelect.tsx
│   │       │   │   ├── CustomChartSettings.tsx
│   │       │   │   ├── DataLabelsSettings.test.tsx
│   │       │   │   ├── DataLabelsSettings.tsx
│   │       │   │   ├── DefaultColorsSettings.tsx
│   │       │   │   ├── GeneralSettings.test.tsx
│   │       │   │   ├── GeneralSettings.tsx
│   │       │   │   ├── HeatmapColorsSettings.tsx
│   │       │   │   ├── PieColorsSettings.tsx
│   │       │   │   ├── SeriesSettings.test.tsx
│   │       │   │   ├── SeriesSettings.tsx
│   │       │   │   ├── XAxisSettings.test.tsx
│   │       │   │   ├── XAxisSettings.tsx
│   │       │   │   ├── YAxisSettings.test.tsx
│   │       │   │   ├── YAxisSettings.tsx
│   │       │   │   ├── __snapshots__/
│   │       │   │   │   ├── ColorsSettings.test.tsx.snap
│   │       │   │   │   ├── DataLabelsSettings.test.tsx.snap
│   │       │   │   │   ├── GeneralSettings.test.tsx.snap
│   │       │   │   │   ├── SeriesSettings.test.tsx.snap
│   │       │   │   │   ├── XAxisSettings.test.tsx.snap
│   │       │   │   │   └── YAxisSettings.test.tsx.snap
│   │       │   │   ├── editor.less
│   │       │   │   ├── index.test.tsx
│   │       │   │   └── index.tsx
│   │       │   ├── Renderer/
│   │       │   │   ├── CustomPlotlyChart.tsx
│   │       │   │   ├── PlotlyChart.tsx
│   │       │   │   ├── index.tsx
│   │       │   │   ├── initChart.ts
│   │       │   │   └── renderer.less
│   │       │   ├── fixtures/
│   │       │   │   └── getChartData/
│   │       │   │       ├── multiple-series-grouped.json
│   │       │   │       ├── multiple-series-multiple-y.json
│   │       │   │       ├── multiple-series-sorted.json
│   │       │   │       └── single-series.json
│   │       │   ├── getChartData.test.ts
│   │       │   ├── getChartData.ts
│   │       │   ├── getOptions.ts
│   │       │   ├── index.ts
│   │       │   └── plotly/
│   │       │       ├── customChartUtils.ts
│   │       │       ├── fixtures/
│   │       │       │   ├── prepareData/
│   │       │       │   │   ├── bar/
│   │       │       │   │   │   ├── default.json
│   │       │       │   │   │   ├── normalized.json
│   │       │       │   │   │   └── stacked.json
│   │       │       │   │   ├── box/
│   │       │       │   │   │   ├── default.json
│   │       │       │   │   │   └── with-points.json
│   │       │       │   │   ├── bubble/
│   │       │       │   │   │   └── default.json
│   │       │       │   │   ├── heatmap/
│   │       │       │   │   │   ├── default.json
│   │       │       │   │   │   ├── reversed.json
│   │       │       │   │   │   ├── sorted-reversed.json
│   │       │       │   │   │   ├── sorted.json
│   │       │       │   │   │   └── with-labels.json
│   │       │       │   │   ├── line-area/
│   │       │       │   │   │   ├── default.json
│   │       │       │   │   │   ├── keep-missing-values.json
│   │       │       │   │   │   ├── missing-values-0.json
│   │       │       │   │   │   ├── normalized-stacked.json
│   │       │       │   │   │   ├── normalized.json
│   │       │       │   │   │   └── stacked.json
│   │       │       │   │   ├── pie/
│   │       │       │   │   │   ├── custom-tooltip.json
│   │       │       │   │   │   ├── default.json
│   │       │       │   │   │   ├── without-labels.json
│   │       │       │   │   │   └── without-x.json
│   │       │       │   │   └── scatter/
│   │       │       │   │       ├── default.json
│   │       │       │   │       └── without-labels.json
│   │       │       │   └── prepareLayout/
│   │       │       │       ├── box-single-axis.json
│   │       │       │       ├── box-with-second-axis.json
│   │       │       │       ├── default-single-axis.json
│   │       │       │       ├── default-with-second-axis.json
│   │       │       │       ├── default-with-stacking.json
│   │       │       │       ├── default-without-legend.json
│   │       │       │       ├── pie-multiple-series.json
│   │       │       │       ├── pie-without-annotations.json
│   │       │       │       └── pie.json
│   │       │       ├── index.ts
│   │       │       ├── locales.ts
│   │       │       ├── prepareData.test.ts
│   │       │       ├── prepareData.ts
│   │       │       ├── prepareDefaultData.ts
│   │       │       ├── prepareHeatmapData.ts
│   │       │       ├── prepareLayout.test.ts
│   │       │       ├── prepareLayout.ts
│   │       │       ├── preparePieData.ts
│   │       │       ├── updateAxes.ts
│   │       │       ├── updateChartSize.ts
│   │       │       ├── updateData.ts
│   │       │       └── utils.ts
│   │       ├── choropleth/
│   │       │   ├── ColorPalette.ts
│   │       │   ├── Editor/
│   │       │   │   ├── BoundsSettings.tsx
│   │       │   │   ├── ColorsSettings.tsx
│   │       │   │   ├── FormatSettings.tsx
│   │       │   │   ├── GeneralSettings.tsx
│   │       │   │   ├── index.ts
│   │       │   │   └── utils.ts
│   │       │   ├── Renderer/
│   │       │   │   ├── Legend.tsx
│   │       │   │   ├── index.tsx
│   │       │   │   ├── initChoropleth.tsx
│   │       │   │   ├── renderer.less
│   │       │   │   └── utils.ts
│   │       │   ├── getOptions.ts
│   │       │   ├── hooks/
│   │       │   │   └── useLoadGeoJson.ts
│   │       │   ├── index.ts
│   │       │   └── maps/
│   │       │       ├── convert-projection.ts
│   │       │       ├── countries.geo.json
│   │       │       ├── japan.prefectures.geo.json
│   │       │       ├── usa-albers.geo.json
│   │       │       └── usa.geo.json
│   │       ├── cohort/
│   │       │   ├── Cornelius.tsx
│   │       │   ├── Editor/
│   │       │   │   ├── AppearanceSettings.tsx
│   │       │   │   ├── ColorsSettings.tsx
│   │       │   │   ├── ColumnsSettings.tsx
│   │       │   │   ├── OptionsSettings.tsx
│   │       │   │   └── index.ts
│   │       │   ├── Renderer.tsx
│   │       │   ├── cornelius.less
│   │       │   ├── getOptions.ts
│   │       │   ├── index.ts
│   │       │   ├── prepareData.ts
│   │       │   └── renderer.less
│   │       ├── counter/
│   │       │   ├── Editor/
│   │       │   │   ├── FormatSettings.tsx
│   │       │   │   ├── GeneralSettings.tsx
│   │       │   │   └── index.ts
│   │       │   ├── Renderer.tsx
│   │       │   ├── index.ts
│   │       │   ├── render.less
│   │       │   ├── utils.test.ts
│   │       │   └── utils.ts
│   │       ├── details/
│   │       │   ├── Editor/
│   │       │   │   ├── ColumnEditor.tsx
│   │       │   │   ├── ColumnsSettings.test.tsx
│   │       │   │   ├── ColumnsSettings.tsx
│   │       │   │   ├── __snapshots__/
│   │       │   │   │   └── ColumnsSettings.test.tsx.snap
│   │       │   │   ├── editor.less
│   │       │   │   └── index.tsx
│   │       │   ├── Renderer.test.tsx
│   │       │   ├── Renderer.tsx
│   │       │   ├── details.less
│   │       │   ├── getOptions.test.ts
│   │       │   ├── getOptions.ts
│   │       │   └── index.ts
│   │       ├── funnel/
│   │       │   ├── Editor/
│   │       │   │   ├── AppearanceSettings.tsx
│   │       │   │   ├── GeneralSettings.tsx
│   │       │   │   └── index.ts
│   │       │   ├── Renderer/
│   │       │   │   ├── FunnelBar.tsx
│   │       │   │   ├── funnel-bar.less
│   │       │   │   ├── index.less
│   │       │   │   ├── index.tsx
│   │       │   │   └── prepareData.ts
│   │       │   ├── getOptions.ts
│   │       │   └── index.ts
│   │       ├── index.ts
│   │       ├── map/
│   │       │   ├── Editor/
│   │       │   │   ├── FormatSettings.tsx
│   │       │   │   ├── GeneralSettings.tsx
│   │       │   │   ├── GroupsSettings.tsx
│   │       │   │   ├── StyleSettings.tsx
│   │       │   │   └── index.ts
│   │       │   ├── Renderer.tsx
│   │       │   ├── getOptions.ts
│   │       │   ├── index.ts
│   │       │   ├── initMap.ts
│   │       │   └── prepareData.ts
│   │       ├── pivot/
│   │       │   ├── Editor.tsx
│   │       │   ├── Renderer.tsx
│   │       │   ├── index.ts
│   │       │   └── renderer.less
│   │       ├── prop-types.ts
│   │       ├── registeredVisualizations.ts
│   │       ├── sankey/
│   │       │   ├── Editor.tsx
│   │       │   ├── Renderer.tsx
│   │       │   ├── d3sankey.ts
│   │       │   ├── index.ts
│   │       │   ├── initSankey.ts
│   │       │   └── renderer.less
│   │       ├── shared/
│   │       │   ├── columnUtils.ts
│   │       │   ├── columns/
│   │       │   │   ├── __snapshots__/
│   │       │   │   │   ├── boolean.test.tsx.snap
│   │       │   │   │   ├── datetime.test.tsx.snap
│   │       │   │   │   ├── image.test.tsx.snap
│   │       │   │   │   ├── link.test.tsx.snap
│   │       │   │   │   ├── number.test.tsx.snap
│   │       │   │   │   └── text.test.tsx.snap
│   │       │   │   ├── boolean.test.tsx
│   │       │   │   ├── boolean.tsx
│   │       │   │   ├── datetime.test.tsx
│   │       │   │   ├── datetime.tsx
│   │       │   │   ├── image.test.tsx
│   │       │   │   ├── image.tsx
│   │       │   │   ├── index.ts
│   │       │   │   ├── json.tsx
│   │       │   │   ├── link.test.tsx
│   │       │   │   ├── link.tsx
│   │       │   │   ├── number.test.tsx
│   │       │   │   ├── number.tsx
│   │       │   │   ├── text.test.tsx
│   │       │   │   └── text.tsx
│   │       │   └── components/
│   │       │       ├── ColumnEditor.test.tsx
│   │       │       ├── ColumnEditor.tsx
│   │       │       └── ColumnsSettings.tsx
│   │       ├── sunburst/
│   │       │   ├── Editor.tsx
│   │       │   ├── Renderer.tsx
│   │       │   ├── index.ts
│   │       │   ├── initSunburst.ts
│   │       │   └── renderer.less
│   │       ├── table/
│   │       │   ├── Editor/
│   │       │   │   ├── ColumnEditor.tsx
│   │       │   │   ├── ColumnsSettings.test.tsx
│   │       │   │   ├── ColumnsSettings.tsx
│   │       │   │   ├── GridSettings.test.tsx
│   │       │   │   ├── GridSettings.tsx
│   │       │   │   ├── __snapshots__/
│   │       │   │   │   ├── ColumnsSettings.test.tsx.snap
│   │       │   │   │   └── GridSettings.test.tsx.snap
│   │       │   │   ├── editor.less
│   │       │   │   └── index.tsx
│   │       │   ├── Renderer.tsx
│   │       │   ├── getOptions.ts
│   │       │   ├── index.ts
│   │       │   ├── renderer.less
│   │       │   └── utils.tsx
│   │       ├── variables.less
│   │       ├── visualizationsSettings.tsx
│   │       └── word-cloud/
│   │           ├── Editor.tsx
│   │           ├── Renderer.tsx
│   │           ├── index.ts
│   │           └── renderer.less
│   ├── tsconfig.json
│   └── webpack.config.js
├── webpack.config.js
└── worker.conf

================================================
FILE CONTENTS
================================================

================================================
FILE: .ci/Dockerfile.cypress
================================================
FROM cypress/browsers:node-24.14.0-chrome-145.0.7632.116-1-ff-148.0-edge-145.0.3800.70-1

ENV APP /usr/src/app
WORKDIR $APP

COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc $APP/
COPY viz-lib $APP/viz-lib
RUN npm install -g pnpm@10.30.3 && pnpm install --frozen-lockfile > /dev/null

COPY . $APP

RUN ./node_modules/.bin/cypress verify


================================================
FILE: .ci/compose.ci.yaml
================================================
services:
  redash:
    build: ../
    command: manage version
    depends_on:
      - postgres
      - redis
    ports:
      - "5000:5000"
    environment:
      PYTHONUNBUFFERED: 0
      REDASH_LOG_LEVEL: "INFO"
      REDASH_REDIS_URL: "redis://redis:6379/0"
      POSTGRES_PASSWORD: "FmTKs5vX52ufKR1rd8tn4MoSP7zvCJwb"
      REDASH_DATABASE_URL: "postgresql://postgres:FmTKs5vX52ufKR1rd8tn4MoSP7zvCJwb@postgres/postgres"
      REDASH_COOKIE_SECRET: "2H9gNG9obnAQ9qnR9BDTQUph6CbXKCzF"
  redis:
    image: redis:7-alpine
    restart: unless-stopped
  postgres:
    image: postgres:18-alpine
    command: "postgres -c fsync=off -c full_page_writes=off -c synchronous_commit=OFF"
    restart: unless-stopped
    environment:
      POSTGRES_HOST_AUTH_METHOD: "trust"


================================================
FILE: .ci/compose.cypress.yaml
================================================
x-redash-service: &redash-service
  build:
    context: ../
    args:
      install_groups: "main"
      code_coverage: ${CODE_COVERAGE}
x-redash-environment: &redash-environment
  REDASH_LOG_LEVEL: "INFO"
  REDASH_REDIS_URL: "redis://redis:6379/0"
  POSTGRES_PASSWORD: "FmTKs5vX52ufKR1rd8tn4MoSP7zvCJwb"
  REDASH_DATABASE_URL: "postgresql://postgres:FmTKs5vX52ufKR1rd8tn4MoSP7zvCJwb@postgres/postgres"
  REDASH_RATELIMIT_ENABLED: "false"
  REDASH_ENFORCE_CSRF: "true"
  REDASH_COOKIE_SECRET: "2H9gNG9obnAQ9qnR9BDTQUph6CbXKCzF"
services:
  server:
    <<: *redash-service
    command: server
    depends_on:
      - postgres
      - redis
    ports:
      - "5000:5000"
    environment:
      <<: *redash-environment
      PYTHONUNBUFFERED: 0
  scheduler:
    <<: *redash-service
    command: scheduler
    depends_on:
      - server
    environment:
      <<: *redash-environment
  worker:
    <<: *redash-service
    command: worker
    depends_on:
      - server
    environment:
      <<: *redash-environment
      PYTHONUNBUFFERED: 0
  cypress:
    ipc: host
    build:
      context: ../
      dockerfile: .ci/Dockerfile.cypress
    depends_on:
      - server
      - worker
      - scheduler
    environment:
      CYPRESS_baseUrl: "http://server:5000"
      CYPRESS_coverage: ${CODE_COVERAGE}
      PERCY_TOKEN: ${PERCY_TOKEN}
      PERCY_BRANCH: ${CIRCLE_BRANCH}
      PERCY_COMMIT: ${CIRCLE_SHA1}
      PERCY_PULL_REQUEST: ${CIRCLE_PR_NUMBER}
      COMMIT_INFO_BRANCH: ${CIRCLE_BRANCH}
      COMMIT_INFO_MESSAGE: ${COMMIT_INFO_MESSAGE}
      COMMIT_INFO_AUTHOR: ${CIRCLE_USERNAME}
      COMMIT_INFO_SHA: ${CIRCLE_SHA1}
      COMMIT_INFO_REMOTE: ${CIRCLE_REPOSITORY_URL}
      CYPRESS_PROJECT_ID: ${CYPRESS_PROJECT_ID}
      CYPRESS_RECORD_KEY: ${CYPRESS_RECORD_KEY}
  redis:
    image: redis:7-alpine
    restart: unless-stopped
  postgres:
    image: postgres:18-alpine
    command: "postgres -c fsync=off -c full_page_writes=off -c synchronous_commit=OFF"
    restart: unless-stopped
    environment:
      POSTGRES_HOST_AUTH_METHOD: "trust"


================================================
FILE: .ci/docker_build
================================================
#!/bin/bash

# This script only needs to run on the main Redash repo

if [ "${GITHUB_REPOSITORY}" != "getredash/redash" ]; then
	echo "Skipping image build for Docker Hub, as this isn't the main Redash repository"
	exit 0
fi

if [ "${GITHUB_REF_NAME}" != "master" ] && [ "${GITHUB_REF_NAME}" != "preview-image" ]; then
	echo "Skipping image build for Docker Hub, as this isn't the 'master' nor 'preview-image' branch"
	exit 0
fi

if [ "x${DOCKER_USER}" = "x" ] || [ "x${DOCKER_PASS}" = "x" ]; then
	echo "Skipping image build for Docker Hub, as the login details aren't available"
	exit 0
fi

set -e
VERSION=$(jq -r .version package.json)
VERSION_TAG="$VERSION.b${GITHUB_RUN_ID}.${GITHUB_RUN_NUMBER}"

export DOCKER_BUILDKIT=1
export COMPOSE_DOCKER_CLI_BUILD=1

docker login -u "${DOCKER_USER}" -p "${DOCKER_PASS}"

DOCKERHUB_REPO="redash/redash"
DOCKER_TAGS="-t redash/redash:preview -t redash/preview:${VERSION_TAG}"

# Build the docker container
docker build --build-arg install_groups="main,all_ds,dev" ${DOCKER_TAGS} .

# Push the container to the preview build locations
docker push "${DOCKERHUB_REPO}:preview"
docker push "redash/preview:${VERSION_TAG}"

echo "Built: ${VERSION_TAG}"


================================================
FILE: .ci/pack
================================================
#!/bin/bash
NAME=redash
VERSION=$(jq -r .version package.json)
FULL_VERSION=$VERSION+b$CIRCLE_BUILD_NUM
FILENAME=$NAME.$FULL_VERSION.tar.gz

mkdir -p /tmp/artifacts/

tar -zcv -f /tmp/artifacts/$FILENAME --exclude=".git" --exclude="optipng*" --exclude="cypress" --exclude="*.pyc" --exclude="*.pyo" --exclude="venv" *


================================================
FILE: .ci/update_version
================================================
#!/bin/bash
VERSION=$(jq -r .version package.json)
FULL_VERSION=${VERSION}+b${GITHUB_RUN_ID}.${GITHUB_RUN_NUMBER}

sed -ri "s/^__version__ = '([A-Za-z0-9.-]*)'/__version__ = '${FULL_VERSION}'/" redash/__init__.py
sed -i "s/dev/${GITHUB_SHA}/" client/app/version.json


================================================
FILE: .coveragerc
================================================
[run]
branch = True
source = redash

[report]
omit =
    */settings.py
    */python?.?/*
show_missing = True


================================================
FILE: .dockerignore
================================================
client/.tmp/
node_modules/
viz-lib/node_modules/
.tmp/
.venv/
venv/
.git/
/.codeclimate.yml
/.coverage
/coverage.xml
/.circleci/
/.github/
/netlify.toml
/setup/


================================================
FILE: .editorconfig
================================================
root = true

[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.py]
indent_style = space
indent_size = 4

[*.{js,jsx,css,less,html}]
indent_style = space
indent_size = 2


================================================
FILE: .github/ISSUE_TEMPLATE/---bug_report.md
================================================
---
name: "\U0001F41B Bug report"
about: Report reproducible software issues so we can improve
---

<!--

We use GitHub only for bug reports 🐛

Anything else should be a discussion: https://github.com/getredash/redash/discussions/ 👫

🚨For support, help & questions use https://github.com/getredash/redash/discussions/categories/q-a
💡For feature requests & ideas use https://github.com/getredash/redash/discussions/categories/ideas

**Found a security vulnerability?** Please email security@redash.io to report any security vulnerabilities. We will acknowledge receipt of your vulnerability and strive to send you regular updates about our progress. If you're curious about the status of your disclosure please feel free to email us again. If you want to encrypt your disclosure email, you can use this PGP key.

-->

### Issue Summary

A summary of the issue and the browser/OS environment in which it occurs.

### Steps to Reproduce

1. This is the first step
2. This is the second step, etc.

Any other info e.g. Why do you consider this to be a bug? What did you expect to happen instead?

### Technical details:

* Redash Version:
* Browser/OS:
* How did you install Redash:


================================================
FILE: .github/ISSUE_TEMPLATE/--anything_else.md
================================================
---
name: "\U0001F4A1Anything else"
about: "For help, support, features & ideas - please use Discussions \U0001F46B "
labels: "Support Question"
---

We use GitHub only for bug reports 🐛

Anything else should be a discussion: https://github.com/getredash/redash/discussions/ 👫

🚨For support, help & questions use https://github.com/getredash/redash/discussions/categories/q-a
💡For feature requests & ideas use https://github.com/getredash/redash/discussions/categories/ideas

Alternatively, check out these resources below. Thanks! 😁.

- [Discussions](https://github.com/getredash/redash/discussions/)
- [Knowledge Base](https://redash.io/help)


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
## What type of PR is this? 
<!-- Check all that apply, delete what doesn't apply. -->

- [ ] Refactor
- [ ] Feature
- [ ] Bug Fix
- [ ] New Query Runner (Data Source) 
- [ ] New Alert Destination
- [ ] Other

## Description
<!-- In case of adding / modifying a query runner, please specify which version(s) you expect are compatible. -->

## How is this tested?

- [ ] Unit tests (pytest, jest)
- [ ] E2E Tests (Cypress)
- [ ] Manually
- [ ] N/A

<!-- If Manually, please describe. -->

## Related Tickets & Documents
<!-- If applicable, please include a link to your documentation PR against getredash/website -->

## Mobile & Desktop Screenshots/Recordings (if there are UI changes)


================================================
FILE: .github/config.yml
================================================
# https://github.com/behaviorbot/request-info?installation_id=189571
requestInfoLabelToAdd: needs-more-info
requestInfoReplyComment: >
  We would appreciate it if you could provide us with more info about this issue/pr!



================================================
FILE: .github/weekly-digest.yml
================================================
# Configuration for weekly-digest - https://github.com/apps/weekly-digest
publishDay: mon
canPublishIssues: true
canPublishPullRequests: true
canPublishContributors: true
canPublishStargazers: true
canPublishCommits: true


================================================
FILE: .github/workflows/ci.yml
================================================
name: Tests
on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - master
env:
  NODE_VERSION: 24
  PNPM_VERSION: 10.30.3
jobs:
  backend-lint:
    runs-on: ubuntu-22.04
    steps:
      - if: github.event.pull_request.mergeable == 'false'
        name: Exit if PR is not mergeable
        run: exit 1
      - uses: actions/checkout@v4
        with:
          fetch-depth: 1
          ref: ${{ github.event.pull_request.head.sha }}
      - uses: actions/setup-python@v5
        with:
          python-version: '3.13'
      - run: python -m pip install black==23.1.0 ruff==0.0.287
      - run: ruff check .
      - run: black --check .

  backend-unit-tests:
    runs-on: ubuntu-22.04
    needs: backend-lint
    env:
      COMPOSE_FILE: .ci/compose.ci.yaml
      COMPOSE_PROJECT_NAME: redash
      COMPOSE_DOCKER_CLI_BUILD: 1
      DOCKER_BUILDKIT: 1
    steps:
      - if: github.event.pull_request.mergeable == 'false'
        name: Exit if PR is not mergeable
        run: exit 1
      - uses: actions/checkout@v4
        with:
          fetch-depth: 1
          ref: ${{ github.event.pull_request.head.sha }}
      - name: Build Docker Images
        run: |
          set -x
          docker compose build --build-arg install_groups="main,all_ds,dev" --build-arg skip_frontend_build=true
          docker compose up -d
          sleep 10
      - name: Create Test Database
        run: docker compose -p redash run --rm postgres psql -h postgres -U postgres -c "create database tests;"
      - name: List Enabled Query Runners
        run: docker compose -p redash run --rm redash manage ds list_types
      - name: Run Tests
        run: docker compose -p redash run --name tests redash tests --junitxml=junit.xml --cov-report=xml --cov=redash --cov-config=.coveragerc tests/
      - name: Copy Test Results
        run: |
          mkdir -p /tmp/test-results/unit-tests
          docker cp tests:/app/coverage.xml ./coverage.xml
          docker cp tests:/app/junit.xml /tmp/test-results/unit-tests/results.xml
      # - name: Upload coverage reports to Codecov
      #   uses: codecov/codecov-action@v3
      #   with:
      #     token: ${{ secrets.CODECOV_TOKEN }}
      - name: Store Test Results
        uses: actions/upload-artifact@v4
        with:
          name: backend-test-results
          path: /tmp/test-results
      - name: Store Coverage Results
        uses: actions/upload-artifact@v4
        with:
          name: coverage
          path: coverage.xml

  frontend-lint:
    runs-on: ubuntu-22.04
    steps:
      - if: github.event.pull_request.mergeable == 'false'
        name: Exit if PR is not mergeable
        run: exit 1
      - uses: actions/checkout@v4
        with:
          fetch-depth: 1
          ref: ${{ github.event.pull_request.head.sha }}
      - uses: pnpm/action-setup@v4
        with:
          version: ${{ env.PNPM_VERSION }}
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'pnpm'
      - name: Install Dependencies
        run: pnpm install --frozen-lockfile
      - name: Run Lint
        run: pnpm run lint:ci
      - name: Store Test Results
        uses: actions/upload-artifact@v4
        with:
          name: frontend-test-results
          path: /tmp/test-results

  frontend-unit-tests:
    runs-on: ubuntu-22.04
    needs: frontend-lint
    steps:
      - if: github.event.pull_request.mergeable == 'false'
        name: Exit if PR is not mergeable
        run: exit 1
      - uses: actions/checkout@v4
        with:
          fetch-depth: 1
          ref: ${{ github.event.pull_request.head.sha }}
      - uses: pnpm/action-setup@v4
        with:
          version: ${{ env.PNPM_VERSION }}
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'pnpm'
      - name: Install Dependencies
        run: pnpm install --frozen-lockfile
      - name: Run App Tests
        run: pnpm run test
      - name: Run Visualizations Tests
        run: pnpm --filter @redash/viz test
      - run: pnpm run lint

  frontend-e2e-tests:
    runs-on: ubuntu-22.04
    needs: frontend-lint
    env:
      COMPOSE_FILE: .ci/compose.cypress.yaml
      COMPOSE_PROJECT_NAME: cypress
      CYPRESS_INSTALL_BINARY: 0
      PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: 1
      # PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }}
      # CYPRESS_PROJECT_ID: ${{ secrets.CYPRESS_PROJECT_ID }}
      # CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
    steps:
      - if: github.event.pull_request.mergeable == 'false'
        name: Exit if PR is not mergeable
        run: exit 1
      - uses: actions/checkout@v4
        with:
          fetch-depth: 1
          ref: ${{ github.event.pull_request.head.sha }}
      - uses: pnpm/action-setup@v4
        with:
          version: ${{ env.PNPM_VERSION }}
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'pnpm'
      - name: Enable Code Coverage Report For Master Branch
        if: endsWith(github.ref, '/master')
        run: |
          echo "CODE_COVERAGE=true" >> "$GITHUB_ENV"
      - name: Install Dependencies
        run: pnpm install --frozen-lockfile
      - name: Setup Redash Server
        run: |
          set -x
          pnpm run cypress build
          pnpm run cypress start -- --skip-db-seed
          docker compose run cypress pnpm run cypress db-seed
      - name: Execute Cypress Tests
        run: pnpm run cypress run-ci
      - name: "Failure: output container logs to console"
        if: failure()
        run: docker compose logs
      - name: Copy Code Coverage Results
        run: docker cp cypress:/usr/src/app/coverage ./coverage || true
      - name: Store Coverage Results
        uses: actions/upload-artifact@v4
        with:
          name: coverage
          path: coverage


================================================
FILE: .github/workflows/periodic-snapshot.yml
================================================
name: Periodic Snapshot

on:
  schedule:
    - cron: '10 0 1 * *'  # 10 minutes after midnight on the first day of every month
  workflow_dispatch:
    inputs:
      bump:
        description: 'Bump the last digit of the version'
        required: false
        type: boolean
      version:
        description: 'Specific version to set'
        required: false
        default: ''

env:
  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

permissions:
  actions: write
  contents: write

jobs:
  bump-version-and-tag:
    runs-on: ubuntu-latest
    if: github.ref_name == github.event.repository.default_branch
    steps:
      - uses: actions/checkout@v4
        with:
          ssh-key: ${{ secrets.ACTION_PUSH_KEY }}

      - run: |
          git config user.name 'github-actions[bot]'
          git config user.email '41898282+github-actions[bot]@users.noreply.github.com'

          # Function to bump the version
          bump_version() {
            local version="$1"
            local IFS=.
            read -r major minor patch <<< "$version"
            patch=$((patch + 1))
            echo "$major.$minor.$patch-dev"
          }

          # Determine the new version tag
          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
            BUMP_INPUT="${{ github.event.inputs.bump }}"
            SPECIFIC_VERSION="${{ github.event.inputs.version }}"

            # Check if both bump and specific version are provided
            if [ "$BUMP_INPUT" = "true" ] && [ -n "$SPECIFIC_VERSION" ]; then
              echo "::error::Error: Cannot specify both bump and specific version."
              exit 1
            fi

            if [ -n "$SPECIFIC_VERSION" ]; then
              TAG_NAME="$SPECIFIC_VERSION-dev"
            elif [ "$BUMP_INPUT" = "true" ]; then
              CURRENT_VERSION=$(grep '"version":' package.json | awk -F\" '{print $4}')
              TAG_NAME=$(bump_version "$CURRENT_VERSION")
            else
              echo "No version bump or specific version provided for manual dispatch."
              exit 1
            fi
          else
            TAG_NAME="$(date +%y.%m).0-dev"
          fi

          echo "New version tag: $TAG_NAME"

          # Update version in files
          gawk -i inplace -F: -v q=\" -v tag=${TAG_NAME} '/^  "version": / { print $1 FS, q tag q ","; next} { print }' package.json
          gawk -i inplace -F= -v q=\" -v tag=${TAG_NAME} '/^__version__ =/ { print $1 FS, q tag q; next} { print }' redash/__init__.py
          gawk -i inplace -F= -v q=\" -v tag=${TAG_NAME} '/^version =/ { print $1 FS, q tag q; next} { print }' pyproject.toml

          git add package.json redash/__init__.py pyproject.toml
          git commit -m "Snapshot: ${TAG_NAME}"
          git tag ${TAG_NAME}
          git push --atomic origin master refs/tags/${TAG_NAME}

          # Run the 'preview-image' workflow if run this workflow manually
          # For more information, please see the: https://docs.github.com/en/actions/security-guides/automatic-token-authentication
          if [ "$BUMP_INPUT" = "true" ] || [ -n "$SPECIFIC_VERSION" ]; then
            gh workflow run preview-image.yml --ref $TAG_NAME
          fi


================================================
FILE: .github/workflows/preview-image.yml
================================================
name: Preview Image
on:
  push:
    tags:
      - '*-dev'
  workflow_dispatch:
    inputs:
      dockerRepository:
        description: 'Docker repository'
        required: true
        default: 'preview'
        type: choice
        options:
          - preview
          - redash

env:
  NODE_VERSION: 24

jobs:
  build-skip-check:
    runs-on: ubuntu-22.04
    outputs:
      skip: ${{ steps.skip-check.outputs.skip }}
    steps:
      - name: Skip?
        id: skip-check
        run: |
          if [[ "${{ vars.DOCKER_USER }}" == '' ]]; then
            echo 'Docker user is empty. Skipping build+push'
            echo skip=true >> "$GITHUB_OUTPUT"
          elif [[ "${{ secrets.DOCKER_PASS }}" == '' ]]; then
            echo 'Docker password is empty. Skipping build+push'
            echo skip=true >> "$GITHUB_OUTPUT"
          elif [[ "${{ vars.DOCKER_REPOSITORY }}" == '' ]]; then
            echo 'Docker repository is empty. Skipping build+push'
            echo skip=true >> "$GITHUB_OUTPUT"
          else
            echo 'Docker user and password are set and branch is `master`.'
            echo 'Building + pushing `preview` image.'
            echo skip=false >> "$GITHUB_OUTPUT"
          fi

  build-docker-image:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        arch:
          - amd64
          - arm64
        include:
          - arch: amd64
            os: ubuntu-22.04
          - arch: arm64
            os: ubuntu-22.04-arm
    outputs:
      VERSION_TAG: ${{ steps.version.outputs.VERSION_TAG }}
    needs:
      - build-skip-check
    if: needs.build-skip-check.outputs.skip == 'false'
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 1
          ref: ${{ github.event.push.after }}

      - uses: pnpm/action-setup@v4
        with:
          version: 10.30.3
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'pnpm'

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ vars.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASS }}

      - name: Install Dependencies
        env:
          PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: true
        run: pnpm install --frozen-lockfile

      - name: Set version
        id: version
        run: |
          set -x
          .ci/update_version
          VERSION_TAG=$(jq -r .version package.json)
          echo "VERSION_TAG=$VERSION_TAG" >> "$GITHUB_OUTPUT"

      - name: Build and push preview image to Docker Hub
        id: build-preview
        uses: docker/build-push-action@v4
        if: ${{ github.event.inputs.dockerRepository == 'preview' || !github.event.workflow_run }}
        with:
          tags: |
            ${{ vars.DOCKER_REPOSITORY }}/redash
            ${{ vars.DOCKER_REPOSITORY }}/preview
          context: .
          build-args: |
            test_all_deps=true
          outputs: type=image,push-by-digest=true,push=true
          cache-from: type=gha,scope=${{ matrix.arch }}
          cache-to: type=gha,mode=max,scope=${{ matrix.arch }}
        env:
          DOCKER_CONTENT_TRUST: true

      - name: Build and push release image to Docker Hub
        id: build-release
        uses: docker/build-push-action@v4
        if: ${{ github.event.inputs.dockerRepository == 'redash' }}
        with:
          tags: |
            ${{ vars.DOCKER_REPOSITORY }}/redash:${{ steps.version.outputs.VERSION_TAG }}
          context: .
          build-args: |
            test_all_deps=true
          outputs: type=image,push-by-digest=false,push=true
          cache-from: type=gha,scope=${{ matrix.arch }}
          cache-to: type=gha,mode=max,scope=${{ matrix.arch }}
        env:
          DOCKER_CONTENT_TRUST: true

      - name: "Failure: output container logs to console"
        if: failure()
        run: docker compose logs

      - name: Export digest
        run: |
          mkdir -p ${{ runner.temp }}/digests
          if [[ "${{ github.event.inputs.dockerRepository }}" == 'preview' || !github.event.workflow_run ]]; then
            digest="${{ steps.build-preview.outputs.digest}}"
          else
            digest="${{ steps.build-release.outputs.digest}}"
          fi
          touch "${{ runner.temp }}/digests/${digest#sha256:}"

      - name: Upload digest
        uses: actions/upload-artifact@v4
        with:
          name: digests-${{ matrix.arch }}
          path: ${{ runner.temp }}/digests/*
          if-no-files-found: error

  merge-docker-image:
    runs-on: ubuntu-22.04
    needs: build-docker-image
    steps:
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ vars.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASS }}

      - name: Download digests
        uses: actions/download-artifact@v4
        with:
          path: ${{ runner.temp }}/digests
          pattern: digests-*
          merge-multiple: true

      - name: Create and push manifest for the preview image
        if: ${{ github.event.inputs.dockerRepository == 'preview' || !github.event.workflow_run }}
        working-directory: ${{ runner.temp }}/digests
        run: |
          docker buildx imagetools create -t ${{ vars.DOCKER_REPOSITORY }}/redash:preview \
            $(printf '${{ vars.DOCKER_REPOSITORY }}/redash:preview@sha256:%s ' *)
          docker buildx imagetools create -t ${{ vars.DOCKER_REPOSITORY }}/preview:${{ needs.build-docker-image.outputs.VERSION_TAG }} \
            $(printf '${{ vars.DOCKER_REPOSITORY }}/preview:${{ needs.build-docker-image.outputs.VERSION_TAG }}@sha256:%s ' *)

      - name: Create and push manifest for the release image
        if: ${{ github.event.inputs.dockerRepository == 'redash' }}
        working-directory: ${{ runner.temp }}/digests
        run: |
          docker buildx imagetools create -t ${{ vars.DOCKER_REPOSITORY }}/redash:${{ needs.build-docker-image.outputs.VERSION_TAG }} \
            $(printf '${{ vars.DOCKER_REPOSITORY }}/redash:${{ needs.build-docker-image.outputs.VERSION_TAG }}@sha256:%s ' *)


================================================
FILE: .github/workflows/restyled.yml
================================================
name: Restyled

on:
  pull_request:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  restyled:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.sha }}

      - uses: restyled-io/actions/setup@v4
      - id: restyler
        uses: restyled-io/actions/run@v4
        with:
          fail-on-differences: true

      - if: |
          !cancelled() &&
          steps.restyler.outputs.success == 'true' &&
          github.event.pull_request.head.repo.full_name == github.repository
        uses: peter-evans/create-pull-request@v6
        with:
          base: ${{ steps.restyler.outputs.restyled-base }}
          branch: ${{ steps.restyler.outputs.restyled-head }}
          title: ${{ steps.restyler.outputs.restyled-title }}
          body: ${{ steps.restyler.outputs.restyled-body }}
          labels: "restyled"
          reviewers: ${{ github.event.pull_request.user.login }}
          delete-branch: true


================================================
FILE: .gitignore
================================================
.venv
venv/
.cache
.coverage.*
.coveralls.yml
.idea
*.pyc
.nyc_output
coverage
.coverage
coverage.xml
client/dist
.DS_Store
.#*
\#*#
*~
_build
.vscode
.env
.tool-versions

dump.rdb

node_modules
.tmp
.sass-cache
npm-debug.log

client/cypress/screenshots
client/cypress/videos


================================================
FILE: .npmrc
================================================
engine-strict=true
auto-install-peers=true
shamefully-hoist=true


================================================
FILE: .nvmrc
================================================
v24


================================================
FILE: .pre-commit-config.yaml
================================================
repos:
  - repo: https://github.com/psf/black
    rev: 23.1.0
    hooks:
      - id: black
        language_version: python3
  - repo: https://github.com/charliermarsh/ruff-pre-commit
    rev: "v0.0.287"
    hooks:
      - id: ruff


================================================
FILE: .restyled.yaml
================================================
enabled: true

auto: false

# Open Restyle PRs?
pull_requests: true

# Leave comments on the original PR linking to the Restyle PR?
comments: true

# Set commit statuses on the original PR?
statuses:
  # Red status in the case of differences found
  differences: true
  # Green status in the case of no differences found
  no_differences: true
  # Red status if we encounter errors restyling
  error: true

# Request review on the Restyle PR?
#
# Possible values:
#
#   author: From the author of the original PR
#   owner: From the owner of the repository
#   none: Don't
#
# One value will apply to both origin and forked PRs, but you can also specify
# separate values.
#
#   request_review:
#     origin: author
#     forked: owner
#
request_review: author

# Add labels to any created Restyle PRs
#
# These can be used to tell other automation to avoid our PRs.
#
labels:
  - restyled
  - "Skip CI"

# Labels to ignore
#
# PRs with any of these labels will be ignored by Restyled.
#
# ignore_labels:
#   - restyled-ignore

# Restylers to run, and how
restylers:
  - name: black
    image: restyled/restyler-black:v24.4.2
    include:
      - redash
      - tests
      - migrations/versions
  - name: prettier
    image: restyled/restyler-prettier:v3.3.2-2
    command:
      - prettier
      - --write
    include:
      - client/app/**/*.js
      - client/app/**/*.jsx
      - client/cypress/**/*.js


================================================
FILE: CHANGELOG.md
================================================
# Change Log

## 26.03.0

* Fix regular expression warning ([#7650](https://github.com/getredash/redash/pull/7650))
* Update Python version to 3.13 ([#7636](https://github.com/getredash/redash/pull/7636))
* Add last 2 years, last 3 years to the Date Range list ([#7635](https://github.com/getredash/redash/pull/7635))
* Update plotly.js to 3.3.1, react-pivottable to 0.11.0 ([#7634](https://github.com/getredash/redash/pull/7634))
* Add pivot chart ([#7632](https://github.com/getredash/redash/pull/7632))
* Aggregate y value for same x ([#7631](https://github.com/getredash/redash/pull/7631))
* cli: add --json option to users list command ([#7624](https://github.com/getredash/redash/pull/7624))
* Update packages for compatibility with setuptools 82 ([#7622](https://github.com/getredash/redash/pull/7622))
* Fix Elasticsearch connector configuration key mismatch ([#7607](https://github.com/getredash/redash/pull/7607))
* Support ipv6 for server in ipv6-only kubernetes cluster ([#7596](https://github.com/getredash/redash/pull/7596))
* fix(destinations): Handle unicode characters in webhook notifications ([#7586](https://github.com/getredash/redash/pull/7586))
* Add lineShape option for Line and Area charts ([#7582](https://github.com/getredash/redash/pull/7582))
* Feature/catch notsupported exception ([#7573](https://github.com/getredash/redash/pull/7573))
* Enhance dashboard parameter handling: persist updated values and apply saved parameters ([#7570](https://github.com/getredash/redash/pull/7570))
* Update queries.latest_query_data on save ([#7560](https://github.com/getredash/redash/pull/7560))
* Correct custom chart help text: use newPlot() ([#7557](https://github.com/getredash/redash/pull/7557))
* SchemaBrowser: on column comment tooltip, show newlines correctly ([#7552](https://github.com/getredash/redash/pull/7552))
* Query Serach: avoid concurrent search API request ([#7551](https://github.com/getredash/redash/pull/7551))
* Advanced query search syntax for multi byte search ([#7546](https://github.com/getredash/redash/pull/7546))
* Make details visualization configurable ([#7535](https://github.com/getredash/redash/pull/7535))
* Update ace-builds/react-ace to the latest versions ([#7532](https://github.com/getredash/redash/pull/7532))
* Fix/too many history replace state ([#7530](https://github.com/getredash/redash/pull/7530))
* Add range slider to the chart ([#7525](https://github.com/getredash/redash/pull/7525))
* Add "Missing and NULL values" option to scatter chart ([#7523](https://github.com/getredash/redash/pull/7523))
* fix: webpack missing source-map warning for @plotly/msgbox-gl ([#7522](https://github.com/getredash/redash/pull/7522))
* keep ordering on search ([#7520](https://github.com/getredash/redash/pull/7520))
* Fix: null is not shown for text with "Allow HTML content" ([#7519](https://github.com/getredash/redash/pull/7519))
* Fix stacking bar chart ([#7516](https://github.com/getredash/redash/pull/7516))
* Update plotly.js to 3.1.0 ([#7514](https://github.com/getredash/redash/pull/7514))
* Update Poetry to 2.1.4 ([#7509](https://github.com/getredash/redash/pull/7509))
* Update from webpack4 to webpack5 ([#7507](https://github.com/getredash/redash/pull/7507))
* Allow HTTP request line more than 4096 bytes ([#7506](https://github.com/getredash/redash/pull/7506))
* Add "Last 10 years" option for dynamic date range ([#7422](https://github.com/getredash/redash/pull/7422))
* Make favorite queries/dashboard order by starred at(favorited at) ([#7351](https://github.com/getredash/redash/pull/7351))
* Fix height for mobile safari not to overlap URL bar ([#7334](https://github.com/getredash/redash/pull/7334))
* Multi-org: format base path, not including protocol ([#7260](https://github.com/getredash/redash/pull/7260))
* PostgreSQL
  * PostgreSQL: Rely on information_schema.columns for views and foreign tables ([#7521](https://github.com/getredash/redash/pull/7521))
  * PostgreSQL: allow connection parameters to be specified ([#7579](https://github.com/getredash/redash/pull/7579))
  * changed pg.py has_privileges function to include special characters a… ([#7574](https://github.com/getredash/redash/pull/7574))
  * Use standard PostgreSQL image and drop clean-all target ([#7555](https://github.com/getredash/redash/pull/7555))
* MySQL
  * MySQL: add column type, comment, and table comment on Schema Browser ([#7544](https://github.com/getredash/redash/pull/7544))
  * Add charset option to RDS MySQL datasource ([#7616](https://github.com/getredash/redash/pull/7616))
  * fix(mysql): Change default charset to utf8mb4 ([#7615](https://github.com/getredash/redash/pull/7615))
* BigQuery
  * BigQuery: show table description tooltip in Schema Browser ([#7543](https://github.com/getredash/redash/pull/7543))
  * BigQuery: Remove "Job ID" metadata on annotaton to avoid cache misses ([#7541](https://github.com/getredash/redash/pull/7541))
  * BigQuery: support multiple dataset locations ([#7540](https://github.com/getredash/redash/pull/7540))
  * BigQuery: show column description(comment) on Schema Browser ([#7538](https://github.com/getredash/redash/pull/7538))
* DuckDB
  * Add duckdb support ([#7548](https://github.com/getredash/redash/pull/7548))
  * duckdb: Show catalog (database) where applicable (e.g. Motherduck) ([#7599](https://github.com/getredash/redash/pull/7599))
* Trino
  * Serialize Trino ROW types as JSON objects with field names ([#7644](https://github.com/getredash/redash/pull/7644))
  * added passing client_tags option to Trino plugin ([#7633](https://github.com/getredash/redash/pull/7633))
  * Add impersonation option in trino datasource ([#7605](https://github.com/getredash/redash/pull/7605))
* DB2
  * Add ibm-db package to enable DB2 as datasource: ([#7581](https://github.com/getredash/redash/pull/7581))
* Jira
  * Update jql.py (jira datasource) to use jira api v3 updated. ([#7527](https://github.com/getredash/redash/pull/7527))
* Snowflake
  * Add private_key auth method to snowflake query runner ([#7371](https://github.com/getredash/redash/pull/7371))


## 25.08.0

* MongoDB: fix for empty username/password (Issue #7486) ([#7487](https://github.com/getredash/redash/pull/7487))
* clickhouse: display data types ([#7490](https://github.com/getredash/redash/pull/7490))
* Clickhouse: do not display INFORMATION_SCHEMA tables ([#7489](https://github.com/getredash/redash/pull/7489))
* Sort Dashboard and Query tags by name([#7484](https://github.com/getredash/redash/pull/7484))
* Add migration to set default alert selector([#7475](https://github.com/getredash/redash/pull/7475))
* Make refresh cookie name configurable([#7473](https://github.com/getredash/redash/pull/7473))
* Make NULL values visible([#7439](https://github.com/getredash/redash/pull/7439))
* Fix: saving empty query with auto limit crashes([#7430](https://github.com/getredash/redash/pull/7430))
* Push image using DOCKER_REPOSITORY([#7428](https://github.com/getredash/redash/pull/7428))
* Update assertion method in JSON dumps test([#7424](https://github.com/getredash/redash/pull/7424))
* Add translate="no" to html tag to prevent redash from translating and crashing([#7421](https://github.com/getredash/redash/pull/7421))
* Update Azure Data Explorer query runner to latest version([#7411](https://github.com/getredash/redash/pull/7411))
* Use 12-column layout for dashboard grid([#7396](https://github.com/getredash/redash/pull/7396))
* Change BigQuery super class from BaseQueryRunner to BaseSQLQueryRunner([#7378](https://github.com/getredash/redash/pull/7378))
* Upgrade prettier version to the same version that CI is using([#7367](https://github.com/getredash/redash/pull/7367))
* Fix table item list ordering([#7366](https://github.com/getredash/redash/pull/7366))
* Fix to make "show data labels" works([#7363](https://github.com/getredash/redash/pull/7363))
* Upgrade plotly.js to version 2 to fix the UI crashing issue([#7359](https://github.com/getredash/redash/pull/7359))
* TiDB: Exclude INFORMATION_SCHEMA([#7352](https://github.com/getredash/redash/pull/7352))
* Sanitize NaN, Infinite, -Infinite causing error when saving as PostgreSQL JSON([#7348](https://github.com/getredash/redash/pull/7348))
* Fix UnboundLocalError when checking alerts for query([#7346](https://github.com/getredash/redash/pull/7346))
* BigQuery: Avoid too long(10 seconds) interval for bigquery api to get results([#7342](https://github.com/getredash/redash/pull/7342))
* Add NULLS LAST option for query list ordering([#7341](https://github.com/getredash/redash/pull/7341))
* TypeScript sourcemap for viz-lib([#7336](https://github.com/getredash/redash/pull/7336))
* Fix the issue that chart(scatter, bubble, line...) having data with same x-value have wrong y-value([#7330](https://github.com/getredash/redash/pull/7330))
* Partiallly Revert "Remove workaround from check_csrf() (#6919)" ([#7327](https://github.com/getredash/redash/pull/7327))
* Make autocomplete always available([#7326](https://github.com/getredash/redash/pull/7326))
* Include Plotly.js localization([#7323](https://github.com/getredash/redash/pull/7323))
* Use absolute path for image resources([#7322](https://github.com/getredash/redash/pull/7322))
* Build/Test
  * Require vars.DOCKER_REPOSITORY to publish image([#7400](https://github.com/getredash/redash/pull/7400))
  * ci: snapshot only on default branch([#7355](https://github.com/getredash/redash/pull/7355))
  * Push by tag name for Docker repository "redash"([#7321](https://github.com/getredash/redash/pull/7321))
* Dependencies
  * Bump tar-fs from 2.1.1 to 2.1.2([#7385](https://github.com/getredash/redash/pull/7385))

## 25.01.0

* Support result reuse in Athena data sources ([\#7202](https://github.com/getredash/redash/pull/7202))
* Handle the case when query runner configuration is an empty dict ([\#7258](https://github.com/getredash/redash/pull/7258))
* BigQuery: add date, datetime type mapping ([\#7252](https://github.com/getredash/redash/pull/7252))
* Build/Test
  * Create workflow trigger for publishing release image ([\#7259](https://github.com/getredash/redash/pull/7259))
* Dependencies
  * Bump actions/upload-artifact from v3 to v4 ([\#7266](https://github.com/getredash/redash/pull/7266))
  * Bump jinja2 from 3.1.4 to 3.1.5 ([\#7262](https://github.com/getredash/redash/pull/7262))
  * Bump nanoid from 3.3.6 to 3.3.8 ([\#7249](https://github.com/getredash/redash/pull/7249))
  * Bump to paramiko-3.4.1 ([\#7240](https://github.com/getredash/redash/pull/7240))

## 24.12.0

* Replace ptvsd with debugpy to match modern VS Code ([\#7234](https://github.com/getredash/redash/pull/7234))
* Alerts: Only evaluate the next state if there's a value ([\#7222](https://github.com/getredash/redash/pull/7222))
* Bring back version check & beacon reporting ([\#7211](https://github.com/getredash/redash/pull/7211))

## 24.11.0

* Alerts: don't crash when there is no data ([\#7208](https://github.com/getredash/redash/pull/7208))
* Fix issue with scheduled queries ([\#7111](https://github.com/getredash/redash/pull/7111))
* Correctly rehash queries in a migration ([\#7184](https://github.com/getredash/redash/pull/7184))
* Use correct redis connection ([\#7077](https://github.com/getredash/redash/pull/7077))
* Fix RQ wrongly moving jobs to FailedJobRegistry ([\#7186](https://github.com/getredash/redash/pull/7186))
* Build/Test
  * Move restyled to a github action ([\#7191](https://github.com/getredash/redash/pull/7191))
  * Docker build: use heredoc for multi-line actions ([\#7210](https://github.com/getredash/redash/pull/7210))
* Dependencies
  * Bump cryptography from 42.0.8 to 43.0.1 ([\#7205](https://github.com/getredash/redash/pull/7205))
  * Bump http-proxy-middleware from 2.0.6 to 2.0.7 ([\#7204](https://github.com/getredash/redash/pull/7204))
  * Bump snowflake-connector-python from 3.12.0 to 3.12.3 ([\#7203](https://github.com/getredash/redash/pull/7203))
  * Bump restrictedpython from 6.2 to 7.3 ([\#7181](https://github.com/getredash/redash/pull/7181))
  * Bump elliptic from 6.5.7 to 6.6.0 ([\#7214](https://github.com/getredash/redash/pull/7214))

## 24.10.0

* Get rid of the strange looking 0 following "Running..." and "runtime" ([\#7099](https://github.com/getredash/redash/pull/7099))
* Automatically remove orphans when running make up ([\#7164](https://github.com/getredash/redash/pull/7164))
* Update `make up` to automatically initialize the db ([\#7161](https://github.com/getredash/redash/pull/7161))
* Better error msg for token validation ([\#7159](https://github.com/getredash/redash/pull/7159))
* Add REDASH_HOST to the docker compose file ([\#7157](https://github.com/getredash/redash/pull/7157))
* Make schema refresh timeout configurable via env var ([\#7114](https://github.com/getredash/redash/pull/7114))
* Dependencies 
  * Update pymssql to fix some problems with macOS ARM64 (`2.3.1`) ([\#7140](https://github.com/getredash/redash/pull/7140))
  * Bump body-parser from 1.20.1 to 1.20.3 ([\#7156](https://github.com/getredash/redash/pull/7156))
  * Bump express from 4.19.2 to 4.21.0 ([\#7155](https://github.com/getredash/redash/pull/7155))
  * Bump path-to-regexp from 3.2.0 to 3.3.0 ([\#7154](https://github.com/getredash/redash/pull/7154))
  * Bump dompurify from 2.0.17 to 2.5.4 in /viz-lib ([\#7163](https://github.com/getredash/redash/pull/7163))

## 24.09.0

* Add option to choose color scheme for charts ([\#7062](https://github.com/getredash/redash/pull/7062))
* Add data type to Athena query runner ([\#7112](https://github.com/getredash/redash/pull/7112))
* Add data type to Redshift query runner ([\#7109](https://github.com/getredash/redash/pull/7109))
* Fix a display order bug in MongoDB Query Runner ([\#7106](https://github.com/getredash/redash/pull/7106))
* Add the option to take new custom version for Snapshot ([\#7096](https://github.com/getredash/redash/pull/7096))
* Update certificates for RDS ([\#7100](https://github.com/getredash/redash/pull/7100))
* Fix columns duplication on MongoDB Query Runner [\#6640](https://github.com/getredash/redash/pull/6640) ([\#6641](https://github.com/getredash/redash/pull/6641))
* Get data size in memory for better logs ([\#7090](https://github.com/getredash/redash/pull/7090))
* Adding Evaluate button for alerts to test them ([\#7032](https://github.com/getredash/redash/pull/7032))
* Add min/max/first selector for alerts ([\#7076](https://github.com/getredash/redash/pull/7076))([\#7103](https://github.com/getredash/redash/pull/7103))
* Add support for 'linux/arm64' platforms ([\#7094](https://github.com/getredash/redash/pull/7094))
* Regressions
  * Revert "Removed unused configuration class ([\#6682](https://github.com/getredash/redash/pull/6682))" ([\#7071](https://github.com/getredash/redash/pull/7071))
  * Revert "Adding ability to fix table columns in place ([\#7019](https://github.com/getredash/redash/pull/7019))" ([\#7131](https://github.com/getredash/redash/pull/7131))
* Dependencies
  * Fix mismatched poetry version ([\#7122](https://github.com/getredash/redash/pull/7122))
  * Bump cryptography to 42.0.x & snowflake-connector-python to 3.12.0 ([\#7097](https://github.com/getredash/redash/pull/7097))
  * Bump webpack from 5.88.2 to 5.94.0 in /viz-lib ([\#7135](https://github.com/getredash/redash/pull/7135))
  * Bump bootstrap to 3.4.1
  * Bump sentry-sdk from 1.28.1 to 2.8.0 ([\#7069](https://github.com/getredash/redash/pull/7069))
  * Bump python-rapidjson to 1.20 ([\#7126](https://github.com/getredash/redash/pull/7126))
  * Bump elliptic to version 6.5.7 to fix a Dependabot warning ([\#7120](https://github.com/getredash/redash/pull/7120))

## 24.08.0

* Remove defaults set during schema upgrade/downgrade [\#7068](https://github.com/getredash/redash/pull/7068)  
* Athena: Support Arbitrary Catalog ID [\#7059](https://github.com/getredash/redash/pull/7059)  
* Add option to toggle sort on pie charts [\#7055](https://github.com/getredash/redash/pull/7055)  
* Conditionally render tooltip for Edit alert button [\#7054](https://github.com/getredash/redash/pull/7054)  
* Make Redash FIPS compatible [\#7049](https://github.com/getredash/redash/pull/7049)  
* Add a label for Restyler's PR and Bump component version [\#7037](https://github.com/getredash/redash/pull/7037)  
* Add new text pattern parameter input type [\#7025](https://github.com/getredash/redash/pull/7025)  
* Adding ability to fix table columns in place [\#7019](https://github.com/getredash/redash/pull/7019) (_reverted in [#7131](https://github.com/getredash/redash/pull/7131)_)
* Fixed frontend test deprecation warnings [\#7013](https://github.com/getredash/redash/pull/7013)  
* Dependencies  
  * Bump setuptools from 69.0.3 to 70.0.0 [\#7060](https://github.com/getredash/redash/pull/7060)  
  * Bump requests to 2.32.3 [\#7057](https://github.com/getredash/redash/pull/7057)  
  * Bump zipp from 3.17.0 to 3.19.1 [\#7051](https://github.com/getredash/redash/pull/7051)
  * Bump certifi from 2023.11.17 to 2024.7.4 [\#7047](https://github.com/getredash/redash/pull/7047)
  * Bump ws from 5.2.3 to 5.2.4 in /viz-lib [\#7040](https://github.com/getredash/redash/pull/7040)

## 24.07.0

* Map() implementation fix for chart labels [\#7022](https://github.com/getredash/redash/pull/7022)  
* PostgreSQL: Only list tables where schema has USAGE permission [\#7000](https://github.com/getredash/redash/pull/7000)  
* Update to Python 3.10 / Debian 12 [\#6991](https://github.com/getredash/redash/pull/6991)  
* Dependencies  
  * Bump ws from 5.2.3 to 5.2.4 [\#7021](https://github.com/getredash/redash/pull/7021)  
  * Bump urllib3 from 1.26.18 to 1.26.19 [\#7020](https://github.com/getredash/redash/pull/7020)

## 24.06.0 [broken]

* Sync .nvmrc with workflow [\#6958](https://github.com/getredash/redash/pull/6958)
* Fix 'str' object has no attribute 'pop' error when parsing query [\#6941](https://github.com/getredash/redash/pull/6941)
* pgautoupgrade now does multi-arch builds [\#6939](https://github.com/getredash/redash/pull/6939)
* Fix error serialization [\#6937](https://github.com/getredash/redash/pull/6937)
* Dependencies  
  * Bump requests from 2.31.0 to 2.32.0 [\#6981](https://github.com/getredash/redash/pull/6981)
  * Bump pyodbc from 4.0.28 to 5.1.0 [\#6962](https://github.com/getredash/redash/pull/6962)
  * Bump jinja2 from 3.1.3 to 3.1.4 [\#6951](https://github.com/getredash/redash/pull/6951)


## 24.05.0 [broken]

* Downgrade 'codecov-action' version from v4 to v3 [\#6930](https://github.com/getredash/redash/pull/6930)
* Update widgets.py [\#6926](https://github.com/getredash/redash/pull/6926)
* Use staticPath var to fetch unsupportedRedirect.js [\#6923](https://github.com/getredash/redash/pull/6923)
* Remove workaround from check\_csrf() [\#6919](https://github.com/getredash/redash/pull/6919)
* Bugfix: unable to parse elasticsearch index mappings [\#6918](https://github.com/getredash/redash/pull/6918)
* Consistent rq status naming and handling [\#6913](https://github.com/getredash/redash/pull/6913)
* Fix: aws elasticsearch typo [\#6899](https://github.com/getredash/redash/pull/6899)
* Add pydeps Makefile target for installing Python dependencies [\#6890](https://github.com/getredash/redash/pull/6890)
* Improve the text displayed when using the command line [\#6884](https://github.com/getredash/redash/pull/6884)
* Fixed local setup to run on ARM64 [\#6877](https://github.com/getredash/redash/pull/6877)
* Fix for coverage [\#6872](https://github.com/getredash/redash/pull/6872)
* Use default docker repo name if variable is not defined [\#6870](https://github.com/getredash/redash/pull/6870)
* Fix percy for a branch [\#6868](https://github.com/getredash/redash/pull/6868)
* Update yarn to current latest in 1.22.x series [\#6858](https://github.com/getredash/redash/pull/6858)
* Extend \`make up\` to automatically initialise the database [\#6855](https://github.com/getredash/redash/pull/6855)
* Remove version check and all of the data sharing [\#6852](https://github.com/getredash/redash/pull/6852)
* Automatically use the latest version of PostgreSQL [\#6851](https://github.com/getredash/redash/pull/6851)
* Remove Qubole query runner [\#6848](https://github.com/getredash/redash/pull/6848)
* Update "make clean" to remove Redash dev Docker images [\#6847](https://github.com/getredash/redash/pull/6847)
* Handle timedelta in query results [\#6846](https://github.com/getredash/redash/pull/6846)
* Autoformat hyperlinks in Slack alerts [\#6845](https://github.com/getredash/redash/pull/6845)
* Flatten all level for MongoDB data source [\#6844](https://github.com/getredash/redash/pull/6844)
* Filter widget results to fix tests during repeatable execution [\#6693](https://github.com/getredash/redash/pull/6693)
* Reuse built frontend in ci, merge compose files [\#6674](https://github.com/getredash/redash/pull/6674)
* Show pg and athena column comments and table descriptions as antd tooltip if they are defined [\#6582](https://github.com/getredash/redash/pull/6582)
* Dependencies  
  * Bump gunicorn to 22.0.0 [\#6900](https://github.com/getredash/redash/pull/6900)
  * Bump sqlparse from 0.4.4 to 0.5.0 [\#6895](https://github.com/getredash/redash/pull/6895)
  * Bump dnspython from 2.4.2 to 2.6.1 [\#6886](https://github.com/getredash/redash/pull/6886)
  * Bump python-oracledb from 2.0.1 to 2.1.2 [\#6881](https://github.com/getredash/redash/pull/6881)
  * Bump idna from 3.6 to 3.7 [\#6878](https://github.com/getredash/redash/pull/6878)
  * Bump tar from 6.1.15 to 6.2.1 [\#6866](https://github.com/getredash/redash/pull/6866)
  * Bump pymongo from 4.3.3 to 4.6.3 [\#6863](https://github.com/getredash/redash/pull/6863)
  * Bump Rq from 1.9.0 to 1.16.1 [\#6902](https://github.com/getredash/redash/pull/6902)

## 24.04.0 [broken]

* Handle decimal types in query results [\#6837](https://github.com/getredash/redash/pull/6837)
* BigQuery: use default for useQueryAnnotation option [\#6824](https://github.com/getredash/redash/pull/6824) 
* Uncaught rejection promise error in Edit Visualization Dialog Modal [\#6794](https://github.com/getredash/redash/pull/6794)
* Add RisingWave support [\#6776](https://github.com/getredash/redash/pull/6776)
* Schedule may not contain an until key [\#6771](https://github.com/getredash/redash/pull/6771)
* ClickHouse query runner: fixed error message [\#6764](https://github.com/getredash/redash/pull/6764)
* Dependencies  
  * Bump express from 4.18.2 to 4.19.2 [\#6838](https://github.com/getredash/redash/pull/6838)
  * Bump webpack-dev-middleware from 5.3.3 to 5.3.4 [\#6829](https://github.com/getredash/redash/pull/6829)
  * Bump jwcrypto from 1.5.1 to 1.5.6 [\#6816](https://github.com/getredash/redash/pull/6816)
  * Bump follow-redirects from 1.15.5 to 1.15.6 in /viz-lib [\#6813](https://github.com/getredash/redash/pull/6813)
  * Bump es5-ext from 0.10.53 to 0.10.63 in /viz-lib [\#6782](https://github.com/getredash/redash/pull/6782)

## 24.03.0

- Publish preview Docker image when release candidate is tagged [#6787](https://github.com/getredash/redash/pull/6787) [#6789](https://github.com/getredash/redash/pull/6789)

## 24.02.0

- Converted `text` columns to `jsonb` [#6687](https://github.com/getredash/redash/pull/6687) [#6713](https://github.com/getredash/redash/pull/6713)
- Update query hash with parameters applied [#6683](https://github.com/getredash/redash/pull/6683)

## 24.01.0

- Prometheus:
  - Add ssl support [#6657](https://github.com/getredash/redash/pull/6657)
- Influxdb
  - Add v2 query runner [#6646](https://github.com/getredash/redash/pull/6646)

## 23.12.0

- Add unarchive button to dashboard
- Add fork dashboard function
- Default to last used datasource
- Regression fix
  - Revert "Switch from numeral to numbro)" [#6595](https://github.com/getredash/redash/pull/6595)

## 23.11.0

- Add query Runner for Yandex Disk
- New connection options for MySQL [#6538](https://github.com/getredash/redash/pull/6538)
- Regression fix
  - Revert "Render counter widgets using relative font size" [#6566](https://github.com/getredash/redash/pull/6566)

## 23.10.0

- Avoid updating query result for archived queries [#6488](https://github.com/getredash/redash/pull/6488)
- Add Tinybird query runner [#5616](https://github.com/getredash/redash/pull/5616)

## 23.09.0

- Allow the X and Y tick format to be customized using a [D3 format string](https://redash.io/help/user-guide/visualizations/formatting-axis/) [#6370](https://github.com/getredash/redash/pull/6370)
- Add support for a default alert template [#5996](https://github.com/getredash/redash/pull/5996)
- New alert destination: Asana [#5753](https://github.com/getredash/redash/pull/5753)
- Fix query refresh if name contain control characters [#5602](https://github.com/getredash/redash/pull/5602)
- Allow RSA key used for JWT to be specified as a file path [#6271](https://github.com/getredash/redash/pull/6271)
- Add 'click' functionality for Chart visualization



## V10.1.0 - 2021-11-23

This release includes patches for three security vulnerabilities:

- Insecure default configuration affects installations where REDASH_COOKIE_SECRET is not set explicitly (CVE-2021-41192)
- SSRF vulnerability affects installations that enabled URL-loading data sources (CVE-2021-43780)
- Incorrect usage of state parameter in OAuth client code affects installations where Google Login is enabled (CVE-2021-43777)

And a couple features that didn't merge in time for 10.0.0

- Big Query: Speed up schema loading (#5632)
- Add support for Firebolt data source (#5606)
- Fix: Loading schema for Sqlite DB with "Order" column name fails (#5623)

## v10.0.0 - 2021-10-01

A few changes were merged during the V10 beta period.

- New Data Source: CSV/Excel Files
- Fix: Edit Source button disappeared for users without CanEdit permissions
- We pinned our docker base image to Python3.7-slim-buster to avoid build issues
- Fix: dashboard list pagination didn't work

## v10.0.0-beta - 2021-06-16

Just over a year since our last release, the V10 beta is ready. Since we never made a non-beta release of V9, we expect many users will upgrade directly from V8 -> V10. This will bring a lot of exciting features. Please check out the V9 beta release notes below to learn more.

This V10 beta incorporates fixes for the feedback we received on the V9 beta along with a few long-requested features (horizontal bar charts!) and other changes to improve UX and reliability.

This release was made possible by contributions from 35+ people (the Github API didn't let us pull handles this time around): Alex Kovar, Alexander Rusanov, Arik Fraimovich, Ben Amor, Christopher Grant, Đặng Minh Dũng, Daniel Lang, deecay, Elad Ossadon, Gabriel Dutra, iwakiriK, Jannis Leidel, Jerry, Jesse Whitehouse, Jiajie Zhong, Jim Sparkman, Jonathan Hult, Josh Bohde, Justin Talbot, koooge, Lei Ni, Levko Kravets, Lingkai Kong, max-voronov, Mike Nason, Nolan Nichols, Omer Lachish, Patrick Yang, peterlee, Rafael Wendel, Sebastian Tramp, simonschneider-db, Tim Gates, Tobias Macey, Vipul Mathur, and Vladislav Denisov

Our special thanks to [Sohail Ahmed](https://pk.linkedin.com/in/sohail-ahmed-755776184) for reporting a vulnerability in our "forgot password" page (#5425)

### Upgrading

(This section is duplicated from the previous release - since many users will upgrade directly from V8 -> V10)

Typically, if you are running your own instance of Redash and wish to upgrade, you would simply modify the Docker tag in your `docker-compose.yml` file. Since RQ has replaced Celery in this version, there are a couple extra modifications that need to be done in your `docker-compose.yml`:

1. Under `services/scheduler/environment`, omit `QUEUES` and `WORKERS_COUNT` (and omit `environment` altogether if it is empty).
2. Under `services`, add a new service for general RQ jobs:

```yaml
worker:
  <<: *redash-service
  command: worker
  environment:
    QUEUES: "periodic emails default"
    WORKERS_COUNT: 1
```

Following that, force a recreation of your containers with `docker-compose up --force-recreate --build` and you should be good to go.
### UX
- Redash now uses a vertical navbar
- Dashboard list now includes “My Dashboards” filter
- Dashboard parameters can now be re-ordered
- Queries can now be executed with Shift + Enter on all platforms.
- Added New Dashboard/Query/Alert buttons to corresponding list pages
- Dashboard text widgets now prompt to confirm before closing the text editor
- A plus sign is now shown between tags used for search
- On the queries list view “My Queries” has moved above “Archived”
- Improved behavior for filtering by tags in list views
- When a user’s session expires for inactivity, they are prompted to log-in with a pop-up so they don’t lose their place in the app
- Numerous accessibility changes towards the a11y standard
- Hide the “Create” menu button if current user doesn’t have permission to any data sources

### Visualizations
- Feature: Added support for horizontal box plots
- Feature: Added support for horizontal bar charts
- Feature: Added “Reverse” option for Chart visualization legend
- Feature: Added option to align Chart Y-axes at zero
- Feature: The table visualization header is now fixed when scrolling
- Feature: Added USA map to choropleth visualization
- Fix: Selected filters were reset when switching visualizations
- Fix: Stacked bar chart showed the wrong Y-axis range in some cases
- Fix: Bar chart with second y axis overlapped data series
- Fix: Y-axis autoscale failed when min or max was set
- Fix: Custom JS visualization was broken because of a typo
- Fix: Too large visualization caused filters block to collapse
- Fix: Sankey visualization looked inconsistent if the data source returned VARCHAR instead of numeric types

### Structural Updates
- Redash now prevents CSRF attacks
- Migration to TypeScript
- Upgrade to Antd version 4
### Data Sources
- New Data Sources: SPARQL Endpoint, Eccenca Corporate Memory, TrinoDB
- Databricks
  - Custom Schema Browser that allows switching between databases
  - Option added to truncate large results
  - Support for multiple-statement queries
  - Schema browser can now use eventlet instead of RQ
- MongoDB:
  - Moved Username and Password out of the connection string so that password can be stored secretly
- Oracle:
  - Fix: Annotated queries always failed. Annotation is now disabled
- Postgres/CockroachDB:
  - SSL certfile/keyfile fields are now handled as secret
- Python:
  - Feature: Custom built-ins are now supported
  - Fix: Query runner was not compatible with Python 3
- Snowflake:
  - Data source now accepts a custom host address (for use with proxies)
- TreasureData:
  - API key field is now handled as secret
- Yandex:
  - OAuth token field is now handled as secret

### Alerts
- Feature: Added ability to mute alerts without deleting them
- Change: Non-email alert destination details are now obfuscated to avoid leaking sensitive information (webhook URLs, tokens etc.)
- Fix: numerical comparisons failed if value from query was a string

### Parameters
- Added “Last 12 months” option for dynamic date ranges

### Bug Fixes
- Fix: Private addresses were not allowed even when enforcing was disabled 
- Fix: Python query runner wasn’t updated for Python 3
- Fix: Sorting queries by schedule returned the wrong order
- Fix: Counter visualization was enormous in some cases
- Fix: Dashboard URL will now change when the dashboard title changes
- Fix: URL parameters were removed when forking a query
- Fix: Create link on data sources page was broken
- Fix: Queries could be reassigned to read-only data sources
- Fix: Multi-select dropdown was very slow if there were 1k+ options
- Fix: Search Input couldn’t be focused or updated while editing a dashboard
- Fix: The CLI command for “status” did not work
- Fix: The dashboard list screen displayed too few items under certain pagination configurations

### Other
- Added an environment variable to disable public sharing links for queries and dashboards
- Alert destinations are now encrypted at the database
- The base query runner now has stubs to implement result truncating for other data sources
- Static SAML configuration and assertion encryption are now supported
- Adds new component for adding extra actions to the query and dashboard pages
- Non-admins with at least view_only permission on a dashboard can now make GET requests to the data source resource
- Added a BLOCKED_DOMAINS setting to prevent sign-ups from emails at specific domains
- Added a rate limit to the “forgot password” page
- RQ workers will now shutdown gracefully for known error codes
- Scheduled execution failure counter now resets following a successful ad hoc execution
- Redash now deletes locks for cancelled queries
- Upgraded Ace Editor from v6 to v9
- Added a periodic job to remove ghost locks
- Removed content width limit on all pages
- Introduce a <Link> React component

## v9.0.0-beta - 2020-06-11

This release was long time in the making and has several major changes:

- Our backend code was updated to support Python 3 and we no longer support Python 2. If you're using our Docker images, this should be a transparent change for you.
- We replaced Celery with RQ for background jobs processing. This will require some setup updates -- see instructions below.
- The frontend code is now 100% React and we removed all the Angular dependencies.

This release was made possible by contributions from over 50 people: @ari-e, @ariarijp, @arihantsurana, @arikfr, @atharvai, @cemremengu, @chulucninh09, @citrin, @daniellangnet, @DavidHernandez, @deecay, @dmudro, @erans, @erels, @ezkl, @gabrieldutra, @gstaykov, @ialeinikov, @ikenji, @Jakdaw, @jezdez, @juanvasquezreyes, @koooge, @kravets-levko, @kykrueger, @leibowitz, @leosunmo, @lihan, @loganprice, @mickeey2525, @mnoorenberghe, @monicagangwar, @NicolasLM, @p-yang, @Ralnoc, @ranbena, @randyzwitch, @rauchy, @rxin, @saravananselvamohan, @satyamkrishna, @shinsuke-nara, @stefan-mees, @stevebuckingham, @susodapop, @taminif, @thewarpaint, @tsuyoshizawa, @uncletimmy3, @wengkham.

### Upgrading

Typically, if you are running your own instance of Redash and wish to upgrade, you would simply modify the Docker tag in your `docker-compose.yml` file. Since RQ has replaced Celery in this version, there are a couple extra modifications that need to be done in your `docker-compose.yml`:

1. Under `services/scheduler/environment`, omit `QUEUES` and `WORKERS_COUNT` (and omit `environment` altogether if it is empty).
2. Under `services`, add a new service for general RQ jobs:

```yaml
worker:
  <<: *redash-service
  command: worker
  environment:
    QUEUES: "periodic emails default"
    WORKERS_COUNT: 1
```

Following that, force a recreation of your containers with `docker-compose up --force-recreate --build` and you should be good to go.

### UX

- Redesigned Query Results page:
  - Completely new layout is easier to read for non-technical Redash users.
  - Empty query results are clearly displayed. User is now prompted to edit or execute the query.
- Mobile Experience Improvements:
  - UI element spacing has been redesigned for clarity
  - Admin pages now honor max-width. Tables scroll independent of the top menu.
  - Large legends no longer shrink the visualization on small screens.
  - Fix: it was sometimes impossible to scroll pages with dashboards because the visualizations captured every touch event.
  - Fix: Visualizations on small screens would not always show horizontal scroll bars.
- Dashboards can now be un-archived using the API.
- Dashboard UI performance was improved.
- List pages were changed to show a user's name instead of avatar.
- Search-enabled tables now show a prompt for which columns will be searched.
- In the visualization editor, the settings pane now scrolls independent of the visualization preview.
- Tokens in the schema viewer now sort alphabetically.
- Links to settings panes that require Admin privileges are now hidden from non-Admins.
- The Admin page now remembers which tab you were viewing after a page reload.

### Visualizations

- Feature: Allow bubble size control with either coefficient or sizemode.
- Feature: Table visualization now treats Unix timestamps in query results as timestamps.
- Feature: It's now possible to provide a description to each Table column, appearing in UI as a tooltip.
- Feature: Added tooltip and popover templating to the map with markers visualization.
- Feature: Added an organization setting to hide the Plotly mode bar on all visualizations.
- Feature: Cohort visualization now has appearance settings.
- Feature: Add option to explicitly set Chart legend position.
- Change: Deprecated visualizations are now hidden.
- Change: Table settings editor now extends vertically instead of horizontally.
- Change: The maximum table pagination is now 500.
- Change: Pie chart labels maintain contrast against lighter slices.
- Fix: Chart series switched places when picking Y axis.
- Fix: Third column was not selectable for Bubble and Heatmap charts.
- Fix: On the counter visualizations, the “count rows” option showed an empty string instead of 0.
- Fix: Table visualization with column named "children" rendered +/- buttons.
- Fix: Sankey visualization now correctly occupies all available area even with fewer stages.
- Fix: Pie chart ignores series labels.

### Data Sources

- New Data Sources: Amazon Cloudwatch, Amazon CloudWatch Logs Insights, Azure Kusto, Exasol.
- Athena:
  - Added the option to specify a base cost in settings, displaying a price for each query when executed.
- BigQuery:
  - Fix: large jobs continued running after the user clicked “Cancel” query execution.
- Cassandra:
  - Updated driver to 3.21.0 which dramatically reduces Docker build times.
  - SSL options are now available.
- Clickhouse:
  - You can now choose whether to verify the SSL certificate.
- Databricks:
  - Databricks now use an ODBC-based connector.
  - Fix: Date column was coerced to DateTime in the front-end.
- Druid:
  - Added username and password authentication option.
- Microsoft SQL Server
  - Added support for ODBC connections via pyodbc. There are now two MSSQL data source types. One using TDS. The other is using ODBC.
- MongoDB:
  - Added support for running queries on secondary in replicaset mode.
  - Fix: Connection test always succeeded.
- Oracle:
  - Fix: Connection would fail if username or password contained special characters.
  - Fix: Comparisons would fail if scale was None.
- RDS:
  - Updated rds-combined-ca-bundle.pem to the latest CA.
- Redshift:
  - Added the ability to use IAM Roles and Users.
  - Fix: Redshift was unable to have its schema refreshed.
- Rockset:
  - Fix: Allow Redash to load collections in all workspaces.
- Snowflake:
  - You can now refresh the snowflake schema without waking the cluster.
  - Added support for all of Snowflake’s datetime types. Otherwise certain timestamps would only appear as strings in the front-end.
- TreasureData:
  - Fix: API calls would fail when setting a non-default region.

### Alerts

- Feature: Added ability to mute alerts without deleting them.
- Fix: numerical comparisons failed if value from query was a string.

### Parameters

- Added Last x Days options for date range parameters.
- Fix: Parameters added in empty queries were always added as text parameters

### Bug Fixes

- Fix: Alembic migration schema was preventing v4 users from upgrading. In v5 we started encrypting data source credentials in the database.
- Fix: System admin dashboard would not show correct database size if non-default name was used.
- Fix: refresh_queries job would break if any query had a bad schedule object.
- Fix: Orgs with LDAP enabled couldn’t disable password login.
- Fix: SSL mode was sometimes sent as an empty string to the database instead of omitted entirely.
- Fix: When creating new Map visualization with clustering disabled, map would crash on save.
- Fix: It was possible on the New Query page to click “Save” multiple times, causing multiple new query records to be created.
- Fix: Visualization render errors on a dashboard would crash the entire page.
- Fix: A scheduled execution failure would modify the query’s “updated_at” timestamp.
- Fix: Parameter UI would wrap awkwardly during some drag operations.
- Fix: In dashboard edit mode, users couldn’t modify widgets.
- Fix: Frontend error when parsing a NaN float.

### Other

- Added TSV as a download format (in addition to CSV and Excel).
- Added maildev settings (helps with automated settings).
- Refine permissions usage in Redash to allow for guest users
- The query results API now explicitly handles 404 errors.
- Forked queries now retain the tags of the original query.
- We now allow setting custom Sentry environments.
- Started using Black linter for our Python source code
- Added CLI command to re-encrypt data source details with new secret key.
- Favorites list is now loaded on menu click instead of on page load.
- Administrators can now allow connections to private IP addresses.

## v8.0.0 - 2019-10-27

There were no changes in this release since `v8.0.0-beta.2`. This is just to mark a stable release.

## v8.0.0-beta.2 - 2019-09-16

This is an update to the previous beta release, which includes:

- Add options for users to share anonymous usage information with us (see [docs](https://redash.io/help/open-source/admin-guide/usage-data) for details).
- Visualizations:
  - Allow the user to decide how to handle null values in charts.
- Upgrade Sentry-SDK to latest version.
- Make horizontal table scroll visible in dashboard widgets without scrolling.
- Data Sources:
  - Add support for Azure Data Explorer (Kusto).
  - MySQL: fix connections without SSL configuration failing.
  - Amazon Redshift: option to set query group for adhoc/scheduled queries.
  - Hive: make error message more friendly.
  - Qubole: add support to run Quantum queries.
- Display data source icon in query editor.
- Fix: allow users with view only acces to use the queries in Query Results
- Dashboard: when updating parameters refersh only widgets that use those parameters.

This release had contributions from 12 people: @arikfr, @cclauss, @gabrieldutra, @justinclift, @kravets-levko, @ranbena, @rauchy, @sandeepV2, @shinsuke-nara, @spacentropy, @sphenlee, @swfz.

## v8.0.0-beta - 2019-08-18

After months of being heads down with hard work, it's finally time to wrap up the V8 release 🤩 This release includes many long awaited improvements to parameters, UX improvements, further React migration and other changes, fixes and improvements.

While this version is already running on the hosted platform to make sure it's stable, we're excited to put this in the hands of our Open Source users.

Starting from this release we will no longer build a tarball distribution of the codebase and recommend everyone to switch over to using our Docker images. We're planning on dropping Python 2 support towards its EOL this year and switching over to the Docker image will make this transition much simpler.

This release was made possible by contributions from over 40 people: @aidarbek, @AntonZarutsky, @ariarijp, @arikfr, @combineads, @deecay, @fmy, @gabrieldutra, @guwenqing, @guyco33, @ialeinikov, @Jakdaw, @jezdez, @justinclift, @k-tomoyasu, @katty0324, @koooge, @kravets-levko, @ktmud, @KumanoTanaka, @kyoshidajp, @nason, @oldPadavan, @openjck, @osule, @otsaloma, @ranbena, @rauchy, @rueian, @sekiyama58, @shinsuke-nara, @taminif, @The-Alchemist, @vv-p, @washort, @wudi-ayuan, @ygrishaev, @yoavbls, @yoshiken, @yusukegoto and the support of over 500 organizations who subscribed to our hosted version and by that sponsor the team's work.

### Parameters

- Parameter UI improvements:
  - Support for multi-select in dropdown (and query dropdown) parameters.
  - Support for dynamic values in date and date-range parameters.
  - Search dropdown parameter values.
  - New UX for applying parameter changes in queries and dashboards.
- Allow using Safe Parameters in visualization embeds and public dashboards. Safe Parameters are any parameter type except for the a text parameter (dropdowns are safe).

### Data Sources

- New Data Sources: Couchbase, Phoenix and Dgraph.
- New JSON data source (and deprecated old URL data source).
- Snowflake: update connector to latest version.
- PostgreSQL: show only accessible tables in schema.
- BigQuery:
  - Correctly handle NaN values.
  - Treat repeated fields as rrays.
  - [BigQuery] Fix: in some queries there is no mode field
- DynamoDB:
  - Support for Unicode in queries.
  - Safe loading of schema.
- Rockset: better handling of query errors.
- Google Sheets:
  - Support for Team Drive.
  - Friendlier error message in case of an API error and more reliable test connection.
- MySQL:
  - Support for calling Stored Procedures and better handling of query cancellation.
  - Switch to using `mysqlclient` (a maintained fork of `Python-MySQL`).
- MongoDB: Support serializing Decimal128 values.
- Presto: support for passwords in connection settings.
- Amazon Athena: allow to specify custom work group.
- Query Results: querying a column with a dictionary or array fails
- Clickhouse: make sure we don't show password in error messages.
- Enable Cassandra support by default.

### Visualizations

- Charts:
  - Fix: legend overlapping chart on small screens.
  - Fix: Pie chart not rendering when series doesn't exist in options.
  - Pie Chart: add option to set direction of slices.
- WordCloud: rewritten to support new options (provide frequency in query, limits), scale when resizing, handle long words and more.
- Pivot Table: support hiding totals.
- Counters: apply formatting to target value.
- Maps:
  - Ability to customize marker icon and color.
  - Customization options for Choropleth maps.
- New Visualization: Details View.

### **UX**

- Replace blank screen with a loading indicator when the application is doing its first load.
- Multiple improvements to dashboards editing: auto-save, grid markings and better refresh indicator.
- Admin can now edit user's groups from the user page.
- Add keyboard shortcut (Ctrl/Cmd+Shift+F) to trigger query formatting.

### API

- Query Result API response minimized to only required fields when called with a non user API key.
- Prefer API key over cookies in authentication.
- User can now regenerate Query API Key.

### Other Changes

- Sends CSP headers to prevent various kinds of security attacks via the browser. Might break unusual usages and embeds of Redash.
- New Failed Scheduled Queries email report (can be enabled from organization settings screen).
- Deprecated HipChat Alert Destination.
- Add options to hide different parts of a Visualization embed UI (parameters, title, link to query).
- Support multi-byte search for query names and descriptions (needs to be enabled in Organization settings screen).
- CSV query results download: correctly serialize booleans and date values.
- Dashboard filters now collect values from all widgets with the same filter.
- Support for custom message and description in alert notifications (currently disabled behind a feature flag until we improve the alert UX).

### Bug Fixes

- Fix: adding widget to dashboard from a query page is broken.
- Fix: default time format option was wrong.
- Fix: when too many errors of a scheduled queries occur it causes an OverflowError.
- Fix: when forking a query maintain the same visualizations order.

## v7.0.0 - 2019-03-17

We're trying a new format for the CHANGELOG in this release. Focusing on the bigger changes, but for whoever interested, you can see all the changes [here](https://github.com/getredash/redash/compare/v6.0.0...master).

Besides all the features, bug fixes and improvements listed below we managed to convert a large portion of Redash's frontend code from Angular.js to React. You can see status in [#3071](https://github.com/getredash/redash/issues/3071).

This release was made possible with the help of 34 contributors. 🙇‍♂️

### Data Sources

- **All data source options are now encrypted in the database.** By default the encryption uses the `REDASH_COOKIE_SECRET` value (`redash.settings.COOKIE_SECRET`), but you can specify a different value by setting the `REDASH_SECRET_KEY` environment variable value. Note that you need to set this _before_ doing the upgrade.
- New Data Sources: Uptycs and Apache Drill.
- Snowplow: is now enabled by default & supports region setting.
- Elasticsearch: add support for Amazon Elasticsearch IAM authentication (with IAM profile or key/secret pair).
- PostgreSQL: add support for serializing range values.
- Redshift: remove duplicate column information for late-binding views.
- Athena: load all databases (using pagination).
- BigQuery: correctly handle temp tables with no schema field.
- Jira (JQL): support for fetching all records with pagination.
- Prometheus: fix schema loading and add support for query range.

### In-app Help

You can now open the [Knowledge Base](https://redash.io/help) inside the application. We also added a few "help triggers" in the app, that will open the Knowledge Base in context of what you're currently doing.

### Parameters

- **Dashboard Parameters**: We improved the flow of adding queries with parameters to dashboards and now give you full control over how parameters are mapped. You no longer have to make sure all parameters have the same name or use the `Global` checkbox. We also added new options, like keeping the parameter local to the widget or setting a static value. [Read more in our Knowledge Base →](https://redash.io/help/user-guide/querying/query-parameters#Parameter-Mapping-on-Dashboards)
- We added server side validation of parameter values for all parameter types, except for parameters of `text` type. All validated parameter types are considered safe. When a query is using safe parameters (or no parameters at all), View Only users can refresh it.
- Refreshing safe queries is done using the new results API endpoint, which takes only a query ID (and optionally parameter values) and does not need the query text.

### Query Editor Improvements

- Run only the highlighted query text: hit Execute after highlighting a portion of your query and only the selected portion will be sent to the database. This is useful for testing sub-SELECT statements and CTE's.
- Improved auto complete: add a dot . after a table name in the query editor and auto complete will only suggest columns on that table.
- Autosave parameter configuration changes.
- YAML syntax support (for data sources like Yandex Metrica).

### Improved Query Scheduler

The Query Scheduler got a face lift and some new options: you can pick a day for a weekly schedule to run on and also set an end date after which the query will no longer execute on schedule.

### Data Sources

We added Apache Drill, Uptycs and a new JSON data source. Also fixed a few bugs in Athena's query runner and others.

### User Management

The users page got revamped with a new look and feel and few new features:

- An indication when a user was last active.
- Show if an invited user hasn't finished the setup process yet (Pending Invitations section).
- You can now generate a new API key for users, if there's a concern it was compromised.

### Admin

- New Celery queues status screens, replacing the old Queries Status and better reflecting the status of running queries.
- Make the queue name for schema refresh job configurable. The default used to be hard coded `schemas`, which is not available on all setups. Now it's `celery`.
- The `gevent` library is installed by default, and you can now setup gunicorn to use `gevent` based workers.
- New Docker entrypoint command to do a health check for a worker process.
- Flask-Admin is no longer setup or supported.

### Other Changes

- New Alert destination: Google Hangouts Chat.
- When downloading results from the results API it will set a user friendly filename for the downloaded file.
- Archived Queries section added to the queries list.

### Bug Fixes

- Fixed: fork query does not fork tables but instead adds default table.
- Fixed: when deleting a visualization, any widget using it was left empty on the dashboard.
- Fixed: issues with Query Editor resizing on new versions of Chrome.
- Fixed: issues with exporting dictionaries to Excel.
- Fixed: Cohort visualization gets stuck when passing string values.
- Fixed: use series name for Pie chart label.
- Make sure Flask app created in Celery's worker process (could cause some query runners to get stuck while running queries).

## v6.0.0 - 2018-12-16

v6.0.0 release version. Mainly includes fixes for regressions from the beta version.

This release had contributions from 5 people: @rauchy, @denisov-vlad, @arikfr, @ariarijp, and @gabrieldutra. Thank you, everyone 🙏

### Changed

- #3183 Make refresh_queries less noisey in logs. @arikfr

### Fixed

- #3163 Include correct version in production builds. @rauchy
- #3161 Clickhouse: fix int() conversion error. @denisov-vlad
- #3166 Directly using record_event task requires timestamp. @arikfr
- #3167 Alert.evaluate failing when the column is missing. @arikfr
- ##3162 Remove API permissions for users who have been disabled. @rauchy
- #3171 Reject empty query name. @ariarijp
- #3175, #3186 Fix disable error message. @rauchy, @gabrieldutra
- #3182 [Redshift] support for schema names with dots. @arikfr
- #3187 Safely create_app in Celery code (try to fetch current_app first). @arikfr

### Other

- #3155 Add DB Seed to Cypress and setup Percy. @gabrieldutra
- #3180 Remove coverage from pytest terminal output. @rauchy

## v6.0.0-beta - 2018-12-03

This release was 2 months in the making and it is full with good stuff!

- We have 5 new data sources: Databricks, IBM DB2, Kylin, Druid and Rockset. ⌗
- There are fixes and improvements to 11 existing data sources (MySQL, Redshift, Postgres, MongoDB, Google BigQuery, Vertica, TreasureData, Presto, ClickHouse, Google Sheets and Google Analytics).
- The Query Results data source can now load cached results, just use the `cached_query_` prefix instead of `query_`.
- On the visualizations front we added a Heatmap visualization and did updated the table and counter visualizations.
- Alerts got some fixes and a new destination: PagerDuty.
- If the live autocomplete in the code editor annoys you, you can disable it now (although we're working to make it better, see #3092).
- Fast queries will now load faster. 🏃‍♂️
- We improved the layout of visualizations and content on smaller screen sizes. 📱
- For those of you who like sharing, you can now enable the ability to share ownership of queries and dashboards and let others to edit them. Check the Settings page to enable this feature.

There were also important changes to the code and infrastructure:

- More components moved to React.
- We switched to Webpack 4 with the help of @dmonego.
- We upgraded to Celery 4 with the help of @emtwo, @jezdez, @mashrikt and @atharvai.
- We started moving towards Python 3 for our backend. The first step was to make sure our code pass basic sanity tests with Flake 8, which was implemented by @cclauss.
- We improved our testing on the frontend by adding setup for Jest tests and E2E testing using Cypress (@gabrieldutra).
- Each pull request now gets a deploy preview using Netlify to easily test frontend changes.

This is just a summary, you're welcome to review the full list below. ⬇

This release had contributions from 38 people: @arikfr, @kravets-levko, @jezdez, @kyoshidajp, @kocsmy, @alison985, @gabrieldutra, @washort, @GitSumito, @emtwo, @rauchy, @alexanderlz, @denisov-vlad, @ariarijp, @yoavbls, @zhujunsan, @sjakthol, @koooge, @SakuradaJun, @dmonego, @Udomomo, @cclauss, @combineads, @zaimy, @Trigl, @ralphilius, @jodevsa, @deecay, @igorcanadi, @pashaxp, @hoangphuoc25, @toph, @burnash, @wankdanker, @Yossi-a, @Rovel, @kadrach, and @nicof38. Thank you, everyone 🙏

### Added

- #2747, #3143 Add a new Databricks query runner. @alison985, @jezdez, @arikfr
- #2767 Add ability to add viz to dashboard from query edit page. @alison985, @jezdez
- #2780 Add a query autocomplete toggle. @alison985, @jezdez, @arikfr
- #2768 Add authentication via JWT providers. @SakuradaJun
- #2790 Add the ability to sort favorited queries, paginate the dashboard list and improve UI inconsistencies. @jezdez
- #2681 Add ability to search table column names in schema browser. @alison985
- #2855 Add option to query cached results. @yoavbls
- #2740 Add ability for extensions to add periodic tasks. @emtwo
- #2924 Google Spreadsheets: Add support for opening by URL. @alexanderlz
- #2903 Add PagerDuty as an Alert Destination. @alexanderlz
- #2824 Add support for expanding dashboard visualizations. @sjakthol
- #2900 Add ability to specify a counter label. @ralphilius
- #2565 Add frontend extension capabilities. @emtwo
- #2848 Add IBM Db2 as a data source using the ibm-db Python package. @nicof38
- #2959 Add option to auto reload widget data in shared dashboards. @arikfr
- #2993 Add page size settings. @kyoshidajp
- #2080 New Heatmap chart visualization with Plotly. @deecay
- #2991 Show users in CLI group list. @GitSumito
- #2342 New SQLPARSE_FORMAT_OPTIONS setting to configure query formatter. @ariarijp
- #3031 Add some tests for Query Results. @ariarijp
- #2936 Add Kylin data source. @Trigl
- #3047 Add Druid data source. @rauchy
- #3077 New user interface for the feature flag of the share edit permissions feature. @arikfr
- #3007 Add permissions to the result of "manage.py groups list" command. @Udomomo
- #3088 Add get_current_user() fuction for the Python query runner. @kyoshidajp
- #3114 Add event tracking to autocomplete toggle. @arikfr
- #3068 Add Rockset query runner. @igorcanadi, @arikfr
- #3105 Display frontend version. @rauchy

### Changed

- #2636 Rewrite query editor with React. @washort, @arikfr
- #2637 Convert edit-in-place component to React. @washort, @arikfr
- #2766 Suitable events are now being recorded server side instead of in the frontend. @alison985, @jezdez
- #2796 Change placement (right/bottom) of chart legend depending on chart width. @kravets-levko
- #2833 Uses server side sort order for tag list and show count of tagged items. @jezdez
- #2318 Support authentication for the URL data source. @jezdez
- #2884 Rename Yandex Metrika to Metrica. @jezdez
- #2909 MySQL: hide sys tables. @arikfr
- #2817 Consistently use simplejson for loading and dumping JSON. @jezdez
- #2872 Use Plotly's function to clean y-values (x may be category or date/time). @kravets-levko
- #2938 Auto focus tag input. @kyoshidajp
- #2927 Design refinements for queries pages. @kocsmy
- #2950 Show activity status in CLI user list. @GitSumito
- #2968 Presto data source: setting protocol (http/https), safe loading of error messages. @arikfr
- #2967 Show groups in CLI user list. @GitSumito
- #2603 MongoDB: Update requirements to support srv. @arikfr
- #2961 MongoDB: Skip system collections when loading schema. @arikfr
- #2960 Add timeout to various HTTP requests. @arikfr
- #2983 Databricks: New logo, updated name and enabled by default. @arikfr
- #2982 Table visualization: change default size to 25 and add more size options. @arikfr
- #2866 Redshift: Hide tables the configured user cannot access. @sjakthol
- #3058 Mustache: don't html-escape query parameters values. @kravets-levko
- #3079 Always use basic autocomplete, as well as the live autocomplete. @arikfr
- #3084 Support tel://, sms://, mailto:// links in query results. @zhujunsan
- #3083 Clickhouse: Add WITH TOTALS option support. @denisov-vlad
- #3063 Allow setting colors for bubble charts. @toph
- #3085 BigQuery: Switch to Standard SQL as the default. @kyoshidajp
- #3094 Tags autocomplete: Show note when creating a new label. @kravets-levko
- #2984 Autocomplete toggle improvements. @arikfr
- #3089 Open new tab when forking a query. @kyoshidajp
- #3126 MongoDB: add support for sorting columns. @arikfr
- #3128 Improve backoff algorithm of query results polling to speed it up. @arikfr
- #3125 Vertica: update driver & add support for connection timeout. @arikfr
- #3124 Support unicode in Postgres/Redshift schema. @arikfr
- #3138 Migrate all tags components to React. @kravets-levko
- #3139 Better manage permissions modal. @kocsmy
- #3149 Improve tag link colors and fix group tags on Users page. @kocsmy
- #3146 Update, replace and fix new alert destination logos so it fits better. @kocsmy
- #3147 Add and improve recent db logos that didn't fit in size properly. @kocsmy
- #3148 Fix label positioning on no found screen. @kocsmy
- #3156 json_dumps: add support for serializing buffer objects. @arikfr

### Fixed

- #2849 Fix invalid reference to alert.to_dict() in webhook. @wankdanker
- #2840 Improve counter visualization text scaling. @kravets-levko
- #2854 Widget titles are no longer rendered wrong on public dashboards. @kravets-levko
- #2318 Removed redundant exception handling in data sources since that's handled in the query backend. @jezdez
- #2886 Fix Javascript build that broke because registerAll tried to run EditInPlace component. @arikfr
- #2911 Don’t show “Add to dashboard” in dropdown to unsaved queries. @jezdez
- #2916 Fix export query results output file name. @gabrieldutra
- #2917 Fix output file name not changing after rename query. @gabrieldutra
- #2868 Address edge case when retrieving Glue schemas for Athena data source. @kadrach
- #2929 Fix: date value in a filter is duplicated. @combineads
- #2875 Unbreak charts with long legend break in horizontal mode. Update plotly.js. @kravets-levko
- #2937 Fix event recording in admin API backend. @kyoshidajp
- #2953 Minor fixes for the Clickhouse data source. @denisov-vlad
- #2941 Bring back fix to Box plot hover. @arikfr
- #2957 Apply missing CSS classes to EditInPlace component. @arikfr
- #2897 Show "Add description" only after saving the query. @arikfr
- #2922 Query page layout improvements for small screens. @kravets-levko
- #2956 Clickhouse: move timeout to params. @denisov-vlad
- #2964 Fix no tags shown when having empty set. @gabrieldutra
- #2757 Use full text search ranking when searching in list views. @jezdez
- #2969 Query Results data source: improved errors, quoted column names. @arikfr
- #2906 Preventing open redirection in loging process. @kyoshidajp
- #2867 TreasureData: Deduplicate column names. @zaimy
- #2994 Fix scheme of various URLs from http to https. @kyoshidajp
- #2992 Fix an invalid prop type warning in new version notifier. @kyoshidajp
- #3022 Fix Toolbox covering part of a chart. @kravets-levko
- #2998 Fix charts losing responsive features after refreshing the dashboard. @kravets-levko
- #3034 Postgres: handle NaN/Infinity values. @kravets-levko
- #2745 Sort columns with undefined values. @Yossi-a
- #3041 Sort CLI output of lists. @GitSumito
- #2803, #3006 Address various tag display issues on query list page. @kocsmy, @alison985
- #3049 Fix edit-in-place component which ignored isEditable flag and didn't work on Groups page. @kravets-levko
- #2965 Google Analytics: Fix crash when no results are returned. @alexanderlz
- #3061 Fix table visualization so that the horizontal scrollbar is not be always visible. @kravets-levko
- #3076 Add white-space padding to separators in the footer. @burnash
- #2919 Fix URL data source to not require a URL. @arikfr
- #3098 Force AngularJS to update query editor properly. @washort
- #3100 Delete redundant regex segment in query result frontend. @zhujunsan
- #2978 Prevent the query update timestamp from changing when it is linked to new query results. @rauchy
- #3046 Fix query page header. @kravets-levko
- #3097 Mongo: Fix collection fields retreival bug when Views are present. @jodevsa
- #3107 Keep query text in local state for now. @washort
- #3111 Fix mobile padding issues on Query results. @kocsmy
- #3122 Show menu divider only if query is archived. @jezdez
- #3120 Fix tag counts for dashboards and queries. @jezdez
- #3141 Fix schema refresh to work on MySQL 8. @hoangphuoc25
- #3142 Fix: editing dashboard title results in the visualizations being replaced by the loading markers. @kravets-levko

### Other

- #2850 The setup scripts are now based on Ubuntu 18.04 LTS and Docker. @pashaxp, @arikfr
- #2985 Add Jest based tests to our stack. @arikfr
- #2999 Add netlify configuration. @arikfr
- #3000 Initial Cypress based E2E test infrastructure. @gabrieldutra
- #2898 Move Ant styles into a central location. @arikfr
- #2910 Fix webpack build error about BigMessage. @jezdez
- #2928 Speed up builds by skipping installing requirements_all_ds.txt in CI unit tests. @arikfr
- #2963 Fix tarball build failure. @emtwo
- #2996 Fix setup.sh failures when run as root. @arikfr
- #2989 Rearrange make targets. @koooge
- #3036 Update Flask-Admin to 1.5.2. @yoavbls
- #2901 Fix documentation links. @kravets-levko
- #3073 Remove only Redash containers in clean Make task. @ariarijp
- #3048 Remove pytest-watch dependency to workaround an issue with watchdog. @rauchy
- #2905 Update development docker-compose.yml file to use latest Redis and Postgres servers and specify working volume explictly. @Rovel
- #3032 Makefile: Add make targets for test. @koooge
- #2933 Switch to Webpack 4. @dmonego
- #2908 Update setup files. @arikfr
- #2946 Update snowflake_connector_python version. @arikfr
- #2773 Upgrade to Celery 4.2.1. @emtwo, @jezdez
- #2881 CircleCI: Make flake8 tests pass on Legacy Python and Python 3. @cclauss
- #2907 Remove unused dependencies (honcho, wsgiref). @arikfr
- #3039 Build docker image on master branch. @arikfr
- #3106 Fix registerAll failures after minification. @arikfr

## v5.0.2 - 2018-10-18

### Security

- Fix: prevent Open Redirect vulnerability.

## v5.0.1 - 2018-09-27

### Added

- Added support for JWT authentication (for services like Cloudflare Access or Google IAP).

### Changed

- Upgraded Celery version to 3.1.26 to make upgrade to Celery 4 easier.

## v5.0.0 - 2018-09-21

Final release for V5. Most of the changes were already in the beta release of V5, but this includes several fixes along
with UI improvements.

🙏 Thanks to @arikfr, @jezdez, @kravets-levko, @alison985, @kocsmy, @yossi-a, @tdsmith, @nasmithan, @jrbenny35, @sjakthol, @ariarijp and @combineads who contributed to this release.

### Security

- Fix: don't expose Google OAuth client secret. @arikfr

### Changed

- Improve mobile rendering of dashboards and queries. @kocsmy
- UI improvements for favorites and empty state. @arikfr
- Remove unnecessary X at the end of the query search. @kocsmy
- Add server-side sorting to dashboard list. @jezdez
- Sort queries in descending order. @jezdez
- Throw error when non-owner tries to add a user to dashboard permissions. @alison985
- Propagate query execution errors from Celery tasks properly. @alison985
- Reload the route when using the app header search input. @jezdez

### Fixed

- Fix: BigQuery default location is null and not US. @arikfr
- Fix: query embeds are broken. @arikfr
- Fix: typo in Celery log foramt. @ariarijp
- Use QuerySerializer in outdated queries list. @jezdez
- Fix: sometimes widgets are getting zero height. @kravets-levko
- Athena: Switch to simple_json to serialize NaN/Infinity values as nulls. @kravets-levko, @jezdez
- Fix: queries with parameters with no value breaking the scheduler. @arikfr
- Fix: MongoDB query results parser didn't support unicode keys. @arikfr
- Fix: Google Analytics schema wasn't loading in some cases. @arikfr
- Fix: date/time parameters not working as global param @kravets-levko.
- Fix: Widgets crumble when trying to move / resize a widget. @kravets-levko
- Fix: handling rows with "length" field with forOwn method. @yossi-a
- Fix: query selection not working on alert page. @sjakthol
- Fix: query_results for Embedded Parameters (removed deprecated to_dict function). @nasmithan
- Fix: unicode not supported in dashboard search. @combineads
- Fix: unicode not supported in users search. @arikfr

### Other

- Add test for using saved parameters in scheduled queries. @alison985
- Minor code smell cleanup. @jezdez
- Update QueryResultListResource docstring. @tdsmith
- Switch to CirlceCI 2.0 @jrbenny35, @arikfr
- Remove unnecessary init methods. @jezdez

## v5.0.0-Beta - 2018-08-06

This is the first beta of the V5 release (and hopefully the last one). This version includes a lot of exciting new additions along with bug fixes and other changes.

Some notable changes:

- Extensive work on parameters UI:
  - New Date Range parameter type.
  - UI for creating new parameters.
  - Support for Now/Today as default value of date/time parameter.
- Tagging and favorites ⭐️ support for queries and dashboards.
- Users list page was improved (search, additional information) and you can now disable users.
- Query editor improvements: additional keyboard shortcuts and support for searching in query text.
- Visualizations improvements: option to select colors of pie chart sectors, X Axis type auto detect and option to format values, labels and tooltips.
- Data Sources:
  - Support for Yandex Metrika and AppMetrika.
  - BigQuery: location property support and schema will load all tables now.
  - Elasticsearch: stop sending source_content_type parameter which wasn't supported in older versions.
- Started migrating the frontend codebase to React.

And much more!

🙏 Thanks to @kravets-levko, @arikfr, @ariarijp, @alison985, @kyoshidajp, @kocsmy, @denisov-vlad, @deecay, @yuua, @emtwo, @Pablohn26, @sieben, @atharvai, @matsumo, @tdawber, @innovia, @gabrieldutra, @coreyhuinker, @maxv, @sjakthol, @mtrbean and @washort who contributed to this release!

### Added

- #2712: Date/Time Range parameter type (@kravets-levko)
- #2482: Add support for ChatWork Alert Destination. (@matsumo)
- #2678: Explicit "Add Parameter" Button in Query Editor. (@kravets-levko)
- #2513: Add location property to BigQuery data source settings. (@kyoshidajp)
- #2616: Pie chart: support setting pie chart sector colors. (@kravets-levko)
- #2697: Date/Time parameters: support for "Now" as default value. (@kravets-levko)
- #2693: Enable search function in Query Editor. (@arikfr)
- #2573: Tagging and favorites for Queries and Dashboards (@arikfr)
- #2640: Keyboard shortcut to collapse query editor/schema browser (@kravets-levko)
- #2674: Add support for the Chrome Logger extension (@arikfr)
- #2653: Add redash db size to status page (@alison985)
- #2669: Store Athena query id with result metadata (@tdawber)
- #2546: Configuration for incorporating React components (@washort)
- #2533: New datasource: Yandex Metrika & AppMetrika (@denisov-vlad)
- #2536: Chart: formats for values, labels and tooltips (@kravets-levko)
- #2560: Introduce Policy object (@arikfr)
- #2380: Admin should be able to disable a user (@kravets-levko)
- #2509: Show custom date format on settings page (@kyoshidajp)

### Changed

- #2715: Improve users list page (@arikfr)
- #2710: Update Ant variables to fit Redash's style (@kocsmy)
- #2709: Move format button next Add New Param button. (@arikfr)
- #2664: Dashboard shows a spinner when query failed to load (@kravets-levko)
- #2626: Show real status when loading cached query result (@kravets-levko)
- #2663: Set column name implicitly when column name is blank (@ariarijp)
- #2695: Improve Date/DateTime type parameters (@kravets-levko)
- #2694: Block users with disposable email addresses (@arikfr)
- #2687: YAML: changed load to safe_load (@denisov-vlad)
- #2514: Update value parsing for google spreadsheets source (@atharvai)
- #2570: fixes query pagination alignment (@alison985)
- #2584: keep query result pagination out of scroll (@alison985)
- #2647: Improve Script Query Runner (@ariarijp)
- #2583: Query header improvements on widgets (@kocsmy)
- #2671: Save some space (@kocsmy)
- #2658: delaying schema filtering to improve responsiveness (@alison985)
- #2648: Update datasource documentation links (@Pablohn26)
- #2613: Improve Script Query Runner (@ariarijp)
- #2619: data source sort case insensitive (@alison985)
- #2604: Improve Google Spreadsheets Query Runner (@ariarijp)
- #2542: Closes #2541: x-axis improvements. (@emtwo)
- #2590: Remove redundant variables (@ariarijp)
- #2585: Show data only mode: allow to add and delete visualizations (@kravets-levko)
- #2549: Allow get_tables to see views and v10-style partitioned tables (@coreyhuinker)
- #2568: sort datasources alphabetically (@alison985)
- #2444: feat: show error if saml response cannot be parsed (@sjakthol)
- #2554: Display name to be delete (@kyoshidajp)
- #2510: Display confirmation dialog when deleting a item (@kyoshidajp)
- #2518: Design improvements (@kocsmy)
- #2520: Filter data sources in a data source input area (@kyoshidajp)

### Fixed

- #2722: Elasticsearch: Don't send source_content_type parameter. (@arikfr)
- #2719: Remove closing input tags (@maxv)
- #2458: Get all tables in the BigQuery (@kyoshidajp)
- #2698: Make sure we return distinct data source values (@arikfr)
- #2315: Fix: pyHive type matches (@yuua)
- #2638: Dashboard stops rendering when adding widget with empty query (@kravets-levko)
- #2610: Fix export query results output file name (@gabrieldutra)
- #2574: commit query result to db before evaluating alerts (@mtrbean)
- #2580: add break-word wrap to add/edit text box on dashboard (@alison985)
- #2578: Fix connection error when you run "create_tables" (@ariarijp)
- #2572: remove extra menu line if query is archived (@alison985)
- #2526: Fix pivot hide control in dashboards (@deecay)
- #2511: Fixing signed_out.html template (@kocsmy)
- #2523: Frontend: fix boolean field with null value display as null. (@innovia)

### Other

- #2682: Add Zeit's now support to have preview builds for every PR (@arikfr)
- #2668: Upgrade bootstrap script to Redash 4.0.1 (@ariarijp)
- #2639: Add tests for SpreadSheets (@ariarijp)
- #2635: Add tests for Query Results (@ariarijp)
- #2537: Remove trailing semicolon (@sieben)

## v4.0.1 - 2018-05-02

### Added

- Log user's screen resolution. @arikfr

### Changed

- [Redshift] fix the order of columns in the schema browser. @akiray03
- Improve dashboard refresh UX: show previous data while refreshing. @arikfr

### Fixed

- Disable fork button to view_only users. @tonyjiangh
- Hide overflowing data source and alert destination names. @kocsmy
- Login pages were broken on mobile. @kocsmy
- Cohort visualization wasn't rendering if value wasn't properly detected as date. @kravets-levko
- Dashboard filters setting wasn't persisting. @arikfr
- Display nulls and empty values as blank in table numeric fields. @chriszs
- Date column on alerts page is labeled "Created By". @dbravender
- Bootstrap script was breaking due to incompatability with pip 10. @ariarijp

### Other

- Updated README. @kocsmy

## v4.0.0 - 2018-04-16

### Added

- MatterMost alert destination. @alon710
- Full screen view on map visualizations. @deecay
- Choropleth map visualization 🗺. @kravets-levko
- Report Celery queue size. @arikfr
- Load dashboard refresh rate from URL. @arikfr
- Configuration for query refresh intervals. @arikfr

### Changed

- TreasureData: improve query failure message. @toru-takahashi
- Update botocore version (fixes an issue with loading Athena tables). @arikfr
- Changed Map visualization name to "Map (Markers)" to distinguish from the Choropleth one. @arikfr
- Use MongoClient for ReplicaSet connections. @fmy
- Update pymongo version to support newer MongoDB versions. @arikfr
- Changed "his" to "their" in user creation form success message. @tnetennba3
- Show friendly names in dynamic forms labels. @arikfr
- Render safe HTML by default in tables to remain backward compatible. @arikfr
- Apply time limit to alert status checking task. @arikfr
- Plotly: increase Y value accuracy. @arikfr
- close metadata database connection early in the execute query Celery task. @arikfr

### Fixed

- Query page layout gets messed up when clicking on "cancel" in "Do you want to leave this page?" dialog. @kravets-levko
- docker-entrypoint broke for other database names than "postgres". @valentin2105
- (BigQuery) UDF URI was used even if empty. @arikfr
- Show correct Box Plot chart hover data. @deeccay
- Fork button shows in data only view, but not working. @arikfr
- Saving widget sends too much data to the server, sometimes making dashboard save fail. @arikfr
- DynamoDB: always return counter as a number rather than string. @arikfr
- MSSQL: UUID fields were detected as booleans. @arikfr
- The whole dashboard page reloads when clicking on refresh. @arikfr
- Line chart with category x-axis: when some values missing, wrong hints displayed on hover. @kravets-levko
- Second Y-axis not displayed when stacking enabled. @kravets-levko
- Widget with empty contents had extra 40px of white space (paddings of container). @kravets-levko
- Add scrollbars to pivot table widgets. @kravets-levko
- Multiple performance, usability and auto-height related fixes to the dashboard rendering engine (also switched to GridStack). @kravets-levko
- Login form missing on LDAP logging page. @idalin
- Empty state: show connect data source link only to admins. @arikfr
- Dashboard "dancing" widgets (when auto-height enabled). @kravets-levko

### Other

- Webpack: ignore vim swap files. @deecay

## v4.0.0-rc.1 - 2018-03-05

### Added

- Configuration for query refresh intervals.
- [Prometheus] Support for range queries. @jubel-han
- Extensions system based on Python entrypoints. @jezdez
- Funnel visualization. @tonyjiangh
- UI to edit allowed Google OAuth domains. @arikfr
- Empty state for homepage, alerts, queries and dashboards pages. @kocsmy, @arikfr

### Changed

- Maintain widget's auto-height state until it's been resized by the user. @kravets-levko
- Change default table viz width from 4 to 3 columns. @kravets-levko
- When saving dashboard adding or removing widgets, save only modified widgets (with changed size and/or position). @kravets-levko
- Don't allow disabling Password based login if no SSO is enabled. @arikfr
- Always show login page, even if password based login disabled. @arikfr
- Upgrade `sqlparse` to 0.2.4. @ariarijp
- Make sure datetime/number columns in table visualization don't wrap. @kravets-levko
- Explicitly set order of tabs in settings page. @kravets-levko
- User can no longer change the type of a saved visualization. @kravets-levko
- Update docker-compose.yml to restart postgres/redis containers `unless-stopped`. @benmanns
- New default colors for chart visualizations. @kocsmy
- Updated design of all the authentication pages (login, forgot password, etc). @kravets-levko

### Fixed

- Glue schemas with more than 100 tables were showing only first 100 tables. @jezdez
- Long visualizations dind't render scrollbars on some browsers. @kravets-levko
- When the dataset was returning some columns name as non strings, table couldn't be rendered. @kravets-levko
- Missing logos for Prometheus and Snowflake. @kocsmy
- Render correct link to LDAP login on login page. @arikfr
- Sort widgets by column/row to make sure they are placed correctly. @arikfr
- Public dashboards were not rendered due to Javascript error. @kravets-levko

## v4.0.0-beta - 2018-02-14

### Added

- Massive update to the UI/UX of the whole application. @kocsmy, @kravets-levko, @arikfr
- Flexible dashboard layout: resize widgets both vertically and horizonally. @kravets-levko
- Configuration and new options for the table visualization. @kravets-levko
- API to return internal usage events. @arikfr
- Add an option to set a common prefix to the backend logs. @arikfr
- [MongoDB] support nested fields in results. @arikfr
- Cohort visualization: add options and fix rendering logic. @kravets-levko
- Table visualization: `URL` column type. @kravets-levko
- Table visualization: `Image` column type. @kravets-levko
- [BigQuery] show amount of data scanned. @arikfr
- Make dashboard refresh intervals configurable. @arikfr
- Button to insert table/column name from schema into the query text. @kravets-levko
- [Athena] show amount of data scanned. @washort
- [Salesforce] Add setting to set the API version. @mayconbordin
- UI for configuration options (auth, date format, etc). @arikfr
- CLI command to create the root user. @kyoshidajp
- [Redshift] support for loading late binding views in schema browser. @tonyjiangh
- Show user's profile picture and load it from Google when using Google OAuth. @kyoshidajp
- CockroachDB query runner. @yershalom
- MAPD query runner. @cdessanti
- Pie chart: show subplot titles. @deecay

### Changed

- Make trusted header authentication compatible with multiorg mode. @sjakthol
- Update AWS RDS certificate bundle. @arikfr
- Add Prometheus to the default query runners list. @arikfr
- [Athena] update botocore version to support Glue. @arikfr
- Support for quotes passwords in the Redis and Postgres connection URLs. @javier-sanz
- Change the way static assets are served. @arikfr
- [BigQuery] Properly handle RECORD fields in schema (show the nested fields). @arikfr
- Upgrade to Celery 3.1.25 in preparation to Celery 4. @jezdez
- Remove loading indicator when updating query parameter value (before executing). @kravets-levko
- Improvements to the chart visualization (see #2156 for details). @kravets-levko
- Start searching for queries immediately instead of waiting for 3 characters. @kyoshidajp
- Make all references to Elasticsearch be properly capitalized. @kakakakakku
- Use PostgreSQL's FTS/tsvector type for query searches. @jezdez
- [Redshift] Make sslmode configurable. @sjakthol
- Allow passing options to tests Docker command. @arikfr
- Improve error handling mechanism and make error pages friendlier. @kravets-levko, @kocsmy, @arikfr
- Make LDAP settings names more consistent. @gramakri
- [Oracle] support for non SELECT queries. @doddjc21
- Admin can no longer remove themselves from the built-in groups. @negibouze
- Update pie charts font style. @deecay
- Upgrade psycopg2 for support PostgreSQL 10.0. @kyoshidajp
- Convert all stylesheets to LESS. @kravets-levko
- [Elasticsearch] Collect doc_count field from aggregation. @arjan
- Switch to pytest. @jezdez
- Ensure email is case-insensitive. @miketheman
- [Redshift] change default SSL mode to prefer. @arikfr
- Return Redis memory usage in bytes for easier monitoring. @kakakakakku
- create_db command in docker-entrypoint waits for Postgres to become available first. @ariarijp
- [Elasticsearch] set source_content_type on ES queries to support Elasticsearch 6.0. @alexdrans
- Show `-` instead of `Invalid Date` for null values given to `dateTime` filter. @kyoshidajp

### Fixed

- Parameters list was resetting when adding a new parameter. @arikfr
- Don't escape values in non-html columns. @kravets-levko
- Commit SAML user group assignment to the database. @sjakthol
- Update correct settings in SAML settings form. @sjakthol
- Fix Google OAuth login in MULTIORG mode. @shinji19
- Strip annotation from query when path is specified in Script query runner. @ariarijp
- Fix filter headers when there are multiple rows of filters. @kocsmy
- Update query version when changing query data source. @washort
- Fix upgrade script to support changes in CircleCI. @rgjodekerken
- Don't show error indicators after submitting the user form. @bamboo-yujiro
- [Query Results] support unicode column names. @tonyjiangh
- Issue with Google OAuth caused by old pyOpenSSL version. @crooy
- Fix layout of outdated queries admin view. @bamboo-yujiro
- User can't download query results of a new query. @arikfr
- Typo in celery logs format. @ariarijp
- Handling whitespace characters in Query Results data source. @ariarijp
- [MySQL] Close cursor when cancellig the query. @jasonsmithj

## v3.0.0 - 2017-11-13

### Added

- Query Result data source (run queries on query results).
- Athena: option to load schema from Glue catalog. @myouju
- Allow running any command inside the container via the Docker entrypoint script. @jezdez
- Make invitation token max age configurable. @hhamalai
- Redshift: add support for the new ACM root CA.
- Redshift: support for Spectrum (external) tables. @atharvai
- MongoDB: option to set allowDiskUse in queries.
- Option to disable SQLAlchemy connection pool.
- Option to set a time limit on adhoc queries.
- Option to disable sending an invite to a new user.
- Azure SQL Data Warehouse query runner. @kitsuyui
- Prometheus query runner. @yershalom
- Option to set the Flask-Limiter storage engine.
- Option to set UnicodeWriter's error handling method. @fan-t-endo
- PostgreSQL: SSL configuration option. @TylerBrock
- Counter visualization: additional formatting options. @deecay
- Query based drop down parameter. @rohithmenon
- MySQL: multiple queries support & connection timeout.
- Ability to select all in multi-filter. @Posnet
- LDAP (Active Directory) support. @amarjayr

### Changed

- Copy parameters when forking a query. @kyoshidajp
- Prevent using Query API Key with refresh API (previously it was just failing).
- Reduce boilerplate in frontend code.
- Set auto focus in first input items. @kyoshidajp
- Update gunicorn to latest version.
- Make log format configurable.
- Sort series by name.
- Allow setting test file with Docker test run. @meinac
- Use outdated queries count stored already in Redis.
- Show links based on permissions the user have.
- Cassandra: update driver version. @yershalom
- Docker-Compose: update configuration to always restart services. @muddydixon
- Modernize Python 2 code to get ready for Python 3. @cclauss
- Cohort visualization: make it friendlier to use by better handle gaps in data, so it's easier to generate the data needed.
- Use a different markdown library. @alexmuller
- Salesforce: improve error messages we receive from the API. @akiray03
- Custom JS code visualization improvements. @deecay
- DQL: Update version to 0.5.24. @aterreno
- Cassandra: get_schema support for both C\* 2.x and 3.x, support for SortedSet type serialization. (@mfouilleul))
- Replace deprecated ng-annotate with babel plugin. @44px
- Update Python dependencies to recent versions. @alison985
- Bootstrap script: create /opt/redash directory only if it doesn't exist. @isomura
- Bootstrap script: make use of REDASH_BASE_PATH variable in setup script. @sylvain

### Fixed

- Require full data source access to fork a query.
- API key of one query could be used to get results of another one.
- Delete group id from user object when deleting the group. @kyoshidajp
- Sorting of X axis wasn't working for Box plot type visualizations. @deecay
- Exporting query results as excel was failing when one of the columns had array data. @kyoshidajp
- Show query editor's Archive/Publish Query drop-down only on saved queries. @cyriac
- Move misplaced configuration in docker-compose.production.yml. @yutannihilation
- MySQL: support UTF8 schema.
- TreasureData queries were failing when returning 0 rows.
- Use series color for Boxplot. @deecay
- Revoke permission should respect to given grantee and access type. @meinac
- Fixed eslint "Cannot read property 'length' of undefined" error. @kravets-levko
- Don't crash query editor when there are unclosed curly brackets.
- Error value in charts wasn't displayed if it was 0.
- Prevent line breaks in EditInPlace description when using Firefox. @alexmuller
- Queries#all_queries was sometimes returning wrong number of queries.
- record_event fails for API events.
- Cancel button on tasks admin page was broken.
- Remove deprecated cx_Oracle types. @queeno
- Textbox widgets were updating their value even when editor was cancelled. @alison985
- Collaborators couldn't edit visualizations or schedule.
- Use series color for error bar. @deecay
- Upgrade script was using the wrong restart command on new AMIs.

## v2.0.1 - 2017-10-22

This is a patch release, that adds support for Redshift ACM certificates (see #2044 for details).

## v2.0.0 - 2017-08-08

### Added

- [Cassandra] Support for UUID serializing and setting protocol version. @mfouilleul
- [BigQuery] Add maximumBillingTier to BigQuery configuration. @dotneet
- Add the propertyOrder field to specify order of data source settings. @rmakulov
- Add Plotly based Boxplot visualization. @deecay
- [Presto] Add: query cancellation support. @fbertsch
- [MongoDB] add \$oids JSON extension.
- [PostgreSQL] support for loading materialized views in schema.
- [MySQL] Add option to hide SSL settings.
- [MySQL] support for RDS MySQL and SSL.
- [Google Analytics] support for mcf queries & better errors.
- Add: static enum parameter type. @rockwotj
- Add: option to hide pivot table controls. @deecay
- Retry reload of query results if it had an error.
- [Data Sources] Add: MemSQL query runner. @alexanderlz
- "Dumb" recents option (see #1779 for details)
- Athena: direct query runner using the instead of JDBC proxy. @laughingman7743
- Optionally support parameters in embeds. @ziahamza
- Sorting ability in alerts view.
- Option to change default encoding of CSV writer. @yamamanx
- Ability to set dashboard level filters from UI.
- CLI command to open IPython shell.
- Add link to query page from admin view. @miketheman
- Add the option to write logs to STDOUT instead of STDERR. @eyalzek
- Add limit parameter to tasks API. @alexpekurovsky
- Add SQLAlchemy pool settings.
- Support for category type y axis.
- Add 12 & 24 hours refresh rate option to dashboards.

### Changed

- Upgrade Google API client library for all Google data sources. @ahamino
- [JIRA JQL] change default max results limit from 50 to 1000. @jvanegmond
- Upgrade to newer Plotly version. @deecay
- [Athena] Configuration flag to disable query annotations for Athena. @suemoc
- Ignore extra columns in CSV output. @alexanderlz
- [TreasureData] improve error handling and upgrade client.
- [InfluxDB] simpler test connection query (show databases requires admin).
- [MSSQL] Mark integers as decimals as well, as sometimes decimal columns being returned
  with integer column type.
- [Google Spreadsheets] add timeout to requests.
- Sort dashboards list by name. @deecay
- Include Celery task name in statsd metrics.
- Don't include paused datasource's queries in outdated queries count.
- Cohort: handle the case where the value/total might be strings.
- Query results: better type guessing on the client side.
- Counter: support negative indexes to iterate from the end of the results.
- Data sources and destinations configuration: change order of name and type (type first now).
- Show API Key in a modal dialog instead of alert.
- Sentry: upgrade client version.
- Sentry: don't install logging hook.
- Split refresh schemas into separate tasks and add a timeout.
- Execute scheduled queries with parameters using their default value.
- Keep track of last query execution (including failed ones) for scheduling purposes.
- Same view for input on search result page as in header. @44px
- Metrics: report endpoints without dots for metrics.
- Redirect to / when org not found.
- Improve parameters label placement. @44px
- Auto-publish queries when they are named (with option to disable; #1830).
- Show friendly error message in case of duplicate data source name.
- Don't allow saving dashboard with empty name.
- Enable strict checking for Angular DI.
- Disable Angular debug info (should improve performance).
- Update to Webpack 2. @44px
- Remove /forgot endpoint if REDASH_PASSWORD_LOGIN_ENABLED is false. @amarjayr
- Docker: make Gunicorn worker count configurable. @unixwitch
- Snowflake support is no longer enabled by default.
- Enable memory optimization for Excel exporter.

### Fixed

- Fix: set default values in options to enable 'default: True' for checkbox. @rmakulov
- Support MULTI_ORG again.
- [Google Spreadsheets] handle distant future dates.
- [SQLite] better handle utf-8 error messages.
- Fix: don't remove locks for queries with task status of PENDING.
- Only split columns with \_\_/:: that end with filter/MultiFilter.
- Alert notifications fail (sometime) with a SQLAlchemy error.
- Safeguard against empty query results when checking alert status. @danielerapati
- Delete data source doesn't work when query results referenced by queries.
- Fix redirect to /setup on the last setup step. @44px
- Cassandra: use port setting in connection options. @yershalom
- Metrics: table name wasn't found for count queries.
- BigQuery wasn't loading due to bad import.
- DynamicForm component was inserting empty values.
- Clear null values from data source options dictionary.
- /api/session API call wasn't working when multi tenancy enabled
- If column had no type it would use previous column's type.
- Alert destination details were not updating.
- When setting rearm on a new alert, it wasn't persisted.
- Salesforce: sandbox parameter should be optional. @msnider
- Alert page wasn't properly linked from alerts list. @alison985
- PostgreSQL passwords with spaces were not supported. (#1056)
- PivotTable wasn't updating after first save.

## v1.0.3 - 2017-04-18

### Fixed

- Fix: sort by column no longer working.

## v1.0.2 - 2017-04-18

### Fixed

- Fix: favicon wasn't showing up.
- Fix: support for unicode in dashboard tags. @deecay
- Fix: page freezes when rendering large result set.
- Fix: chart embeds were not rendering in PhantomJS.

## v1.0.1 - 2017-04-02

### Added

- Add: bubble charts support.
- Add "Refresh Schema" button to the datasource @44px
- [Data Sources] Add: ATSD query runner @rmakulov
- [Data Sources] Add: SalesForce query runner @msnider
- Add: scheduled query backoff in case of errors @washort
- Add: use results row count as the value for the counter visualization. @deecay

### Changed

- Moved CSV/Excel query results generation code to models. @akiray03
- Add support for filtered data in Pivot table visualization @deecay
- Friendlier labels for archived state of dashboard/query

### Fixed

- Fix: optimize queries to avoid N+1 queries.
- Fix: percent stacking math was wrong. @spasovski
- Fix: set query filter to match value from URL query string. @benmargo
- [Clickhouse] Fix: detection of various data types. @denisov-vlad
- Fix: user can't edit their own alert.
- Fix: angular minification issue in textbox editor and schema browser.
- Fixes to better support IE11 (add polyfill for Object.assign and show vertical scrollbar). @deecay
- Fix: datetime parameters were not using a date picker.
- Fix: Impala schema wasn't loading.
- Fix: query embed dialog close button wasn't working @r0fls
- Fix: make errors from Presto runner JSON-serializable @washort
- Fix: race condition in query task status reporting @washort
- Fix: remove \$\$hashKey from Pivot table
- Fix: map visualization had severe performance issue.
- Fix: pemrission dialog wasn't rendering.
- Fix: word cloud visualization didn't show column names.
- Fix: wrong timestamps in admin tasks page.
- Fix: page header wasn't updating on dashboards page @MichaelJAndy
- Fix: keyboard shortcuts didn't work in parameter inputs

### Other

- Change default job expiry times to: job lock expire after 12 hours (previously: 6 hours) and Celery task result object expire after 4 hours (previously: 1 hour). @shimpeko

## v1.0.0-rc.2 - 2017-02-22

### Changed

- [#1563](https://github.com/getredash/redash/pull/1563) Send events to webhook as JSON with a schema.
- [#1601][presto] friendlier error messages. (@aslotnick)
- Move the query runner unavailable log message to be DEBUG level instead of WARNING, as it was mainly confusing people.
- Remove "Send to Cloud" button from Plotly based visualizations.
- Change Plotly's default hover mode to "Compare".
- [#1612] Change: Improvements to the dashboards list page.

### Fixed

- [#1564] Fix: map visualization column picker wasn't populated. (@janusd)
- [#1597][sql server] Fix: schema wasn't loading on case sensitive servers. (@deecay)
- Fix: dashbonard owner couldn't edit his dashboard.
- Fix: toggle_publish event wasn't logged properly.
- Fix: events with API keys were not logged.
- Fix: share dashboard dialog was broken after code minification.
- Fix: public dashboard endpoint was broken.
- Fix: public dashboard page was broken after code minification.
- Fix: visualization embed page was broken after code minification.
- Fix: schema browser has dark background.
- Fix: Google button missing on invite page.
- Fix: global parameters don't render on dashboards with text boxes.
- Fix: sunburst / Sankey visualizations have bad data.
- Fix: extra whitespace created by the filters component.
- Fix: query results cleanup task was trying to delete query objects.
- Fix: alert subscriptions were not triggered.
- [DynamoDB] Fix: count(\*) queries were broken. (@kopanitsa))
- Fix: Redash is using too many database connections.
- Fix: download links were not working in dashboards.
- Fix: the first selection in multi filters was broken in dashboards.

### Other

- [#1555] Change sourcemaps to generate a sourcemap per module. (@44px)
- [#1570] Fix Docker Compose configuration for nginx. (@btmc)
- [#1582] Update Dockerfile to build frontend assets and update the folder ownership.
- Dockerfile: change the uid of the redash user to match host user uid.
- Update npm-shrinkwrap.json file to use http proctocol instead of git. (@deecay)

## v1.0.0-rc.1 - 2017-01-31

This version has two big changes behind the scenes:

- Refactor the frontend to use latest (at the time) Angular version (1.5) along with better frontend pipeline based on)
  WebPack.
- Refactor the backend code to use SQLAlchemy and Alembic, for easier migrations/upgrades.)

Along with that we have many fixes, additions, new data sources (Google Analytics, ClickHouse, Amazon Athena, Snowflake)
and fixes to the existing ones (mainly ElasticSearch and Cassandra).

When upgrading make sure to upgrade from version 0.12.0 and update your .env file:

1. If you have local PostreSQL database, you will need to update the URL from `postgresql://redash` to `postgresql:///redash`.
2. Remove the `REDASH_STATIC_ASSETS_PATH` definition.

Make sure to make these changes before running upgrade as otherwise it will fail.

We're releasing a new upgrade script -- see [here](https://redash.io/help-onpremise/maintenance/how-to-upgrade-redash.html) for details.

### Added

- [#1546](https://github.com/getredash/redash/pull/1546) Add: API docstrings (@washort)
- [#1504](https://github.com/getredash/redash/pull/1504) Add: global parameters for dashboards (Tyler Rockwood)
- [#1508](https://github.com/getredash/redash/pull/1508) [Jira JQL] Add: support custom JIRA fields and enhance value mapping (@sseifert)
- [#1530](https://github.com/getredash/redash/pull/1530) Add: Docker based developer workflow (Arik Fraimovich)
- [#1515](https://github.com/getredash/redash/pull/1515) [Python] Add: get_source_schema method (Vladislav Denisov)
- [#1512](https://github.com/getredash/redash/pull/1512) [Python] Add: define more safe_builtins (Vladislav Denisov)
- [#1513](https://github.com/getredash/redash/pull/1513) Add: get_by_id & get_by_name methods for Query and DataSource classes (Vladislav Denisov)
- [#1482](https://github.com/getredash/redash/pull/1482) [Cassandra] Add: schema browser support & explicit protocol version (@yershalom)
- [#1488](https://github.com/getredash/redash/pull/1488) [Data Sources] Add: Snowflake query runner (@arikfr)
- [#1479](https://github.com/getredash/redash/pull/1479) [ElasticSearch] Add: enable schema browser (@adamlwgriffiths)
- [#1475](https://github.com/getredash/redash/pull/1475) [Cassnadra] Added set_keyspace for easier query cassandra (@yershalom)
- [#1468](https://github.com/getredash/redash/pull/1468) [Datasources] Add: Amazon Athena query runner (@arikfr)
- [#1433](https://github.com/getredash/redash/pull/1433) [Charts] Add: errors bands in graphs (@luke14free)
- [#1405](https://github.com/getredash/redash/pull/1405) [Datasources] Add: simple Google Analytics query runner (@denisov-vlad)
- [#1409](https://github.com/getredash/redash/pull/1409) [Datasources] Add: Add query runner for Yandex ClickHouse (@denisov-vlad)
- [#1373](https://github.com/getredash/redash/pull/1373) Add: rate limit the login page (@AntoineAugusti)

### Changed

- [#1549](https://github.com/getredash/redash/pull/1549) Change: disable version counter for queries: (Arik Fraimovich)
- [#1548](https://github.com/getredash/redash/pull/1548) Change: improve UI in small resolution: (Arik Fraimovich)
- [#1547](https://github.com/getredash/redash/pull/1547) Change: Improve drafts UX (Arik Fraimovich)
- [#1540](https://github.com/getredash/redash/pull/1540) [MySQL] Change: faster retrieval of schema (Yaning Zhu)
- [#1517](https://github.com/getredash/redash/pull/1517) [ClickHouse] Change: convert UInt64 columns to integer type (Vladislav Denisov)
- [#1528](https://github.com/getredash/redash/pull/1528) [Vertica] Change: set longer read_timeout (lab79)
- [#1522](https://github.com/getredash/redash/pull/1522) Change: move package.json/webpack.config to root directory (Arik Fraimovich)
- [#1514](https://github.com/getredash/redash/pull/1514) [Athena] Change: enable query annotations (Gaurav Awadhwal)
- [#1525](https://github.com/getredash/redash/pull/1525) Change: update amazon linux bootstrap.sh (Karri Niemelä)
- [#1509](https://github.com/getredash/redash/pull/1509) [Presto/Athena] Change: remove special rule around public schema (@GAwadhwalAtlassian)
- [#1485](https://github.com/getredash/redash/pull/1485) Close #1453: more minimal notification of draft status for query/dashboard (@arikfr)
- [#1474](https://github.com/getredash/redash/pull/1474) [Cassandra] Change: test connection query (@yershalom)
- [#1464](https://github.com/getredash/redash/pull/1464) [Clickhouse] Change: use UTF-8 encoding for POST data (@jaykelin)
- [#1417](https://github.com/getredash/redash/pull/1417) Change: Replace Peewee with SQLAlchemy/Alembic (@arikfr, @washort)
- [#1458](https://github.com/getredash/redash/pull/1458) Change: switch from flask_script to click, add CLI unit tests and upgrade Flask version (@washort)
- [#1438](https://github.com/getredash/redash/pull/1438) [ElasticSearch] Change: use simplejson for better error descriptions (@adamlwgriffiths)
- [#1435](https://github.com/getredash/redash/pull/1435) Whitelisting more builtin primitives (@mattrobenolt)
- [#1376](https://github.com/getredash/redash/pull/1376) Change: upgrade the frontend stack (@arikfr, @luke14free)
- [#1429](https://github.com/getredash/redash/pull/1429) Add missing error check from #1402 (@adamlwgriffiths)
- [#1256](https://github.com/getredash/redash/pull/1256) Change: when forking a query, copy all visualizations (@ninneko)
- [#1421](https://github.com/getredash/redash/pull/1421) Change: [BigQuery] only specify useLegacySQL is it's True (@arikfr)
- [#1353](https://github.com/getredash/redash/pull/1353) Change: make draft status for queries and dashboards toggleable (@washort)
- [#1419](https://github.com/getredash/redash/pull/1419) Change: use redash.utils.json_dumps instead of json.dumps in Python query runner (@ehfeng)
- [#1402](https://github.com/getredash/redash/pull/1402) Change: correctly propagate ElasticSearch errors to the UI (@adamlwgriffiths)
- [#1371](https://github.com/getredash/redash/pull/1371) Change: display user's password reset link to the admin when mail server disabled (@vitorbaptista)

### Fixed

- [#1551](https://github.com/getredash/redash/pull/1551) Fix: flask-admin - exclude created_at/updated_at so models can be saved (Arik Fraimovich)
- [#1545](https://github.com/getredash/redash/pull/1545) [ElasticSearch] Fix: query fails when properties key is missing (hgs847825)
- [#1526](https://github.com/getredash/redash/pull/1526) [ElasticSearch] Fix for #1521 (Adam Griffiths)
- [#1521](https://github.com/getredash/redash/pull/1521) [ElasticSearch] Fix: wrong variable name. (Arik Fraimovich)
- [#1497](https://github.com/getredash/redash/pull/1497) Fix #16: when updating dashboard name refresh dashboards dropdown (@arikfr)
- [#1491](https://github.com/getredash/redash/pull/1491) Fix: DynamoDB test connection was broken (@arikfr)
- [#1487](https://github.com/getredash/redash/pull/1487) Fix #1432: delete visualization sends full visualization body instead… (@arikfr)
- [#1484](https://github.com/getredash/redash/pull/1484) Fix #1457: sort was using the string value (@arikfr)
- [#1478](https://github.com/getredash/redash/pull/1478) [ElasticSearch] Fix: connection test was always succesfful (@adamlwgriffiths)
- [#1440](https://github.com/getredash/redash/pull/1440) Fix: API errors for dashboards with invalid layout data (@whummer)
- [#1427](https://github.com/getredash/redash/pull/1427) [Cassandra] Fix: remove reference to non existing Error class (@arikfr)
- [#1423](https://github.com/getredash/redash/pull/1423) [Cassandra] Fix: cassandra.cluster.Error wasn't imported (@arikfr)
- Fix #1001: queries with a column named "length" were not rendered.
- Fix #578: dashboard list not scrollable.
- Fix #137: add direction indicators when sorting query results.

## v0.12.0 - 2016-11-20

### Added

- 61fe16e #1374: Add: allow '\*' in REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN (Allen Short)
- 2f09043 #1113: Add: share modify/access permissions for queries and dashboard (whummer)
- 3db0eea #1341: Add: support for specifying SAML nameid-format (zoetrope)
- b0ecd0e #1343: Add: support for local SAML metadata file (zoetrope)
- 0235d37 #1335: Add: allow changing alert email subject. (Arik Fraimovich)
- 2135dfd #1333: Add: control over y axis min/max values (Arik Fraimovich)
- 49e788a #1328: Add: support for snapshot generation service (Arik Fraimovich)
- 229ca6c #1323: Add: collect runtime metrics for Celery tasks (Arik Fraimovich)
- 931a1f3 #1315: Add: support for loading BigQuery schema (Arik Fraimovich)
- 39b4f9a #1314: Add: support MongoDB SSL connections (Arik Fraimovich)
- ca1ca9b #1312: Add: additional configuration for Celery jobs (Arik Fraimovich)
- fc00e61 #1310: Add: support for date/time with seconds parameters (Arik Fraimovich)
- d72a198 #1307: Add: API to force refresh data source schema (Arik Fraimovich)
- beb89ec #1305: Add: UI to edit dashboard text box widget (Kazuhito Hokamura)
- 808fdd4 #1298: Add: JIRA (JQL) query runner (Arik Fraimovich)
- ff9e844 #1280: Add: configuration flag to disable scheduled queries (Hirotaka Suzuki)
- ef4699a #1269: Add: Google Drive federated tables support in BigQuery query runner (Kurt Gooden)
- 2eeb947 #1236: Add: query runner for Cassandra and ScyllaDB (syerushalmy)
- 10b398e #1249: Add: override slack webhook parameters (mystelynx)
- 2b5e340 #1252: Add: Schema loading support for Presto query runner (using information_schema) (Rohan Dhupelia)
- 2aaf5dd #1250: Add: query snippets feature (Arik Fraimovich)
- 8d8af73 #1226: Add: Sankey visualization (Arik Fraimovich)
- a02edda #1222: Add: additional results format for sunburst visualization (Arik Fraimovich)
- 0e70188 #1213: Add: new sunburst sequence visualization (Arik Fraimovich)
- 9a6d2d7 #1204: Add: show views in schema browser for Vertica data sources (Matthew Carter)
- 600afa5 #1138: Add: ability to register user defined function (UDF) resources for BigQuery DataSource/Query (fabito)
- b410410 #1166: Add: "every 14 days" refresh option (Arik Fraimovich)
- 906365f #967: Add: extend ElasticSearch query_runner to support aggregations (lloydw)

### Changed

- 2de4aa2 #1395: Change: switch to requests in URL query runner (Arik Fraimovich)
- db1a941 #1392: Change: Update documentation links to point at the new location. (Arik Fraimovich)
- 002f794 #1368: Change: added ability to disable auto update in admin views (Arik Fraimovich)
- aa5d14e #1366: Change: improve error message for exception in the Python query runner (deecay)
- 880627c #1355: Change: pass the user object to the run_query method (Arik Fraimovich)
- 23c605b #1342: SAML: specify entity id (zoetrope)
- 015b1dc #1334: Change: allow specifying recipient address when sending email test message (Arik Fraimovich)
- 39aaa2f #1292: Change: improvements to map visualization (Arik Fraimovich)
- b22191b #1332: Change: upgrade Python packages (Arik Fraimovich)
- 23ba98b #1331: Celery: Upgrade Celery to more recent version. (Arik Fraimovich)
- 3283116 #1330: Change: upgrade Requests to latest version. (Arik Fraimovich)
- 39091e0 #1324: Change: add more logging and information for refresh schemas task (Arik Fraimovich)
- 462faea #1316: Change: remove deprecated settings (Arik Fraimovich)
- 73e1837 #1313: Change: more flexible column width calculation (Arik Fraimovich)
- e8eb840 #1279: Change: update bootstrap.sh to support Ubuntu 16.04 (IllusiveMilkman)
- 8cf0252 #1262: Change: upgrade Plot.ly version and switch to smaller build (Arik Fraimovich)
- 0b79fb8 #1306: Change: paginate queries page & add explicit urls. (Arik Fraimovich)
- 41f99f5 #1299: Change: send Content-Type header (application/json) in query results responses (Tsuyoshi Tatsukawa)
- dfb1a20 #1297: Change: update Slack configuration titles. (Arik Fraimovich)
- 8c1056c #1294: Change: don't annotate BigQuery queries (Arik Fraimovich)
- a3cf92e #1289: Change: use key_as_string when available (ElasticSearch query runner) (Arik Fraimovich)
- e155191 #1285: Change: do not display Oracle tablespace name in schema browser (Matthew Carter)
- 6cbc39c #1282: Change: deduplicate Google Spreadsheet columns (Arik Fraimovich)
- 4caf2e3 #1277: Set specific version of cryptography lib (Arik Fraimovich)
- d22f0d4 #1216: Change: bootstrap.sh - use non interactive dist-upgrade (Atsushi Sasaki)
- 19530f4 #1245: Change: switch from CodeMirror to Ace editor (Arik Fraimovich)
- dfb92db #1234: Change: MongoDB query runner set DB name as mandatory (Arik Fraimovich)
- b750843 #1230: Change: annotate Presto queries with metadata (Noriaki Katayama)
- 5b20fe2 #1217: Change: install libffi-dev for Cryptography (Ubuntu setup script) (Atsushi Sasaki)
- a9fac34 #1206: Change: update pymssql version to 2.1.3 (kitsuyui)
- 5d43cbe #1198: Change: add support for Standard SQL in BigQuery query runner (mystelynx)
- 84d0c22 #1193: Change: modify the argument order of moment.add function call (Kenya Yamaguchi)

### Fixed

- d6febb0 #1375: Fix: Download Dataset does not work when not logged in (Joshua Dechant)
- 96553ad #1369: Fix: missing format call in Elasticsearch test method (Adam Griffiths)
- c57c765 #1365: Fix: compare retrieval times in UTC timezone (Allen Short)
- 37dff5f #1360: Fix: connection test was broken for MySQL (ichihara)
- 360028c #1359: Fix: schema loading query for Hive was wrong for non default schema (laughingman7743)
- 7ee41d4 #1358: Fix: make sure all calls to run_query updated with new parameter (Arik Fraimovich)
- 0d94479 #1329: Fix: Redis memory leak. (Arik Fraimovich)
- 7145aa2 #1325: Fix: queries API was doing N+1 queries in most cases (Arik Fraimovich)
- cd2e927 #1311: Fix: BoxPlot visualization wasn't rendering on a dashboard (Arik Fraimovich)
- a562ce7 #1309: Fix: properly render checkboxes in dynamic forms (Arik Fraimovich)
- d48192c #1308: Fix: support for Unicode columns name in Google Spreadsheets (Arik Fraimovich)
- e42f93f #1283: Fix: schema browser was unstable after opening a table (Arik Fraimovich)
- 170bd65 #1272: Fix: TreasureData get_schema method was returning array instead of string as column name (ariarijp)
- 4710c41 #1265: Fix: refresh modal not working for unsaved query (Arik Fraimovich)
- bc3a5ab #1264: Fix: dashboard refresh not working (Arik Fraimovich)
- 6202d09 #1240: Fix: when shared dashboard token not found, return 404 (Wesley Batista)
- 93aac14 #1251: Fix: autocomplete went crazy when database has no autocomplete. (Arik Fraimovich)
- b8eca28 #1246: Fix: support large schemas in schema browser (Arik Fraimovich)
- b781003 #1223: Fix: Alert: when hipchat Alert.name is multibyte character, occur error. (toyama0919)
- 0b928e6 #1227: Fix: Bower install fails in vagrant (Kazuhito Hokamura)
- a411af2 #1232: Fix: don't show warning when query string (parameters value) changes (Kazuhito Hokamura)
- 3dbb5a6 #1221: Fix: sunburst didn't handle all cases of path lengths (Arik Fraimovich)
- a7cc1ee #1218: Fix: updated result not being saved when changing query text. (Arik Fraimovich)
- 0617833 #1215: Fix: email alerts not working (Arik Fraimovich)
- 78f65b1 #1187: Fix: read only users receive the permission error modal in query view (Arik Fraimovich)
- bba801f #1167: Fix the version of setuptools on bootstrap script for Ubuntu (Takuya Arita)
- ce81d69 #1160: Fix indentation in docker-compose-example.yml (Hirofumi Wakasugi)
- dd759fe #1155: Fix: make all configuration values of Oracle required (Arik Fraimovich)

### Docs

- a69ee0c #1225: Fix: RST formatting of the Vagrant documentation (Kazuhito Hokamura)
- 03837c0 #1242: Docs: add warning re. quotes on column names and BigQuery (Ereli)
- 9a98075 #1255: Docs: add documentation for InfluxDB (vishesh92)
- e0485de #1195: Docs: fix typo in maintenance page title (Antoine Augusti)
- 7681d3e #1164: Docs: update permission documentation (Daniel Darabos)
- bcd3670 #1156: Docs: add SSL parameters to nginx configuration (Josh Cox)

## v0.11.1.b2095 - 2016-08-02

This is a hotfix release, which fixes an issue with email alerts in v0.11.0.

## v0.11.0.b2016 - 2016-07-03

The main features of this release are:

- Alert Destinations: ability to define multiple destinations for alert notifications (currently implemented: HipChat, Slack, Webhook and email).
- The long-awaited UI for query parameters (see example in #1069).

Also, this release includes numerous smaller features, improvements, and bug fixes.

A big thank you goes to all who contributed code and documentation in this release: @AntoineAugusti, @James226, @adamlwgriffiths, @alexdebrie, @anthony-coble, @ariarijp, @dheerajrav, @edwardsharp, @machira, @nabilblk, @ninneko, @ordd, @tomerben, @toru-takahashi, @vishesh92, @vorakumar and @whummer.

### Added

- d5e5b24 #1136: Feature: add --org option to all relevant CLI commands. (@adamlwgriffiths)
- 87e25f2 #1129: Feature: support for JSON query formatting (Mongo, ElasticSearch) (@arikfr)
- 6bb2716 #1121: Show error when failing to communicate with server (@arikfr)
- f21276e #1119: Feature: add UI to delete alerts (@arikfr)
- 8656540 #1069: Feature: UI for query parameters (@arikfr)
- 790128c #1067: Feature: word cloud visualization (@anthony-coble)
- 8b73a2b #1098: Feature: UI for alert destinations & new destination types (@alexdebrie)
- 1fbeb5d #1092: Add Heroku support (@adamlwgriffiths)
- f64622d #1089: Add support for serialising UUID type within MSSQL #961 (@James226)
- 857caab #1085: Feature: API to pause a data source (@arikfr)
- 214aa3b #1060: Feature: support configuring user's groups with SAML (@vorakumar)
- e20a005 #1007: Issue#1006: Make bottom margin editable for Chart visualization (@vorakumar)
- 6e0dd2b #1063: Add support for date/time Y axis (@tomerben)
- b5a4a6b #979: Feature: Add CLI to edit group permissions (@ninneko)
- 6d495d2 #1014: Add server-side parameter handling for embeds (@whummer)
- 5255804 #1091: Add caching for queries used in embeds (@whummer)

### Changed

- 0314313 #1149: Presto QueryRunner supports tinyint and smallint (@toru-takahashi)
- 8fa6fdb #1030: Make sure data sources list ordered by id (@arikfr)
- 8df822e #1141: Make create data source button more prominent (@arikfr)
- 96dd811 #1127: Mark basic_auth_password as secret (@adamlwgriffiths)
- ad65391 #1130: Improve Slack notification style (@AntoineAugusti)
- df637e3 #1116: Return meaningful error when there is no cached result. (@arikfr)
- 65635ec #1102: Switch to HipChat V2 API (@arikfr)
- 14fcf01 #1072: Remove counter from the tasks Done tab (as it always shows 50). #1047 (@arikfr)
- 1a1160e #1062: DynamoDB: Better exception handling (@arikfr)
- ed45dcb #1044: Improve vagrant flow (@staritza)
- 8b5dc8e #1036: Add optional block for more scripts in template (@arikfr)

### Fixed

- dbd48e1 #1143: Fix: use the email input type where needed (@ariarijp)
- 7445972 #1142: Fix: dates in filters might be duplicated (@arikfr)
- 5d0ed02 #1140: Fix: Hive should use the enabled variable (@arikfr)
- 392627d #1139: Fix: Impala data source referencing wrong variable (@arikfr)
- c5bfbba #1133: Fix: query scrolling issues (@vishesh92)
- c01d266 #1128: Fix: visualization options not updating after changing type (@arikfr)
- 6bc0e7a #1126: Fix #669: save fails when doing partial save of new query (@arikfr)
- 3ce27b9 #1118: Fix: remove alerts for archived queries (@arikfr)
- 4fabaae #1117: Fix #1052: filter not working for date/time values (@arikfr)
- c107c94 #1077: Fix: install needed dependencies to use Hive in Docker image (@nabilblk)
- abc790c #1115: Fix: allow non integers in alert reference value (@arikfr)
- 4ec473c #1110: Fix #1109: mixed group permissions resulting in wrong permission (@arikfr)
- 1ca5262 #1099: Fix RST syntax for links (@adamlwgriffiths)
- daa6c1c #1096: Fix typo in env variable VERSION_CHECK (@AntoineAugusti)
- cd06d27 #1095: Fix: use create_query permission for new query button. (@ordd)
- 2bc0b27 #1061: Fix: area chart stacking doesn't work (@machira)
- 8c21e91 #1108: Remove potnetially concurrency not safe code form enqueue_query (@arikfr)
- e831218 #1084: Fix #1049: duplicate alerts when data source belongs to multiple groups (@arikfr)
- 6edb0ca #1080: Fix typo (@jeffwidman)
- 64d7538 #1074: Fix: ElasticSearch wasn't using correct type names (@toyama0919)
- 3f90dd9 #1064: Fix: old task trackers were not really removed (@arikfr)
- e10ecd2 #1058: Bring back filters if dashboard filters are enabled (@AntoineAugusti)
- 701035f #1059: Fix: DynamoDB having issues when setting host (@arikfr)
- 2924d4f #1040: Small fixes to visualizations view (@arikfr)
- fec0d5f #1037: Fix: multi filter wasn't working with \_\_ syntax (@dheerajrav)
- b066ce4 #1033: Fix: only ask for notification permissions if wasn't denied (@arikfr)
- 960c416 #1032: Fix: make sure we return dashboards only for current org only (@arikfr)
- b3844d3 #1029: Hive: close connection only if it exists (@arikfr)

### Docs

- 6bb09d8 #1146: Docs: add a link to settings documentation. (@adamlwgriffiths)
- 095e759 #1103: Docs: add section about monitoring (@AntoineAugusti)
- e942486 #1090: Contributing Guide (@arikfr)
- 3037c4f #1066: Docs: command type-o fix. (@edwardsharp)
- 2ee0065 #1038: Add an ISSUE_TEMPLATE.md to direct people at the forum (@arikfr)
- f7322a4 #1021: Vagrant docs: add purging the cache step (@ariarijp)

---

For older releases check the GitHub releases page:
https://github.com/getredash/redash/releases


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing Guide

Thank you for taking the time to contribute! :tada::+1:

The following is a set of guidelines for contributing to Redash. These are guidelines, not rules, please use your best judgement and feel free to propose changes to this document in a pull request.

:star: If you're already here and love the project, please make sure to press the Star button. :star:
## Table of Contents

[How can I contribute?](#how-can-i-contribute)

- [Reporting Bugs](#reporting-bugs)
- [Suggesting Enhancements / Feature Requests](#suggesting-enhancements--feature-requests)
- [Pull Requests](#pull-requests)
- [Documentation](#documentation)
- Design?

[Additional Notes](#additional-notes)

- [Release Method](#release-method)
- [Code of Conduct](#code-of-conduct)

## Quick Links:

- [User Forum](https://github.com/getredash/redash/discussions)
- [Documentation](https://redash.io/help/)


---
## How can I contribute?

### Reporting Bugs

When creating a new bug report, please make sure to:

- Search for existing issues first. If you find a previous report of your issue, please update the existing issue with additional information instead of creating a new one.
- If you are not sure if your issue is really a bug or just some configuration/setup problem, please start a [Q&A discussion](https://github.com/getredash/redash/discussions/new?category=q-a) first. Unless you can provide clear steps to reproduce, it's probably better to start with a discussion and later to open an issue.
- If you still decide to open an issue, please review the template and guidelines and include as much details as possible.

### Suggesting Enhancements / Feature Requests

If you would like to suggest an enhancement or ask for a new feature:

- Please check [the Ideas discussions](https://github.com/getredash/redash/discussions/categories/ideas) for existing threads about what you want to suggest/ask. If there is, feel free to upvote it to signal interest or add your comments.
- If there is no open thread, you're welcome to start one to have a discussion about what you want to suggest. Try to provide as much details and context as possible and include information about *the problem you want to solve* rather only *your proposed solution*.

### Pull Requests

**Code contributions are welcomed**. For big changes or significant features, it's usually better to reach out first and discuss what you want to implement and how (we recommend reading: [Pull Request First](https://medium.com/practical-blend/pull-request-first-f6bb667a9b6#.ozlqxvj36)). This is to make sure that what you want to implement is aligned with our goals for the project and that no one else is already working on it.

#### Criteria for Review / Merging

When you open your pull request, please follow this repository’s PR template carefully:

- Indicate the type of change
  - If you implement multiple unrelated features, bug fixes, or refactors please split them into individual pull requests.
- Describe the change 
- If fixing a bug, please describe the bug or link to an existing github issue / forum discussion
- Include UI screenshots / GIFs whenever possible
- Please add [documentation](#documentation) for new features or changes in functionality along with the code.
- Please follow existing code style:
  - Python: we use [Black](https://github.com/psf/black) to auto format the code.
  - Javascript: we use [Prettier](https://github.com/prettier/prettier) to auto-format the code.

#### Initial Review (1 week)

During this phase, a team member will apply the “Team Review” label if a pull request meets our criteria or a “Needs More Information” label if not. If more information is required, the team member will comment which criteria have not been met.

If your pull request receives the “Needs More Information” label, please make the requested changes and then remove the label. This resets the 1 week timer for an initial review.

Stale pull requests that remain untouched in “Needs More Information” for more than 4 weeks will be closed.

If a team member closes your pull request, you may reopen it after you have made the changes requested during initial review. After you make these changes, remove the “Needs More Information” label. This again resets the timer for another initial review.

#### Full Review (2 weeks)

After the “Team Review” label is applied, a member of the core team will review the PR within 2 weeks. 

Reviews will approve, request changes, or ask questions to discuss areas of uncertainty. After you’ve responded, a member of the team will re-review within one week.

#### Merging (1 week)

After your pull request has been approved, a member of the core team will merge the pull request within a week.

### Documentation

The project's documentation can be found at [https://redash.io/help/](https://redash.io/help/). The [documentation sources](https://github.com/getredash/website/tree/master/src/pages/kb) are hosted on GitHub. To contribute edits / new pages, you can use GitHub's interface. Click the "Edit on GitHub" link on the documentation page to quickly open the edit interface.

## Additional Notes

### Release Method

We publish a stable release every ~3-4 months, although the goal is to get to a stable release every month. 

Every build of the master branch updates the *redash/redash:preview* Docker Image. These releases are usually stable, but might contain regressions and therefore recommended for "advanced users" only.

When we release a new stable release, we also update the *latest* Docker image tag, the EC2 AMIs and GCE images.

## Code of Conduct

This project adheres to the Contributor Covenant [code of conduct](https://redash.io/community/code_of_conduct). By participating, you are expected to uphold this code. Please report unacceptable behavior to team@redash.io.


================================================
FILE: Dockerfile
================================================
FROM node:24-bookworm AS frontend-builder

RUN npm install --global pnpm@10.30.3

# Controls whether to build the frontend assets
ARG skip_frontend_build

ENV CYPRESS_INSTALL_BINARY=0
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1

RUN useradd -m -d /frontend redash
USER redash

WORKDIR /frontend
COPY --chown=redash package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc /frontend/
COPY --chown=redash viz-lib /frontend/viz-lib
COPY --chown=redash scripts /frontend/scripts

# Controls whether to instrument code for coverage information
ARG code_coverage
ENV BABEL_ENV=${code_coverage:+test}

# Use BuildKit cache mount for pnpm store to speed rebuilds
RUN --mount=type=cache,id=pnpm-store,target=/frontend/.cache/pnpm,uid=1001,gid=1001 \
  pnpm config set store-dir /frontend/.cache/pnpm && \
  if [ "x$skip_frontend_build" = "x" ] ; then pnpm install --frozen-lockfile; fi

COPY --chown=redash client /frontend/client
COPY --chown=redash webpack.config.js /frontend/

# Use the same cache mount for the build step
RUN --mount=type=cache,id=pnpm-store,target=/frontend/.cache/pnpm,uid=1001,gid=1001 <<EOF
  if [ "x$skip_frontend_build" = "x" ]; then
    pnpm run build
  else
    mkdir -p /frontend/client/dist
    touch /frontend/client/dist/multi_org.html
    touch /frontend/client/dist/index.html
  fi
EOF

FROM python:3.13-slim-bookworm

EXPOSE 5000

RUN useradd --create-home redash

# Ubuntu packages
RUN apt-get update && \
  apt-get install -y --no-install-recommends \
  pkg-config \
  curl \
  gnupg \
  build-essential \
  pwgen \
  libffi-dev \
  sudo \
  git-core \
  # Kerberos, needed for MS SQL Python driver to compile on arm64
  libkrb5-dev \
  # Postgres client
  libpq-dev \
  # ODBC support:
  g++ unixodbc-dev \
  # for SAML
  xmlsec1 \
  # Additional packages required for data sources:
  libssl-dev \
  default-libmysqlclient-dev \
  freetds-dev \
  libsasl2-dev \
  unzip \
  libsasl2-modules-gssapi-mit && \
  apt-get clean && \
  rm -rf /var/lib/apt/lists/*


ARG TARGETPLATFORM
ARG databricks_odbc_driver_url=https://databricks-bi-artifacts.s3.us-east-2.amazonaws.com/simbaspark-drivers/odbc/2.6.26/SimbaSparkODBC-2.6.26.1045-Debian-64bit.zip
RUN <<EOF
  if [ "$TARGETPLATFORM" = "linux/amd64" ]; then
    curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg
    curl https://packages.microsoft.com/config/debian/12/prod.list > /etc/apt/sources.list.d/mssql-release.list
    apt-get update
    ACCEPT_EULA=Y apt-get install  -y --no-install-recommends msodbcsql18
    apt-get clean
    rm -rf /var/lib/apt/lists/*
    curl "$databricks_odbc_driver_url" --location --output /tmp/simba_odbc.zip
    chmod 600 /tmp/simba_odbc.zip
    unzip /tmp/simba_odbc.zip -d /tmp/simba
    dpkg -i /tmp/simba/*.deb
    printf "[Simba]\nDriver = /opt/simba/spark/lib/64/libsparkodbc_sb64.so" >> /etc/odbcinst.ini
    rm /tmp/simba_odbc.zip
    rm -rf /tmp/simba
  fi
EOF

WORKDIR /app

ENV POETRY_VERSION=2.1.4
ENV POETRY_HOME=/etc/poetry
ENV POETRY_VIRTUALENVS_CREATE=false
RUN curl -sSL --retry 3 --retry-delay 5 https://install.python-poetry.org | python3 -

# Avoid crashes, including corrupted cache artifacts, when building multi-platform images with GitHub Actions.
RUN /etc/poetry/bin/poetry cache clear pypi --all

COPY pyproject.toml poetry.lock ./

ARG POETRY_OPTIONS="--no-root --no-interaction --no-ansi"
# for LDAP authentication, install with `ldap3` group
# disabled by default due to GPL license conflict
ARG install_groups="main,all_ds,dev"
RUN /etc/poetry/bin/poetry install --only $install_groups $POETRY_OPTIONS

COPY --chown=redash . /app
COPY --from=frontend-builder --chown=redash /frontend/client/dist /app/client/dist
RUN chown redash /app
USER redash

ENTRYPOINT ["/app/bin/docker-entrypoint"]
CMD ["server"]


================================================
FILE: LICENSE
================================================
Copyright (c) 2013-2020, Arik Fraimovich.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, 
   this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation and/or
   other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


================================================
FILE: LICENSE.borders
================================================
The Bahrain map data used in Redash was downloaded from
https://cartographyvectors.com/map/857-bahrain-detailed-boundary in PR #6192.
* Free for personal and commercial purpose with attribution.


================================================
FILE: Makefile
================================================
.PHONY: compose_build up test_db create_database clean down tests lint backend-unit-tests frontend-unit-tests test build watch start redis-cli bash

compose_build: .env
	COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker compose build

up:
	docker compose up -d redis postgres --remove-orphans
	docker compose exec -u postgres postgres psql postgres --csv \
		-1tqc "SELECT table_name FROM information_schema.tables WHERE table_name = 'organizations'" 2> /dev/null \
		| grep -q "organizations" || make create_database
	COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker compose up -d --build --remove-orphans

test_db:
	@for i in `seq 1 5`; do \
		if (docker compose exec postgres sh -c 'psql -U postgres -c "select 1;"' 2>&1 > /dev/null) then break; \
		else echo "postgres initializing..."; sleep 5; fi \
	done
	docker compose exec postgres sh -c 'psql -U postgres -c "drop database if exists tests;" && psql -U postgres -c "create database tests;"'

create_database: .env
	docker compose run server create_db

clean:
	docker compose down
	docker compose --project-name cypress down
	docker compose rm --stop --force
	docker compose --project-name cypress rm --stop --force
	docker image rm --force \
		cypress-server:latest cypress-worker:latest cypress-scheduler:latest \
		redash-server:latest redash-worker:latest redash-scheduler:latest
	docker container prune --force
	docker image prune --force
	docker volume prune --force

down:
	docker compose down

.env:
	printf "REDASH_COOKIE_SECRET=`pwgen -1s 32`\nREDASH_SECRET_KEY=`pwgen -1s 32`\n" >> .env

env: .env

format:
	pre-commit run --all-files

tests:
	docker compose run server tests

lint:
	ruff check .
	black --check . --diff

backend-unit-tests: up test_db
	docker compose run --rm --name tests server tests

frontend-unit-tests:
	CYPRESS_INSTALL_BINARY=0 PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 pnpm install --frozen-lockfile
	pnpm test

test: backend-unit-tests frontend-unit-tests lint

build:
	pnpm run build

watch:
	pnpm run watch

start:
	pnpm start

redis-cli:
	docker compose run --rm redis redis-cli -h redis

bash:
	docker compose run --rm server bash


================================================
FILE: README.md
================================================
<p align="center">
  <img title="Redash" src='https://redash.io/assets/images/logo.png' width="200px"/>
</p>

[![Documentation](https://img.shields.io/badge/docs-redash.io/help-brightgreen.svg)](https://redash.io/help/)
[![GitHub Build](https://github.com/getredash/redash/actions/workflows/ci.yml/badge.svg)](https://github.com/getredash/redash/actions)

Redash is designed to enable anyone, regardless of the level of technical sophistication, to harness the power of data big and small. SQL users leverage Redash to explore, query, visualize, and share data from any data source. Their work, in turn, enables anybody in their organization to use the data. Every day, millions of users at thousands of organizations around the world use Redash to develop insights and make data-driven decisions.

Redash features:

1. **Browser-based**: Everything in your browser, with a shareable URL.
2. **Ease-of-use**: Become immediately productive with data without the need to master complex software.
3. **Query editor**: Quickly compose SQL and NoSQL queries with a schema browser and auto-complete.
4. **Visualization and dashboards**: Create [beautiful visualizations](https://redash.io/help/user-guide/visualizations/visualization-types) with drag and drop, and combine them into a single dashboard.
5. **Sharing**: Collaborate easily by sharing visualizations and their associated queries, enabling peer review of reports and queries.
6. **Schedule refreshes**: Automatically update your charts and dashboards at regular intervals you define.
7. **Alerts**: Define conditions and be alerted instantly when your data changes.
8. **REST API**: Everything that can be done in the UI is also available through the REST API.
9. **Broad support for data sources**: An extensible data source API with native support for a long list of common databases and platforms.

<img src="https://raw.githubusercontent.com/getredash/website/8e820cd02c73a8ddf4f946a9d293c54fd3fb08b9/website/_assets/images/redash-anim.gif" width="80%"/>

## Getting Started

* [Setting up a Redash instance](https://redash.io/help/open-source/setup) (includes links to ready-made AWS/GCE images).
* [Documentation](https://redash.io/help/).

## Supported Data Sources

Redash supports more than 35 SQL and NoSQL [data sources](https://redash.io/help/data-sources/supported-data-sources). It can also be extended to support more. Below is a list of built-in sources:

- Amazon Athena
- Amazon CloudWatch / Insights
- Amazon DynamoDB
- Amazon Redshift
- ArangoDB
- Axibase Time Series Database
- Apache Cassandra
- ClickHouse
- CockroachDB
- Couchbase
- CSV
- Databricks
- DB2 by IBM
- Dgraph
- Apache Drill
- Apache Druid
- e6data
- Eccenca Corporate Memory
- Elasticsearch
- Exasol
- Microsoft Excel
- Firebolt
- Databend
- Google Analytics
- Google BigQuery
- Google Spreadsheets
- Graphite
- Greenplum
- Apache Hive
- Apache Impala
- InfluxDB
- InfluxDBv2
- IBM Netezza Performance Server
- JIRA (JQL)
- JSON
- Apache Kylin
- OmniSciDB (Formerly MapD)
- MariaDB
- MemSQL
- Microsoft Azure Data Warehouse / Synapse
- Microsoft Azure SQL Database
- Microsoft Azure Data Explorer / Kusto
- Microsoft SQL Server
- MongoDB
- MySQL
- Oracle
- Apache Phoenix
- Apache Pinot
- PostgreSQL
- Presto
- Prometheus
- Python
- Qubole
- Rockset
- RisingWave
- Salesforce
- ScyllaDB
- Shell Scripts
- Snowflake
- SPARQL
- SQLite
- TiDB
- Tinybird
- TreasureData
- Trino
- Uptycs
- Vertica
- Yandex AppMetrica
- Yandex Metrica

## Getting Help

* Issues: https://github.com/getredash/redash/issues
* Discussion Forum: https://github.com/getredash/redash/discussions/
* Development Discussion: https://discord.gg/tN5MdmfGBp

## Reporting Bugs and Contributing Code

* Want to report a bug or request a feature? Please open [an issue](https://github.com/getredash/redash/issues/new).
* Want to help us build **_Redash_**? Fork the project, edit in a [dev environment](https://github.com/getredash/redash/wiki/Local-development-setup) and make a pull request. We need all the help we can get!

## Security

Please email security@redash.io to report any security vulnerabilities. We will acknowledge receipt of your vulnerability and strive to send you regular updates about our progress. If you're curious about the status of your disclosure please feel free to email us again. If you want to encrypt your disclosure email, you can use [this PGP key](https://keybase.io/arikfr/key.asc).

## License

BSD-2-Clause.


================================================
FILE: SECURITY.md
================================================
# Security Policy

## Reporting a Vulnerability

Please email security@redash.io to report any security vulnerabilities. We will acknowledge receipt of your vulnerability and strive to send you regular updates about our progress. If you're curious about the status of your disclosure please feel free to email us again. If you want to encrypt your disclosure email, you can use [this PGP key](https://keybase.io/arikfr/key.asc).


================================================
FILE: bin/docker-entrypoint
================================================
#!/bin/bash
set -e

scheduler() {
  echo "Starting RQ scheduler..."

  exec /app/manage.py rq scheduler
}

dev_scheduler() {
  echo "Starting dev RQ scheduler..."

  exec watchmedo auto-restart --directory=./redash/ --pattern=*.py --recursive -- ./manage.py rq scheduler
}

worker() {
  echo "Starting RQ worker..."

  export WORKERS_COUNT=${WORKERS_COUNT:-2}
  export QUEUES=${QUEUES:-}

  exec supervisord -c worker.conf
}

workers_healthcheck() {
  WORKERS_COUNT=${WORKERS_COUNT}
  echo "Checking active workers count against $WORKERS_COUNT..."
  ACTIVE_WORKERS_COUNT=`echo $(rq info --url $REDASH_REDIS_URL -R | grep workers | grep -oP ^[0-9]+)`
  if [ "$ACTIVE_WORKERS_COUNT" -lt "$WORKERS_COUNT"  ]; then
    echo "$ACTIVE_WORKERS_COUNT workers are active, Exiting"
    exit 1
  else
    echo "$ACTIVE_WORKERS_COUNT workers are active"
    exit 0
  fi
}

dev_worker() {
  echo "Starting dev RQ worker..."

  exec watchmedo auto-restart --directory=./redash/ --pattern=*.py --recursive -- ./manage.py rq worker $QUEUES
}

server() {
  # Recycle gunicorn workers every n-th request. See http://docs.gunicorn.org/en/stable/settings.html#max-requests for more details.
  MAX_REQUESTS=${MAX_REQUESTS:-1000}
  MAX_REQUESTS_JITTER=${MAX_REQUESTS_JITTER:-100}
  TIMEOUT=${REDASH_GUNICORN_TIMEOUT:-60}
  BIND_ADDRESS=${REDASH_GUNICORN_BIND:-[::]:5000}
  exec /usr/local/bin/gunicorn -b "$BIND_ADDRESS" --name redash -w${REDASH_WEB_WORKERS:-4} redash.wsgi:app --max-requests $MAX_REQUESTS --max-requests-jitter $MAX_REQUESTS_JITTER --timeout $TIMEOUT --limit-request-line ${REDASH_GUNICORN_LIMIT_REQUEST_LINE:-0}
}

create_db() {
  exec /app/manage.py database create_tables
}

help() {
  echo "Redash Docker."
  echo ""
  echo "Usage:"
  echo ""

  echo "server -- start Redash server (with gunicorn)"
  echo "worker -- start a single RQ worker"
  echo "dev_worker -- start a single RQ worker with code reloading"
  echo "scheduler -- start an rq-scheduler instance"
  echo "dev_scheduler -- start an rq-scheduler instance with code reloading"
  echo ""
  echo "shell -- open shell"
  echo "dev_server -- start Flask development server with debugger and auto reload"
  echo "debug -- start Flask development server with remote debugger via debugpy"
  echo "create_db -- create database tables"
  echo "manage -- CLI to manage redash"
  echo "tests -- run tests"
}

tests() {
  export REDASH_DATABASE_URL="postgresql://postgres@postgres/tests"

  if [ $# -eq 0 ]; then
    TEST_ARGS=tests/
  else
    TEST_ARGS=$@
  fi
  exec pytest $TEST_ARGS
}

case "$1" in
  worker)
    shift
    worker
    ;;
  workers_healthcheck)
    shift
    workers_healthcheck
    ;;
  server)
    shift
    server
    ;;
  scheduler)
    shift
    scheduler
    ;;
  dev_scheduler)
    shift
    dev_scheduler
    ;;
  dev_worker)
    shift
    dev_worker
    ;;
  celery_healthcheck)
    shift
    echo "DEPRECATED: Celery has been replaced with RQ and now performs healthchecks autonomously as part of the 'worker' entrypoint."
    ;;
  dev_server)
    export FLASK_DEBUG=1
    exec /app/manage.py runserver --debugger --reload -h 0.0.0.0
    ;;
  debug)
    export FLASK_DEBUG=1
    export REMOTE_DEBUG=1
    exec /app/manage.py runserver --debugger --no-reload -h 0.0.0.0
    ;;
  shell)
    exec /app/manage.py shell
    ;;
  create_db)
    create_db
    ;;
  manage)
    shift
    exec /app/manage.py $*
    ;;
  tests)
    shift
    tests $@
    ;;
  help)
    shift
    help
    ;;
  *)
    exec "$@"
    ;;
esac


================================================
FILE: bin/get_changes.py
================================================
#!/bin/env python3

import re
import subprocess
import sys


def get_change_log(previous_sha):
    args = [
        "git",
        "--no-pager",
        "log",
        "--merges",
        "--grep",
        "Merge pull request",
        '--pretty=format:"%h|%s|%b|%p"',
        "master...{}".format(previous_sha),
    ]
    log = subprocess.check_output(args)
    changes = []

    for line in log.split("\n"):
        try:
            sha, subject, body, parents = line[1:-1].split("|")
        except ValueError:
            continue

        try:
            pull_request = re.match(r"Merge pull request #(\d+)", subject).groups()[0]
            pull_request = " #{}".format(pull_request)
        except Exception:
            pull_request = ""

        author = subprocess.check_output(["git", "log", "-1", '--pretty=format:"%an"', parents.split(" ")[-1]])[1:-1]

        changes.append("{}{}: {} ({})".format(sha, pull_request, body.strip(), author))

    return changes


if __name__ == "__main__":
    previous_sha = sys.argv[1]
    changes = get_change_log(previous_sha)

    for change in changes:
        print(change)


================================================
FILE: bin/release_manager.py
================================================
#!/usr/bin/env python3
import os
import re
import subprocess
import sys
from urllib.parse import urlparse

import requests
import simplejson

github_token = os.environ["GITHUB_TOKEN"]
auth = (github_token, "x-oauth-basic")
repo = "getredash/redash"


def _github_request(method, path, params=None, headers={}):
    if urlparse(path).hostname != "api.github.com":
        url = "https://api.github.com/{}".format(path)
    else:
        url = path

    if params is not None:
        params = simplejson.dumps(params)

    response = requests.request(method, url, data=params, auth=auth)
    return response


def exception_from_error(message, response):
    return Exception("({}) {}: {}".format(response.status_code, message, response.json().get("message", "?")))


def rc_tag_name(version):
    return "v{}-rc".format(version)


def get_rc_release(version):
    tag = rc_tag_name(version)
    response = _github_request("get", "repos/{}/releases/tags/{}".format(repo, tag))

    if response.status_code == 404:
        return None
    elif response.status_code == 200:
        return response.json()

    raise exception_from_error("Unknown error while looking RC release: ", response)


def create_release(version, commit_sha):
    tag = rc_tag_name(version)

    params = {
        "tag_name": tag,
        "name": "{} - RC".format(version),
        "target_commitish": commit_sha,
        "prerelease": True,
    }

    response = _github_request("post", "repos/{}/releases".format(repo), params)

    if response.status_code != 201:
        raise exception_from_error("Failed creating new release", response)

    return response.json()


def upload_asset(release, filepath):
    upload_url = release["upload_url"].replace("{?name,label}", "")
    filename = filepath.split("/")[-1]

    with open(filepath) as file_content:
        headers = {"Content-Type": "application/gzip"}
        response = requests.post(
            upload_url, file_content, params={"name": filename}, headers=headers, auth=auth, verify=False
        )

    if response.status_code != 201:  # not 200/201/...
        raise exception_from_error("Failed uploading asset", response)

    return response


def remove_previous_builds(release):
    for asset in release["assets"]:
        response = _github_request("delete", asset["url"])
        if response.status_code != 204:
            raise exception_from_error("Failed deleting asset", response)


def get_changelog(commit_sha):
    latest_release = _github_request("get", "repos/{}/releases/latest".format(repo))
    if latest_release.status_code != 200:
        raise exception_from_error("Failed getting latest release", latest_release)

    latest_release = latest_release.json()
    previous_sha = latest_release["target_commitish"]

    args = [
        "git",
        "--no-pager",
        "log",
        "--merges",
        "--grep",
        "Merge pull request",
        '--pretty=format:"%h|%s|%b|%p"',
        "{}...{}".format(previous_sha, commit_sha),
    ]
    log = subprocess.check_output(args)
    changes = ["Changes since {}:".format(latest_release["name"])]

    for line in log.split("\n"):
        try:
            sha, subject, body, parents = line[1:-1].split("|")
        except ValueError:
            continue

        try:
            pull_request = re.match(r"Merge pull request #(\d+)", subject).groups()[0]
            pull_request = " #{}".format(pull_request)
        except Exception:
            pull_request = ""

        author = subprocess.check_output(["git", "log", "-1", '--pretty=format:"%an"', parents.split(" ")[-1]])[1:-1]

        changes.append("{}{}: {} ({})".format(sha, pull_request, body.strip(), author))

    return "\n".join(changes)


def update_release_commit_sha(release, commit_sha):
    params = {
        "target_commitish": commit_sha,
    }

    response = _github_request("patch", "repos/{}/releases/{}".format(repo, release["id"]), params)

    if response.status_code != 200:
        raise exception_from_error("Failed updating commit sha for existing release", response)

    return response.json()


def update_release(version, build_filepath, commit_sha):
    try:
        release = get_rc_release(version)
        if release:
            release = update_release_commit_sha(release, commit_sha)
        else:
            release = create_release(version, commit_sha)

        print("Using release id: {}".format(release["id"]))

        remove_previous_builds(release)
        response = upload_asset(release, build_filepath)

        changelog = get_changelog(commit_sha)

        response = _github_request("patch", release["url"], {"body": changelog})
        if response.status_code != 200:
            raise exception_from_error("Failed updating release description", response)

    except Exception as ex:
        print(ex)


if __name__ == "__main__":
    commit_sha = sys.argv[1]
    version = sys.argv[2]
    filepath = sys.argv[3]

    # TODO: make sure running from git directory & remote = repo
    update_release(version, filepath, commit_sha)


================================================
FILE: bin/run
================================================
#!/usr/bin/env bash

# Ideally I would use stdin with source, but in older bash versions this
# wasn't supported properly.
TEMP_ENV_FILE=`mktemp /tmp/redash_env.XXXXXX`
sed 's/^REDASH/export REDASH/' .env > $TEMP_ENV_FILE
source $TEMP_ENV_FILE
rm $TEMP_ENV_FILE

exec "$@"


================================================
FILE: client/.babelrc
================================================
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "exclude": ["@babel/plugin-transform-async-to-generator", "@babel/plugin-transform-arrow-functions"],
        "corejs": "2",
        "useBuiltIns": "usage"
      }
    ],
    "@babel/preset-react",
    "@babel/preset-typescript"
  ],
  "plugins": [
    "@babel/plugin-transform-class-properties",
    "@babel/plugin-transform-object-assign",
    [
      "babel-plugin-transform-builtin-extend",
      {
        "globals": ["Error"]
      }
    ]
  ],
  "env": {
    "test": {
      "plugins": ["istanbul"]
    }
  }
}


================================================
FILE: client/.eslintignore
================================================
build/*.js
dist
config/*.js
client/dist


================================================
FILE: client/.eslintrc.js
================================================
module.exports = {
  root: true,
  parser: "@typescript-eslint/parser",
  extends: [
    "react-app",
    "plugin:compat/recommended",
    "prettier",
    "plugin:jsx-a11y/recommended",
  ],
  plugins: ["jest", "compat", "no-only-tests", "@typescript-eslint", "jsx-a11y"],
  settings: {
    "import/resolver": "webpack",
    polyfills: [
      "document.body",
      "Notification",
    ],
  },
  env: {
    browser: true,
    node: true,
  },
  rules: {
    // allow debugger during development
    "no-debugger": process.env.NODE_ENV === "production" ? 2 : 0,
    // Pre-existing patterns - anonymous default exports are used throughout
    "import/no-anonymous-default-export": "off",
    // Some tests verify no-throw behavior without explicit assertions
    "jest/expect-expect": "off",
    "jsx-a11y/anchor-is-valid": [
      // TMP
      "off",
      {
        components: ["Link"],
        aspects: ["noHref", "invalidHref", "preferButton"],
      },
    ],
    "jsx-a11y/no-redundant-roles": "error",
    "jsx-a11y/no-autofocus": "off",
    "jsx-a11y/click-events-have-key-events": "off", // TMP
    "jsx-a11y/no-static-element-interactions": "off", // TMP
    "jsx-a11y/no-noninteractive-element-interactions": "off", // TMP
    "no-console": ["warn", { allow: ["warn", "error"] }],
    "no-restricted-imports": [
      "error",
      {
        paths: [
          {
            name: "antd",
            message: "Please use 'import XXX from antd/lib/XXX' import instead.",
          },
          {
            name: "antd/lib",
            message: "Please use 'import XXX from antd/lib/XXX' import instead.",
          },
        ],
      },
    ],
  },
  overrides: [
    {
      // Only run typescript-eslint on TS files
      files: ["*.ts", "*.tsx", ".*.ts", ".*.tsx"],
      extends: ["plugin:@typescript-eslint/recommended"],
      rules: {
        // Do not require functions (especially react components) to have explicit returns
        "@typescript-eslint/explicit-function-return-type": "off",
        // Do not require to type every import from a JS file to speed up development
        "@typescript-eslint/no-explicit-any": "off",
        // Do not complain about useless contructors in declaration files
        "no-useless-constructor": "off",
        "@typescript-eslint/no-useless-constructor": "error",
        // Many API fields and generated types use camelcase
        camelcase: "off",
        // Allow {} type - used extensively in existing codebase
        "@typescript-eslint/ban-types": ["error", { types: { "{}": false } }],
      },
    },
    {
      // Cypress test files
      files: ["**/cypress/**/*.js"],
      extends: ["plugin:cypress/recommended"],
      plugins: ["cypress", "chai-friendly"],
      env: {
        "cypress/globals": true,
      },
      rules: {
        "no-redeclare": "off",
        "cypress/unsafe-to-chain-command": "off",
        "func-names": ["error", "never"],
        "no-unused-expressions": "off",
        "chai-friendly/no-unused-expressions": "error",
      },
    },
  ],
};


================================================
FILE: client/.gitignore
================================================
dist


================================================
FILE: client/app/.eslintrc.js
================================================
module.exports = {
  extends: ["plugin:jest/recommended"],
  plugins: ["jest"],
  env: {
    "jest/globals": true,
  },
  rules: {
    "jest/no-focused-tests": "off",
  },
};


================================================
FILE: client/app/__tests__/enzyme_setup.js
================================================
import { configure } from "enzyme";
import Adapter from "enzyme-adapter-react-16";

configure({ adapter: new Adapter() });


================================================
FILE: client/app/__tests__/mocks.js
================================================
import MockDate from "mockdate";

const date = new Date("2000-01-01T02:00:00.000");

MockDate.set(date);


================================================
FILE: client/app/assets/css/login.css
================================================
body {
  padding-top: 0px !important;
  background-color: #FFFFFF;
}

.logo-container {
  background-color: #668899;
  display: table;
  width: 100%;
  padding: 10px;
}

.content-container {
  background-color: white;
  display: table;
  width: 100%;
  padding: 10px;
  height: calc(100% - 116px);
}

@media (min-width: 992px) {
  .content-container {
    height: 100%;
    width: 60%;
    float: left;
  }

  .logo-container {
    height: 100%;
    width: 40%;
    float: right;
  }
}

.login-or {
  position: relative;
  font-size: 18px;
  color: #aaa;
  margin-top: 20px;
  margin-bottom: 20px;
  padding-top: 10px;
  padding-bottom: 10px;
}

.span-or {
  display: block;
  position: absolute;
  left: 50%;
  top: -2px;
  margin-left: -25px;
  background-color: #fff;
  width: 50px;
  text-align: center;
}

.hr-or {
  background-color: #cdcdcd;
  height: 1px;
  margin-top: 0px !important;
  margin-bottom: 0px !important;
}

img.login-button {
  width: 250px;
  display: block;
  margin-left: auto;
  margin-right: auto;
}



================================================
FILE: client/app/assets/images/illustrations/readme.md
================================================
The illustrations shared in this folder are covered by the CC-BY-SA-NC-ND License v4.0 (or newer). You are allowed to use them when using unmodified versions of the Redash source code for non-commercial purposes (meaning for yourself), but you are not allowed to use for any other use or to distribute them as part of your software or fork of Redash.

For any questions, please contact us.


================================================
FILE: client/app/assets/less/STYLING-README.md
================================================
# Styling readme

Some general rules before you add stuff.

- Avoid using inline css
- If possible, use classes that are already in place instead of adding new
- Keep less/inc folder untouched, rewrite things in less/redash respectively 
- Try following BEM naming conventions: http://getbem.com/naming/


================================================
FILE: client/app/assets/less/ant.less
================================================
@import "~antd/lib/style/core/iconfont";
@import "~antd/lib/style/core/motion";
@import "~antd/lib/alert/style/index";
@import "~antd/lib/input/style/index";
@import "~antd/lib/input-number/style/index";
@import "~antd/lib/date-picker/style/index";
@import "~antd/lib/modal/style/index";
@import "~antd/lib/tooltip/style/index";
@import "~antd/lib/select/style/index";
@import "~antd/lib/checkbox/style/index";
@import "~antd/lib/upload/style/index";
@import "~antd/lib/form/style/index";
@import "~antd/lib/button/style/index";
@import "~antd/lib/radio/style/index";
@import "~antd/lib/time-picker/style/index";
@import "~antd/lib/pagination/style/index";
@import "~antd/lib/table/style/index";
@import "~antd/lib/popover/style/index";
@import "~antd/lib/tag/style/index";
@import "~antd/lib/grid/style/index";
@import "~antd/lib/switch/style/index";
@import "~antd/lib/empty/style/index";
@import "~antd/lib/drawer/style/index";
@import "~antd/lib/card/style/index";
@import "~antd/lib/steps/style/index";
@import "~antd/lib/divider/style/index";
@import "~antd/lib/dropdown/style/index";
@import "~antd/lib/menu/style/index";
@import "~antd/lib/list/style/index";
@import "~antd/lib/badge/style/index";
@import "~antd/lib/card/style/index";
@import "~antd/lib/spin/style/index";
@import "~antd/lib/skeleton/style/index";
@import "~antd/lib/tabs/style/index";
@import "~antd/lib/notification/style/index";
@import "~antd/lib/collapse/style/index";
@import "~antd/lib/progress/style/index";
@import "~antd/lib/typography/style/index";
@import "~antd/lib/descriptions/style/index";
@import "inc/ant-variables";

// Increase z-indexes to avoid conflicts with some other libraries (e.g. Plotly)
@zindex-modal: 2000;
@zindex-modal-mask: 2000;
@zindex-message: 2010;
@zindex-notification: 2010;
@zindex-popover: 2030;
@zindex-dropdown: 2050;
@zindex-picker: 2050;
@zindex-tooltip: 2060;
@item-hover-bg: #e5f8ff;

.@{drawer-prefix-cls} {
  &.help-drawer {
    z-index: @zindex-tooltip; // help drawer should be topmost
  }
}

// Remove bold in labels for Ant checkboxes and radio buttons
.ant-checkbox-wrapper,
.ant-radio-wrapper {
  font-weight: normal;
}

.ant-select-dropdown-menu-item em {
  color: @input-color-placeholder;
  font-size: 11px;
}

// Fix for disabled button styles inside Tooltip component.
// Tooltip wraps disabled buttons with `<span>` and moves all styles
// and classes to that `<span>`. This resets all button styles and
// turns it into simple inline element (because now it's wrapper is a button)
.btn {
  button[disabled] {
    -moz-appearance: none !important;
    -webkit-appearance: none !important;
    appearance: none !important;
    border: 0 !important;
    outline: none !important;
    background: transparent !important;
    margin: 0 !important;
    padding: 0 !important;
  }
}

// Button overrides
.@{btn-prefix-cls} {
  transition-duration: 150ms;

  &.icon-button {
    width: 32px;
    padding: 0 10px;
  }
}

// Fix ant input number showing duplicate arrows
.ant-input-number-input::-webkit-outer-spin-button,
.ant-input-number-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

// Pagination overrides (based on existing Bootstrap overrides)
.@{pagination-prefix-cls} {
  display: inline-block;
  margin-top: 18px;
  margin-bottom: 18px;
  vertical-align: top;

  &-item {
    background-color: @pagination-bg;
    border-color: transparent;
    color: @pagination-color;
    font-size: 14px;
    margin-right: 5px;

    a {
      color: inherit;
    }

    &:focus,
    &:hover {
      background-color: @pagination-hover-bg;
      border-color: transparent;
      color: @pagination-hover-color;
      a {
        color: inherit;
      }
    }

    &-active {
      &,
      &:hover,
      &:focus {
        background-color: @pagination-active-bg;
        color: @pagination-active-color;
        border-color: transparent;
        pointer-events: none;
        cursor: default;

        a {
          color: inherit;
        }
      }
    }
  }

  &-disabled {
    &,
    &:hover,
    &:focus {
      opacity: 0.5;
      pointer-events: none;
    }
  }

  &-prev,
  &-next {
    .@{pagination-prefix-cls}-item-link {
      background-color: @pagination-bg;
      border-color: transparent;
      color: @pagination-color;
      line-height: @pagination-item-size - 2px;

      .@{pagination-prefix-cls}.mini & {
        line-height: @pagination-item-size-sm - 2px;
      }
    }

    &:focus .@{pagination-prefix-cls}-item-link,
    &:hover .@{pagination-prefix-cls}-item-link {
      background-color: @pagination-hover-bg;
      border-color: transparent;
      color: @pagination-hover-color;
    }
  }

  &-prev,
  &-jump-prev,
  &-jump-next {
    margin-right: 5px;
  }

  &-jump-prev,
  &-jump-next {
    .@{pagination-prefix-cls}-item-container {
      .@{pagination-prefix-cls}-item-link-icon {
        color: @pagination-color;
      }
    }
  }
}

// Table

.@{table-prefix-cls} {
  color: inherit;

  tr,
  th,
  td {
    transition: none !important;
  }

  &-thead > tr > th {
    padding: @table-padding-vertical * 2 @table-padding-horizontal;
  }

  .@{table-prefix-cls}-column-sorters {
    &:before,
    &:hover:before {
      content: none;
    }
  }

  &-thead > tr > th {
    .@{table-prefix-cls}-column-sorter {
      &-up,
      &-down {
        &.on {
          color: @table-header-icon-active-color;
        }
      }
    }
  }

  &-tbody > tr&-row {
    &:hover,
    &:focus,
    &:focus-within {
      & > td {
        background: @table-row-hover-bg;
      }
    }
  }

  // Custom styles

  &-headerless &-tbody > tr:first-child > td {
    border-top: @border-width-base @border-style-base @border-color-split;
  }
}

// List

.@{list-prefix-cls} {
  &-item {
    // custom rule
    &.selected {
      background-color: #f6f8f9;
    }

    &.disabled {
      background-color: fade(#f6f8f9, 40%);

      & > * {
        opacity: 0.4;
      }
    }
  }
}

.@{dialog-prefix-cls} {
  // styling for short modals (no lines)
  &.shortModal {
    .@{dialog-prefix-cls} {
      &-header,
      &-footer {
        border: none;
        padding: 16px;
      }

      &-body {
        padding: 10px 16px;
      }

      &-close-x {
        width: 46px;
        height: 46px;
        line-height: 46px;
      }
    }
  }

  // fullscreen modals
  &-fullscreen {
    .@{dialog-prefix-cls} {
      position: absolute;
      left: 15px;
      top: 15px;
      right: 15px;
      bottom: 15px;
      width: auto !important;
      height: auto !important;
      max-width: none;
      max-height: none;
      margin: 0;
      padding: 0;

      .@{dialog-prefix-cls}-content {
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        bottom: 0;
        width: auto;
        height: auto;
        margin: 0;
        padding: 0;
        display: flex;
        flex-direction: column;
      }

      .@{dialog-prefix-cls}-body {
        flex: 1 1 auto;
        overflow: auto;
      }
    }
  }
}

// description in modal header
.modal-header-desc {
  font-size: @font-size-base;
  color: @text-color-secondary;
  font-weight: normal;
  margin-top: 4px;
}

// Notification overrides
.@{notification-prefix-cls} {
  // vertical centering
  &-notice-close {
    top: 20px;
    right: 20px;
  }

  &-notice-description {
    max-width: 484px;
  }
}

.@{btn-prefix-cls} .@{iconfont-css-prefix}-ellipsis {
  margin: 0 -7px 0 -8px;
}

// Collapse

.@{collapse-prefix-cls} {
  &&-headerless {
    border: 0;
    background: none;

    .@{collapse-prefix-cls}-header {
      display: none;
    }

    .@{collapse-prefix-cls}-item,
    .@{collapse-prefix-cls}-content {
      border: 0;
    }

    .@{collapse-prefix-cls}-content-box {
      padding: 0;
    }
  }
}

// overrides for tall form components such as ace editor
.@{form-prefix-cls}-item {
  &-children {
    display: block; // so feeback icon positions correctly
  }

  // no change for short components, sticks to body for tall ones
  &-children-icon {
    top: auto !important;
    bottom: 8px;

    // makes the icon white instead of see-through
    & svg {
      background: white;
      border-radius: 50%;
    }
  }

  // for form items that contain text
  &.form-item-line-height-normal .@{form-prefix-cls}-item-control {
    line-height: 20px;
    margin-top: 9px;
  }
}

.@{menu-prefix-cls} {
  // invert stripe position with class .invert-stripe-position
  &-inline.invert-stripe-position {
    .@{menu-prefix-cls}-item {
      &::after {
        right: auto;
        left: 0;
      }
    }

    &:focus,
    &:focus-within {
      color: @menu-highlight-color;
    }
  }
}

.@{dropdown-prefix-cls}-menu-item {
  &:focus,
  &:focus-within {
    background-color: @item-hover-bg;
  }
}

// overrides for checkbox
@checkbox-prefix-cls: ~"@{ant-prefix}-checkbox";

.@{checkbox-prefix-cls}-wrapper + span,
.@{checkbox-prefix-cls} + span {
  padding-right: 0;
}

// make sure Multiple select has room for icons
.@{select-prefix-cls}-multiple {
  &.@{select-prefix-cls}-show-arrow,
  &.@{select-prefix-cls}-show-search,
  &.@{select-prefix-cls}-loading {
    .@{select-prefix-cls}-selector {
      padding-right: 30px;
    }
  }
}


================================================
FILE: client/app/assets/less/inc/404.less
================================================
.four-zero {
	background: @white;
	box-shadow: 0 1px 11px rgba(0, 0, 0, 0.27);
	border-radius: 2px;
	position: absolute;
	top: 50%;
	margin-top: -150px;
	text-align: center;
	padding: 15px;
	height: 300px;
	width: 500px;
	left: 50%;
	color: #333;
	margin-left: -250px;
	
	h2 {
		font-size: 130px;
	}

	
	@media (max-width: @screen-xs-max) {
		width: ~"calc(100% - 40px)";
		left: 20px;
		margin-left: 0;
		height: 260px;
		margin-top: -130px;
		
		h2 {
			font-size: 90px;
		}
        }
	
	h2 {
		line-height: 100%;
		font-weight: 100;
	}
	
	small {
		display: block;
		font-size: 26px;
		margin-top: -10px
	}
	
	
	footer {
		background: @ace;
		position: absolute;
		left: 0;
		bottom: 0;
		width: 100%;
		padding: 10px;
		
		& > a {
			font-size: 21px;
			display: inline-block;
			color: #333;
			margin: 0 1px;
			line-height: 40px;
			width: 40px;
			height: 40px;
			background: rgba(0, 0, 0, 0.09);
			border-radius: 50%;
			text-align: center;
			
			&:hover {
				background: rgba(0, 0, 0, 0.2);
			}
		}
	}
}





================================================
FILE: client/app/assets/less/inc/ace-editor.less
================================================
.ace_editor {
  border: 1px solid fade(@redash-gray, 15%);
  height: 100%;
  margin-bottom: 10px;

  &.ace_autocomplete .ace_completion-highlight {
    text-shadow: none !important;
    background: #ffff005e;
    font-weight: 600;
  }

  &.ace-tm {
    .ace_gutter {
      background: #fff !important;
    }

    .ace_gutter-active-line {
      background-color: fade(@redash-gray, 20%) !important;
    }

    .ace_marker-layer .ace_active-line {
      background: fade(@redash-gray, 9%) !important;
    }
  }
}


================================================
FILE: client/app/assets/less/inc/alert.less
================================================
.alert-page h3 {
  flex-grow: 1;

  input {
    margin: -0.2em 0;
    width: 100%;
    min-width: 170px;
  }
}

.btn-create-alert[disabled] {
  display: block;
  margin-top: -20px;
}

.alert-state {
  border-bottom: 1px solid @input-border;
  padding-bottom: 30px;

  .alert-state-indicator {
    text-transform: uppercase;
    font-size: 14px;
    padding: 5px 8px;
  }

  .ant-form-item-explain {
    margin-top: 10px;
  }

  .alert-last-triggered {
    color: @headings-color;
  }
}

.alert-query-selector {
  min-width: 250px;
  width: auto !important;
}

// allow form item labels to gracefully break line
.alert-form-item label {
  white-space: initial;
  padding-right: 8px;
  line-height: 21px;

  &::after {
    margin-right: 0 !important;
  }
}


================================================
FILE: client/app/assets/less/inc/ant-variables.less
================================================
/* --------------------------------------------------------
    Colors
-----------------------------------------------------------*/
@lightblue: #03a9f4;
@primary-color: #2196f3;

@redash-gray: rgba(102, 136, 153, 1);
@redash-orange: rgba(255, 120, 100, 1);
@redash-black: rgba(0, 0, 0, 1);
@redash-yellow: rgba(252, 252, 161, 0.75);

/* --------------------------------------------------------
    Font
-----------------------------------------------------------*/
@redash-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue",
  sans-serif;
@font-family-no-number: @redash-font;
@font-family: @redash-font;
@code-family: @redash-font;
@font-size-base: 13px;

/* --------------------------------------------------------
    Borders
-----------------------------------------------------------*/
@border-color-split: #f0f0f0;

/* --------------------------------------------------------
    Typograpgy
-----------------------------------------------------------*/
@text-color: #595959;

/* --------------------------------------------------------
    Form
-----------------------------------------------------------*/
@input-height-base: 35px;
@input-color: #595959;
@input-color-placeholder: #b4b4b4;
@border-radius-base: 2px;
@border-color-base: #e8e8e8;

/* --------------------------------------------------------
    Pagination
-----------------------------------------------------------*/
@pagination-item-size: 33px;
@pagination-font-family: @redash-font;
@pagination-font-weight-active: normal;

@pagination-bg: fade(@redash-gray, 15%);
@pagination-color: #7e7e7e;
@pagination-active-bg: @lightblue;
@pagination-active-color: #fff;
@pagination-disabled-bg: fade(@redash-gray, 15%);
@pagination-hover-color: #333;
@pagination-hover-bg: fade(@redash-gray, 25%);

/* --------------------------------------------------------
    Table
-----------------------------------------------------------*/
@table-border-radius-base: 0;
@table-header-color: #333;
@table-header-bg: fade(@redash-gray, 3%);
@table-header-icon-color: fade(@text-color, 20%);
@table-header-icon-active-color: @text-color;
@table-header-sort-bg: @table-header-bg;
@table-header-sort-active-bg: @table-header-bg;
@table-header-filter-active-bg: @table-header-bg;
@table-body-sort-bg: transparent;
@table-row-hover-bg: fade(@redash-gray, 5%);
@table-padding-vertical: 7px;
@table-padding-horizontal: 10px;

/* --------------------------------------------------------
    Notification
-----------------------------------------------------------*/
@notification-padding: @notification-padding-vertical 48px @notification-padding-vertical 17px;
@notification-width: auto;


================================================
FILE: client/app/assets/less/inc/bas
Download .txt
gitextract_b07d1bqv/

├── .ci/
│   ├── Dockerfile.cypress
│   ├── compose.ci.yaml
│   ├── compose.cypress.yaml
│   ├── docker_build
│   ├── pack
│   └── update_version
├── .coveragerc
├── .dockerignore
├── .editorconfig
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── ---bug_report.md
│   │   └── --anything_else.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── config.yml
│   ├── weekly-digest.yml
│   └── workflows/
│       ├── ci.yml
│       ├── periodic-snapshot.yml
│       ├── preview-image.yml
│       └── restyled.yml
├── .gitignore
├── .npmrc
├── .nvmrc
├── .pre-commit-config.yaml
├── .restyled.yaml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── LICENSE.borders
├── Makefile
├── README.md
├── SECURITY.md
├── bin/
│   ├── docker-entrypoint
│   ├── get_changes.py
│   ├── release_manager.py
│   └── run
├── client/
│   ├── .babelrc
│   ├── .eslintignore
│   ├── .eslintrc.js
│   ├── .gitignore
│   ├── app/
│   │   ├── .eslintrc.js
│   │   ├── __tests__/
│   │   │   ├── enzyme_setup.js
│   │   │   └── mocks.js
│   │   ├── assets/
│   │   │   ├── css/
│   │   │   │   └── login.css
│   │   │   ├── images/
│   │   │   │   └── illustrations/
│   │   │   │       └── readme.md
│   │   │   ├── less/
│   │   │   │   ├── STYLING-README.md
│   │   │   │   ├── ant.less
│   │   │   │   ├── inc/
│   │   │   │   │   ├── 404.less
│   │   │   │   │   ├── ace-editor.less
│   │   │   │   │   ├── alert.less
│   │   │   │   │   ├── ant-variables.less
│   │   │   │   │   ├── base.less
│   │   │   │   │   ├── bootstrap-overrides.less
│   │   │   │   │   ├── breadcrumb.less
│   │   │   │   │   ├── button.less
│   │   │   │   │   ├── carousel.less
│   │   │   │   │   ├── chart.less
│   │   │   │   │   ├── dropdown.less
│   │   │   │   │   ├── edit-in-place.less
│   │   │   │   │   ├── flex.less
│   │   │   │   │   ├── font.less
│   │   │   │   │   ├── form.less
│   │   │   │   │   ├── generics.less
│   │   │   │   │   ├── header.less
│   │   │   │   │   ├── ie-warning.less
│   │   │   │   │   ├── jumbotron.less
│   │   │   │   │   ├── label.less
│   │   │   │   │   ├── less-plugins/
│   │   │   │   │   │   └── for.less
│   │   │   │   │   ├── list-group.less
│   │   │   │   │   ├── list.less
│   │   │   │   │   ├── login.less
│   │   │   │   │   ├── media.less
│   │   │   │   │   ├── messages.less
│   │   │   │   │   ├── misc.less
│   │   │   │   │   ├── mixins.less
│   │   │   │   │   ├── modal.less
│   │   │   │   │   ├── panel.less
│   │   │   │   │   ├── photos.less
│   │   │   │   │   ├── popover.less
│   │   │   │   │   ├── pricing-table.less
│   │   │   │   │   ├── print.less
│   │   │   │   │   ├── profile.less
│   │   │   │   │   ├── progress-bar.less
│   │   │   │   │   ├── schema-browser.less
│   │   │   │   │   ├── sidebar.less
│   │   │   │   │   ├── table.less
│   │   │   │   │   ├── tile.less
│   │   │   │   │   ├── tooltips.less
│   │   │   │   │   ├── variables.less
│   │   │   │   │   ├── visualizations/
│   │   │   │   │   │   ├── box.less
│   │   │   │   │   │   ├── map.less
│   │   │   │   │   │   ├── misc.less
│   │   │   │   │   │   └── pivot-table.less
│   │   │   │   │   ├── well.less
│   │   │   │   │   └── widgets.less
│   │   │   │   ├── main.less
│   │   │   │   ├── redash/
│   │   │   │   │   ├── css-logo.less
│   │   │   │   │   ├── loading-indicator.less
│   │   │   │   │   ├── query.less
│   │   │   │   │   ├── redash-table.less
│   │   │   │   │   └── tags-control.less
│   │   │   │   └── server.less
│   │   │   └── robots.txt
│   │   ├── components/
│   │   │   ├── AceEditorInput.jsx
│   │   │   ├── AceEditorInput.less
│   │   │   ├── ApplicationArea/
│   │   │   │   ├── ApplicationLayout/
│   │   │   │   │   ├── DesktopNavbar.jsx
│   │   │   │   │   ├── DesktopNavbar.less
│   │   │   │   │   ├── MobileNavbar.jsx
│   │   │   │   │   ├── MobileNavbar.less
│   │   │   │   │   ├── VersionInfo.jsx
│   │   │   │   │   ├── index.jsx
│   │   │   │   │   └── index.less
│   │   │   │   ├── ErrorMessage.jsx
│   │   │   │   ├── ErrorMessage.less
│   │   │   │   ├── ErrorMessage.test.js
│   │   │   │   ├── ErrorMessageDetails.jsx
│   │   │   │   ├── Router.jsx
│   │   │   │   ├── handleNavigationIntent.js
│   │   │   │   ├── index.jsx
│   │   │   │   ├── navigateTo.js
│   │   │   │   ├── routeWithApiKeySession.jsx
│   │   │   │   └── routeWithUserSession.tsx
│   │   │   ├── BeaconConsent.jsx
│   │   │   ├── BigMessage.jsx
│   │   │   ├── CodeBlock.jsx
│   │   │   ├── CodeBlock.less
│   │   │   ├── Collapse.jsx
│   │   │   ├── CreateSourceDialog.jsx
│   │   │   ├── DateInput.jsx
│   │   │   ├── DateRangeInput.jsx
│   │   │   ├── DateTimeInput.jsx
│   │   │   ├── DateTimeRangeInput.jsx
│   │   │   ├── DialogWrapper.d.ts
│   │   │   ├── DialogWrapper.jsx
│   │   │   ├── DynamicComponent.jsx
│   │   │   ├── EditInPlace.jsx
│   │   │   ├── EditParameterSettingsDialog.jsx
│   │   │   ├── EditParameterSettingsDialog.less
│   │   │   ├── EditVisualizationButton/
│   │   │   │   ├── QueryControlDropdown.jsx
│   │   │   │   ├── QueryResultsLink.jsx
│   │   │   │   └── index.jsx
│   │   │   ├── EmailSettingsWarning.jsx
│   │   │   ├── FavoritesControl.jsx
│   │   │   ├── Filters.jsx
│   │   │   ├── HelpTrigger.jsx
│   │   │   ├── HelpTrigger.less
│   │   │   ├── InputWithCopy.jsx
│   │   │   ├── Link.tsx
│   │   │   ├── NoTaggedObjectsFound.jsx
│   │   │   ├── PageHeader/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── Paginator.jsx
│   │   │   ├── ParameterApplyButton.jsx
│   │   │   ├── ParameterMappingInput.jsx
│   │   │   ├── ParameterMappingInput.less
│   │   │   ├── ParameterValueInput.jsx
│   │   │   ├── ParameterValueInput.less
│   │   │   ├── Parameters.jsx
│   │   │   ├── Parameters.less
│   │   │   ├── PermissionsEditorDialog/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── PlainButton.less
│   │   │   ├── PlainButton.tsx
│   │   │   ├── PreviewCard.jsx
│   │   │   ├── QueryBasedParameterInput.jsx
│   │   │   ├── QueryLink.jsx
│   │   │   ├── QueryLink.less
│   │   │   ├── QuerySelector.jsx
│   │   │   ├── Resizable/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── SelectItemsDialog.jsx
│   │   │   ├── SelectItemsDialog.less
│   │   │   ├── SelectWithVirtualScroll.tsx
│   │   │   ├── SettingsWrapper.jsx
│   │   │   ├── TagsList.less
│   │   │   ├── TagsList.tsx
│   │   │   ├── TimeAgo.jsx
│   │   │   ├── Timer.jsx
│   │   │   ├── Tooltip.tsx
│   │   │   ├── UserGroups.jsx
│   │   │   ├── UserGroups.less
│   │   │   ├── admin/
│   │   │   │   ├── Layout.jsx
│   │   │   │   ├── RQStatus.jsx
│   │   │   │   ├── StatusBlock.jsx
│   │   │   │   └── layout.less
│   │   │   ├── cards-list/
│   │   │   │   ├── CardsList.less
│   │   │   │   └── CardsList.tsx
│   │   │   ├── dashboards/
│   │   │   │   ├── AddWidgetDialog.jsx
│   │   │   │   ├── AutoHeightController.js
│   │   │   │   ├── CreateDashboardDialog.jsx
│   │   │   │   ├── DashboardGrid.jsx
│   │   │   │   ├── EditParameterMappingsDialog.jsx
│   │   │   │   ├── ExpandedWidgetDialog.jsx
│   │   │   │   ├── TextboxDialog.jsx
│   │   │   │   ├── TextboxDialog.less
│   │   │   │   ├── dashboard-grid.less
│   │   │   │   └── dashboard-widget/
│   │   │   │       ├── RestrictedWidget.jsx
│   │   │   │       ├── TextboxWidget.jsx
│   │   │   │       ├── VisualizationWidget.jsx
│   │   │   │       ├── Widget.jsx
│   │   │   │       ├── Widget.less
│   │   │   │       └── index.js
│   │   │   ├── dynamic-form/
│   │   │   │   ├── DynamicForm.jsx
│   │   │   │   ├── DynamicForm.less
│   │   │   │   ├── DynamicFormField.jsx
│   │   │   │   ├── dynamicFormHelper.js
│   │   │   │   ├── fields/
│   │   │   │   │   ├── AceEditorField.jsx
│   │   │   │   │   ├── CheckboxField.jsx
│   │   │   │   │   ├── ContentField.jsx
│   │   │   │   │   ├── FileField.jsx
│   │   │   │   │   ├── InputField.jsx
│   │   │   │   │   ├── NumberField.jsx
│   │   │   │   │   ├── SelectField.jsx
│   │   │   │   │   ├── TextAreaField.jsx
│   │   │   │   │   └── index.js
│   │   │   │   └── getFieldLabel.js
│   │   │   ├── dynamic-parameters/
│   │   │   │   ├── DateParameter.jsx
│   │   │   │   ├── DateRangeParameter.jsx
│   │   │   │   ├── DynamicButton.jsx
│   │   │   │   ├── DynamicButton.less
│   │   │   │   ├── DynamicDatePicker.jsx
│   │   │   │   ├── DynamicDateRangePicker.jsx
│   │   │   │   └── DynamicParameters.less
│   │   │   ├── empty-state/
│   │   │   │   ├── EmptyState.d.ts
│   │   │   │   ├── EmptyState.jsx
│   │   │   │   └── empty-state.less
│   │   │   ├── groups/
│   │   │   │   ├── CreateGroupDialog.jsx
│   │   │   │   ├── DeleteGroupButton.jsx
│   │   │   │   ├── DetailsPageSidebar.jsx
│   │   │   │   ├── GroupName.jsx
│   │   │   │   └── ListItemAddon.jsx
│   │   │   ├── items-list/
│   │   │   │   ├── ItemsList.tsx
│   │   │   │   ├── classes/
│   │   │   │   │   ├── ItemsFetcher.js
│   │   │   │   │   ├── ItemsSource.d.ts
│   │   │   │   │   ├── ItemsSource.js
│   │   │   │   │   ├── Paginator.js
│   │   │   │   │   ├── Sorter.js
│   │   │   │   │   └── StateStorage.js
│   │   │   │   ├── components/
│   │   │   │   │   ├── EmptyState.jsx
│   │   │   │   │   ├── ItemsTable.jsx
│   │   │   │   │   ├── LoadingState.jsx
│   │   │   │   │   └── Sidebar.jsx
│   │   │   │   └── hooks/
│   │   │   │       └── useItemsListExtraActions.js
│   │   │   ├── layouts/
│   │   │   │   ├── ContentWithSidebar.jsx
│   │   │   │   └── content-with-sidebar.less
│   │   │   ├── proptypes.js
│   │   │   ├── queries/
│   │   │   │   ├── AddToDashboardDialog.jsx
│   │   │   │   ├── ApiKeyDialog/
│   │   │   │   │   ├── index.jsx
│   │   │   │   │   └── index.less
│   │   │   │   ├── EmbedQueryDialog.jsx
│   │   │   │   ├── EmbedQueryDialog.less
│   │   │   │   ├── QueryEditor/
│   │   │   │   │   ├── AutoLimitCheckbox.jsx
│   │   │   │   │   ├── AutocompleteToggle.jsx
│   │   │   │   │   ├── QueryEditorControls.jsx
│   │   │   │   │   ├── QueryEditorControls.less
│   │   │   │   │   ├── ace.js
│   │   │   │   │   ├── index.jsx
│   │   │   │   │   └── index.less
│   │   │   │   ├── ScheduleDialog.css
│   │   │   │   ├── ScheduleDialog.jsx
│   │   │   │   ├── ScheduleDialog.test.js
│   │   │   │   ├── SchedulePhrase.jsx
│   │   │   │   ├── SchemaBrowser.jsx
│   │   │   │   ├── __snapshots__/
│   │   │   │   │   └── ScheduleDialog.test.js.snap
│   │   │   │   ├── add-to-dashboard-dialog.less
│   │   │   │   └── editor-components/
│   │   │   │       ├── databricks/
│   │   │   │       │   ├── DatabricksSchemaBrowser.jsx
│   │   │   │       │   ├── DatabricksSchemaBrowser.less
│   │   │   │       │   └── useDatabricksSchema.js
│   │   │   │       ├── editorComponents.js
│   │   │   │       └── index.js
│   │   │   ├── query-snippets/
│   │   │   │   └── QuerySnippetDialog.jsx
│   │   │   ├── tags-control/
│   │   │   │   ├── EditTagsDialog.jsx
│   │   │   │   └── TagsControl.jsx
│   │   │   └── visualizations/
│   │   │       ├── EditVisualizationDialog.jsx
│   │   │       ├── EditVisualizationDialog.less
│   │   │       ├── VisualizationName.jsx
│   │   │       ├── VisualizationName.less
│   │   │       ├── VisualizationRenderer.jsx
│   │   │       └── visualizationComponents.jsx
│   │   ├── config/
│   │   │   ├── antd-spinner.jsx
│   │   │   ├── dashboard-grid-options.js
│   │   │   └── index.js
│   │   ├── extensions/
│   │   │   └── .gitkeep
│   │   ├── index.html
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── accessibility.ts
│   │   │   ├── calculateTextWidth.ts
│   │   │   ├── hooks/
│   │   │   │   ├── useFullscreenHandler.js
│   │   │   │   ├── useImmutableCallback.js
│   │   │   │   ├── useLazyRef.ts
│   │   │   │   ├── useSearchResults.js
│   │   │   │   └── useUniqueId.ts
│   │   │   ├── localOptions.js
│   │   │   ├── pagination/
│   │   │   │   ├── index.js
│   │   │   │   └── paginator.js
│   │   │   ├── queryFormat.test.js
│   │   │   ├── queryFormat.ts
│   │   │   ├── useQueryResultData.js
│   │   │   └── utils.js
│   │   ├── multi_org.html
│   │   ├── pages/
│   │   │   ├── admin/
│   │   │   │   ├── Jobs.jsx
│   │   │   │   ├── OutdatedQueries.jsx
│   │   │   │   ├── SystemStatus.jsx
│   │   │   │   └── system-status.less
│   │   │   ├── alert/
│   │   │   │   ├── Alert.jsx
│   │   │   │   ├── AlertEdit.jsx
│   │   │   │   ├── AlertNew.jsx
│   │   │   │   ├── AlertView.jsx
│   │   │   │   └── components/
│   │   │   │       ├── AlertDestinations.jsx
│   │   │   │       ├── AlertDestinations.less
│   │   │   │       ├── Criteria.jsx
│   │   │   │       ├── Criteria.less
│   │   │   │       ├── HorizontalFormItem.jsx
│   │   │   │       ├── MenuButton.jsx
│   │   │   │       ├── NotificationTemplate.jsx
│   │   │   │       ├── NotificationTemplate.less
│   │   │   │       ├── Query.jsx
│   │   │   │       ├── Query.less
│   │   │   │       ├── Rearm.jsx
│   │   │   │       ├── Rearm.less
│   │   │   │       ├── Title.jsx
│   │   │   │       └── Title.less
│   │   │   ├── alerts/
│   │   │   │   └── AlertsList.jsx
│   │   │   ├── dashboards/
│   │   │   │   ├── DashboardList.jsx
│   │   │   │   ├── DashboardPage.jsx
│   │   │   │   ├── DashboardPage.less
│   │   │   │   ├── PublicDashboardPage.jsx
│   │   │   │   ├── PublicDashboardPage.less
│   │   │   │   ├── components/
│   │   │   │   │   ├── DashboardHeader.jsx
│   │   │   │   │   ├── DashboardHeader.less
│   │   │   │   │   ├── DashboardListEmptyState.tsx
│   │   │   │   │   └── ShareDashboardDialog.jsx
│   │   │   │   ├── dashboard-list.css
│   │   │   │   └── hooks/
│   │   │   │       ├── useDashboard.js
│   │   │   │       ├── useDataSources.js
│   │   │   │       ├── useDuplicateDashboard.js
│   │   │   │       ├── useEditModeHandler.js
│   │   │   │       └── useRefreshRateHandler.js
│   │   │   ├── data-sources/
│   │   │   │   ├── DataSourcesList.jsx
│   │   │   │   └── EditDataSource.jsx
│   │   │   ├── destinations/
│   │   │   │   ├── DestinationsList.jsx
│   │   │   │   └── EditDestination.jsx
│   │   │   ├── groups/
│   │   │   │   ├── GroupDataSources.jsx
│   │   │   │   ├── GroupMembers.jsx
│   │   │   │   └── GroupsList.jsx
│   │   │   ├── home/
│   │   │   │   ├── Home.jsx
│   │   │   │   ├── Home.less
│   │   │   │   └── components/
│   │   │   │       └── FavoritesList.jsx
│   │   │   ├── index.js
│   │   │   ├── queries/
│   │   │   │   ├── QuerySource.jsx
│   │   │   │   ├── QuerySource.less
│   │   │   │   ├── QueryView.jsx
│   │   │   │   ├── QueryView.less
│   │   │   │   ├── VisualizationEmbed.jsx
│   │   │   │   ├── components/
│   │   │   │   │   ├── QueryExecutionMetadata.jsx
│   │   │   │   │   ├── QueryExecutionMetadata.less
│   │   │   │   │   ├── QueryExecutionStatus.jsx
│   │   │   │   │   ├── QueryMetadata.jsx
│   │   │   │   │   ├── QueryMetadata.less
│   │   │   │   │   ├── QueryPageHeader.jsx
│   │   │   │   │   ├── QueryPageHeader.less
│   │   │   │   │   ├── QuerySourceAlerts.jsx
│   │   │   │   │   ├── QuerySourceAlerts.less
│   │   │   │   │   ├── QuerySourceDropdown.jsx
│   │   │   │   │   ├── QuerySourceDropdownItem.jsx
│   │   │   │   │   ├── QuerySourceTypeIcon.jsx
│   │   │   │   │   ├── QueryViewButton.jsx
│   │   │   │   │   ├── QueryVisualizationTabs.jsx
│   │   │   │   │   ├── QueryVisualizationTabs.less
│   │   │   │   │   └── wrapQueryPage.jsx
│   │   │   │   └── hooks/
│   │   │   │       ├── useAddNewParameterDialog.js
│   │   │   │       ├── useAddToDashboardDialog.js
│   │   │   │       ├── useAddVisualizationDialog.js
│   │   │   │       ├── useApiKeyDialog.js
│   │   │   │       ├── useArchiveQuery.jsx
│   │   │   │       ├── useAutoLimitFlags.js
│   │   │   │       ├── useAutocompleteFlags.js
│   │   │   │       ├── useDataSourceSchema.js
│   │   │   │       ├── useDeleteVisualization.js
│   │   │   │       ├── useDuplicateQuery.js
│   │   │   │       ├── useEditScheduleDialog.js
│   │   │   │       ├── useEditVisualizationDialog.js
│   │   │   │       ├── useEmbedDialog.js
│   │   │   │       ├── usePermissionsEditorDialog.js
│   │   │   │       ├── usePublishQuery.js
│   │   │   │       ├── useQuery.js
│   │   │   │       ├── useQueryDataSources.js
│   │   │   │       ├── useQueryExecute.js
│   │   │   │       ├── useQueryFlags.js
│   │   │   │       ├── useQueryParameters.js
│   │   │   │       ├── useRenameQuery.js
│   │   │   │       ├── useUnpublishQuery.js
│   │   │   │       ├── useUnsavedChangesAlert.js
│   │   │   │       ├── useUpdateQuery.jsx
│   │   │   │       ├── useUpdateQueryDescription.js
│   │   │   │       ├── useUpdateQueryTags.js
│   │   │   │       └── useVisualizationTabHandler.js
│   │   │   ├── queries-list/
│   │   │   │   ├── QueriesList.jsx
│   │   │   │   ├── QueriesListEmptyState.jsx
│   │   │   │   └── queries-list.css
│   │   │   ├── query-snippets/
│   │   │   │   ├── QuerySnippetsList.jsx
│   │   │   │   └── QuerySnippetsList.less
│   │   │   ├── settings/
│   │   │   │   ├── OrganizationSettings.jsx
│   │   │   │   ├── components/
│   │   │   │   │   ├── AuthSettings/
│   │   │   │   │   │   ├── GoogleLoginSettings.jsx
│   │   │   │   │   │   ├── PasswordLoginSettings.jsx
│   │   │   │   │   │   ├── SAMLSettings.jsx
│   │   │   │   │   │   └── index.jsx
│   │   │   │   │   ├── GeneralSettings/
│   │   │   │   │   │   ├── BeaconConsentSettings.jsx
│   │   │   │   │   │   ├── FeatureFlagsSettings.jsx
│   │   │   │   │   │   ├── FormatSettings.jsx
│   │   │   │   │   │   ├── PlotlySettings.jsx
│   │   │   │   │   │   └── index.jsx
│   │   │   │   │   └── prop-types.js
│   │   │   │   └── hooks/
│   │   │   │       └── useOrganizationSettings.js
│   │   │   └── users/
│   │   │       ├── UserProfile.jsx
│   │   │       ├── UsersList.jsx
│   │   │       ├── components/
│   │   │       │   ├── ApiKeyForm.jsx
│   │   │       │   ├── CreateUserDialog.jsx
│   │   │       │   ├── EditableUserProfile.jsx
│   │   │       │   ├── PasswordForm/
│   │   │       │   │   ├── ChangePasswordDialog.jsx
│   │   │       │   │   ├── PasswordLinkAlert.jsx
│   │   │       │   │   ├── PasswordResetForm.jsx
│   │   │       │   │   ├── ResendInvitationForm.jsx
│   │   │       │   │   └── index.jsx
│   │   │       │   ├── ReadOnlyUserProfile.jsx
│   │   │       │   ├── ReadOnlyUserProfile.test.js
│   │   │       │   ├── ToggleUserForm.jsx
│   │   │       │   ├── UserInfoForm.jsx
│   │   │       │   └── __snapshots__/
│   │   │       │       └── ReadOnlyUserProfile.test.js.snap
│   │   │       ├── hooks/
│   │   │       │   └── useUserGroups.js
│   │   │       └── settings.less
│   │   ├── redash-font/
│   │   │   ├── style.less
│   │   │   └── variables.less
│   │   ├── services/
│   │   │   ├── KeyboardShortcuts.js
│   │   │   ├── alert-subscription.js
│   │   │   ├── alert.js
│   │   │   ├── auth.js
│   │   │   ├── auth.test.js
│   │   │   ├── axios.js
│   │   │   ├── dashboard.js
│   │   │   ├── data-source.js
│   │   │   ├── databricks-data-source.js
│   │   │   ├── destination.js
│   │   │   ├── getTags.js
│   │   │   ├── group.js
│   │   │   ├── location.js
│   │   │   ├── notification.d.ts
│   │   │   ├── notification.js
│   │   │   ├── notifications.js
│   │   │   ├── offline-listener.js
│   │   │   ├── organizationSettings.js
│   │   │   ├── organizationStatus.js
│   │   │   ├── parameters/
│   │   │   │   ├── DateParameter.js
│   │   │   │   ├── DateRangeParameter.js
│   │   │   │   ├── EnumParameter.js
│   │   │   │   ├── NumberParameter.js
│   │   │   │   ├── Parameter.js
│   │   │   │   ├── QueryBasedDropdownParameter.js
│   │   │   │   ├── TextParameter.js
│   │   │   │   ├── TextPatternParameter.js
│   │   │   │   ├── index.js
│   │   │   │   └── tests/
│   │   │   │       ├── DateParameter.test.js
│   │   │   │       ├── DateRangeParameter.test.js
│   │   │   │       ├── EnumParameter.test.js
│   │   │   │       ├── NumberParameter.test.js
│   │   │   │       ├── Parameter.test.js
│   │   │   │       ├── QueryBasedDropdownParameter.test.js
│   │   │   │       ├── TextParameter.test.js
│   │   │   │       └── TextPatternParameter.test.js
│   │   │   ├── policy/
│   │   │   │   ├── DefaultPolicy.js
│   │   │   │   └── index.js
│   │   │   ├── query-result.js
│   │   │   ├── query-result.test.js
│   │   │   ├── query-snippet.js
│   │   │   ├── query.js
│   │   │   ├── recordEvent.js
│   │   │   ├── resizeObserver.js
│   │   │   ├── restoreSession.jsx
│   │   │   ├── routes.ts
│   │   │   ├── sanitize.js
│   │   │   ├── settingsMenu.js
│   │   │   ├── settingsMenu.test.js
│   │   │   ├── url.js
│   │   │   ├── user.js
│   │   │   ├── utils.js
│   │   │   ├── visualization.js
│   │   │   └── widget.js
│   │   ├── styles/
│   │   │   ├── formStyle.less
│   │   │   └── formStyle.ts
│   │   ├── unsupported.html
│   │   ├── unsupportedRedirect.js
│   │   └── version.json
│   ├── cypress/
│   │   ├── .eslintrc.js
│   │   ├── cypress.js
│   │   ├── integration/
│   │   │   ├── alert/
│   │   │   │   ├── create_alert_spec.js
│   │   │   │   ├── edit_alert_spec.js
│   │   │   │   └── view_alert_spec.js
│   │   │   ├── dashboard/
│   │   │   │   ├── dashboard_list.js
│   │   │   │   ├── dashboard_spec.js
│   │   │   │   ├── dashboard_tags_spec.js
│   │   │   │   ├── filters_spec.js
│   │   │   │   ├── grid_compliant_widgets_spec.js
│   │   │   │   ├── parameter_spec.js
│   │   │   │   ├── sharing_spec.js
│   │   │   │   ├── textbox_spec.js
│   │   │   │   └── widget_spec.js
│   │   │   ├── data-source/
│   │   │   │   ├── create_data_source_spec.js
│   │   │   │   └── edit_data_source_spec.js
│   │   │   ├── destination/
│   │   │   │   └── create_destination_spec.js
│   │   │   ├── embed/
│   │   │   │   └── share_embed_spec.js
│   │   │   ├── group/
│   │   │   │   ├── edit_group_spec.js
│   │   │   │   └── group_list_spec.js
│   │   │   ├── query/
│   │   │   │   ├── create_query_spec.js
│   │   │   │   ├── filters_spec.js
│   │   │   │   ├── parameter_spec.js
│   │   │   │   └── query_tags_spec.js
│   │   │   ├── query-snippets/
│   │   │   │   └── create_query_snippet_spec.js
│   │   │   ├── settings/
│   │   │   │   ├── organization_settings_spec.js
│   │   │   │   └── settings_tabs_spec.js
│   │   │   ├── user/
│   │   │   │   ├── create_user_spec.js
│   │   │   │   ├── edit_profile_spec.js
│   │   │   │   ├── login_spec.js
│   │   │   │   ├── logout_spec.js
│   │   │   │   └── user_list_spec.js
│   │   │   └── visualizations/
│   │   │       ├── box_plot_spec.js
│   │   │       ├── chart_spec.js
│   │   │       ├── choropleth_spec.js
│   │   │       ├── cohort_spec.js
│   │   │       ├── counter_spec.js
│   │   │       ├── edit_visualization_dialog_spec.js
│   │   │       ├── funnel_spec.js
│   │   │       ├── map_spec.js
│   │   │       ├── pivot_spec.js
│   │   │       ├── sankey_sunburst_spec.js
│   │   │       ├── table/
│   │   │       │   ├── .mocks/
│   │   │       │   │   ├── all-cell-types.js
│   │   │       │   │   ├── large-dataset.js
│   │   │       │   │   ├── multi-column-sort.js
│   │   │       │   │   └── search-in-data.js
│   │   │       │   └── table_spec.js
│   │   │       └── word_cloud_spec.js
│   │   ├── seed-data.js
│   │   ├── support/
│   │   │   ├── commands.js
│   │   │   ├── dashboard/
│   │   │   │   └── index.js
│   │   │   ├── index.js
│   │   │   ├── parameters.js
│   │   │   ├── redash-api/
│   │   │   │   └── index.js
│   │   │   ├── tags/
│   │   │   │   └── index.js
│   │   │   └── visualizations/
│   │   │       ├── chart.js
│   │   │       └── table.js
│   │   └── tsconfig.json
│   ├── prettier.config.js
│   └── tsconfig.json
├── codecov.yml
├── compose.yaml
├── cypress.config.js
├── manage.py
├── migrations/
│   ├── 0001_warning.py
│   ├── README
│   ├── alembic.ini
│   ├── env.py
│   ├── script.py.mako
│   └── versions/
│       ├── 0ec979123ba4_.py
│       ├── 0f740a081d20_inline_tags.py
│       ├── 1038c2174f5d_make_case_insensitive_hash_of_query_text.py
│       ├── 1655999df5e3_default_alert_selector.py
│       ├── 1daa601d3ae5_add_columns_for_disabled_users.py
│       ├── 5ec5c84ba61e_.py
│       ├── 640888ce445d_.py
│       ├── 65fc9ede4746_add_is_draft_status_to_queries_and_.py
│       ├── 6b5be7e0a0ef_.py
│       ├── 71477dadd6ef_favorites_unique_constraint.py
│       ├── 7205816877ec_change_type_of_json_fields_from_varchar_.py
│       ├── 73beceabb948_bring_back_null_schedule.py
│       ├── 7671dca4e604_.py
│       ├── 7ce5925f832b_create_sqlalchemy_searchable_expressions.py
│       ├── 89bc7873a3e0_fix_multiple_heads.py
│       ├── 969126bd800f_.py
│       ├── 98af61feea92_add_encrypted_options_to_data_sources.py
│       ├── 9e8c841d1a30_fix_hash.py
│       ├── a92d92aa678e_inline_tags.py
│       ├── d1eae8b9893e_.py
│       ├── d4c798575877_create_favorites.py
│       ├── d7d747033183_encrypt_alert_destinations.py
│       ├── db0aca1ebd32_12_column_dashboard_layout.py
│       ├── e5c7a4e2df4d_remove_query_tracker_keys.py
│       ├── e7004224f284_add_org_id_to_favorites.py
│       ├── e7f8a917aa8e_add_user_details_json_column.py
│       └── fd4fc850d7ea_.py
├── netlify.toml
├── package.json
├── pnpm-workspace.yaml
├── pyproject.toml
├── pytest.ini
├── redash/
│   ├── __init__.py
│   ├── app.py
│   ├── authentication/
│   │   ├── __init__.py
│   │   ├── account.py
│   │   ├── google_oauth.py
│   │   ├── jwt_auth.py
│   │   ├── ldap_auth.py
│   │   ├── org_resolving.py
│   │   ├── remote_user_auth.py
│   │   └── saml_auth.py
│   ├── cli/
│   │   ├── __init__.py
│   │   ├── data_sources.py
│   │   ├── database.py
│   │   ├── groups.py
│   │   ├── organization.py
│   │   ├── queries.py
│   │   ├── rq.py
│   │   └── users.py
│   ├── destinations/
│   │   ├── __init__.py
│   │   ├── asana.py
│   │   ├── chatwork.py
│   │   ├── datadog.py
│   │   ├── discord.py
│   │   ├── email.py
│   │   ├── hangoutschat.py
│   │   ├── mattermost.py
│   │   ├── microsoft_teams_webhook.py
│   │   ├── pagerduty.py
│   │   ├── slack.py
│   │   ├── webex.py
│   │   └── webhook.py
│   ├── handlers/
│   │   ├── __init__.py
│   │   ├── admin.py
│   │   ├── alerts.py
│   │   ├── api.py
│   │   ├── authentication.py
│   │   ├── base.py
│   │   ├── dashboards.py
│   │   ├── data_sources.py
│   │   ├── databricks.py
│   │   ├── destinations.py
│   │   ├── embed.py
│   │   ├── events.py
│   │   ├── favorites.py
│   │   ├── groups.py
│   │   ├── organization.py
│   │   ├── permissions.py
│   │   ├── queries.py
│   │   ├── query_results.py
│   │   ├── query_snippets.py
│   │   ├── settings.py
│   │   ├── setup.py
│   │   ├── static.py
│   │   ├── users.py
│   │   ├── visualizations.py
│   │   ├── webpack.py
│   │   └── widgets.py
│   ├── metrics/
│   │   ├── __init__.py
│   │   ├── database.py
│   │   └── request.py
│   ├── models/
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── changes.py
│   │   ├── mixins.py
│   │   ├── organizations.py
│   │   ├── parameterized_query.py
│   │   ├── types.py
│   │   └── users.py
│   ├── monitor.py
│   ├── permissions.py
│   ├── query_runner/
│   │   ├── __init__.py
│   │   ├── amazon_elasticsearch.py
│   │   ├── arango.py
│   │   ├── athena.py
│   │   ├── axibase_tsd.py
│   │   ├── azure_kusto.py
│   │   ├── big_query.py
│   │   ├── big_query_gce.py
│   │   ├── cass.py
│   │   ├── clickhouse.py
│   │   ├── cloudwatch.py
│   │   ├── cloudwatch_insights.py
│   │   ├── corporate_memory.py
│   │   ├── couchbase.py
│   │   ├── csv.py
│   │   ├── databend.py
│   │   ├── databricks.py
│   │   ├── db2.py
│   │   ├── dgraph.py
│   │   ├── drill.py
│   │   ├── druid.py
│   │   ├── duckdb.py
│   │   ├── e6data.py
│   │   ├── elasticsearch.py
│   │   ├── elasticsearch2.py
│   │   ├── exasol.py
│   │   ├── excel.py
│   │   ├── files/
│   │   │   ├── rds-combined-ca-bundle.pem
│   │   │   └── redshift-ca-bundle.crt
│   │   ├── google_analytics.py
│   │   ├── google_analytics4.py
│   │   ├── google_search_console.py
│   │   ├── google_spanner.py
│   │   ├── google_spreadsheets.py
│   │   ├── graphite.py
│   │   ├── hive_ds.py
│   │   ├── ignite.py
│   │   ├── impala_ds.py
│   │   ├── influx_db.py
│   │   ├── influx_db_v2.py
│   │   ├── jql.py
│   │   ├── json_ds.py
│   │   ├── kylin.py
│   │   ├── memsql_ds.py
│   │   ├── mongodb.py
│   │   ├── mssql.py
│   │   ├── mssql_odbc.py
│   │   ├── mysql.py
│   │   ├── nz.py
│   │   ├── oracle.py
│   │   ├── pg.py
│   │   ├── phoenix.py
│   │   ├── pinot.py
│   │   ├── presto.py
│   │   ├── prometheus.py
│   │   ├── python.py
│   │   ├── query_results.py
│   │   ├── risingwave.py
│   │   ├── rockset.py
│   │   ├── salesforce.py
│   │   ├── script.py
│   │   ├── snowflake.py
│   │   ├── sparql_endpoint.py
│   │   ├── sqlite.py
│   │   ├── tinybird.py
│   │   ├── treasuredata.py
│   │   ├── trino.py
│   │   ├── uptycs.py
│   │   ├── url.py
│   │   ├── vertica.py
│   │   ├── yandex_disk.py
│   │   └── yandex_metrica.py
│   ├── security.py
│   ├── serializers/
│   │   ├── __init__.py
│   │   └── query_result.py
│   ├── settings/
│   │   ├── __init__.py
│   │   ├── dynamic_settings.py
│   │   ├── helpers.py
│   │   └── organization.py
│   ├── tasks/
│   │   ├── __init__.py
│   │   ├── alerts.py
│   │   ├── databricks.py
│   │   ├── failure_report.py
│   │   ├── general.py
│   │   ├── queries/
│   │   │   ├── __init__.py
│   │   │   ├── execution.py
│   │   │   └── maintenance.py
│   │   ├── schedule.py
│   │   └── worker.py
│   ├── templates/
│   │   ├── _includes/
│   │   │   ├── signed_out_tail.html
│   │   │   └── tail.html
│   │   ├── emails/
│   │   │   ├── alert.html
│   │   │   ├── failures.html
│   │   │   ├── failures.txt
│   │   │   ├── invite.html
│   │   │   ├── invite.txt
│   │   │   ├── layout.html
│   │   │   ├── reset.html
│   │   │   ├── reset.txt
│   │   │   ├── reset_disabled.html
│   │   │   ├── reset_disabled.txt
│   │   │   ├── verify.html
│   │   │   └── verify.txt
│   │   ├── error.html
│   │   ├── forgot.html
│   │   ├── invite.html
│   │   ├── layouts/
│   │   │   └── signed_out.html
│   │   ├── login.html
│   │   ├── reset.html
│   │   ├── setup.html
│   │   └── verify.html
│   ├── utils/
│   │   ├── __init__.py
│   │   ├── configuration.py
│   │   ├── human_time.py
│   │   ├── pandas.py
│   │   ├── query_order.py
│   │   ├── requests_session.py
│   │   └── sentry.py
│   ├── version_check.py
│   ├── worker.py
│   └── wsgi.py
├── scripts/
│   └── README.md
├── setup/
│   └── README.md
├── tests/
│   ├── __init__.py
│   ├── destinations/
│   │   └── test_webhook.py
│   ├── factories.py
│   ├── handlers/
│   │   ├── __init__.py
│   │   ├── test_alerts.py
│   │   ├── test_authentication.py
│   │   ├── test_dashboards.py
│   │   ├── test_data_sources.py
│   │   ├── test_destinations.py
│   │   ├── test_embed.py
│   │   ├── test_favorites.py
│   │   ├── test_groups.py
│   │   ├── test_order_results.py
│   │   ├── test_paginate.py
│   │   ├── test_permissions.py
│   │   ├── test_queries.py
│   │   ├── test_query_results.py
│   │   ├── test_query_snippets.py
│   │   ├── test_settings.py
│   │   ├── test_users.py
│   │   ├── test_visualizations.py
│   │   └── test_widgets.py
│   ├── metrics/
│   │   ├── __init__.py
│   │   ├── test_database.py
│   │   └── test_request.py
│   ├── models/
│   │   ├── __init__.py
│   │   ├── test_alerts.py
│   │   ├── test_api_keys.py
│   │   ├── test_changes.py
│   │   ├── test_dashboards.py
│   │   ├── test_data_sources.py
│   │   ├── test_parameterized_query.py
│   │   ├── test_permissions.py
│   │   ├── test_queries.py
│   │   ├── test_query_results.py
│   │   └── test_users.py
│   ├── query_runner/
│   │   ├── __init__.py
│   │   ├── test_athena.py
│   │   ├── test_azure_kusto.py
│   │   ├── test_basequeryrunner.py
│   │   ├── test_basesql_queryrunner.py
│   │   ├── test_bigquery.py
│   │   ├── test_cass.py
│   │   ├── test_clickhouse.py
│   │   ├── test_databricks.py
│   │   ├── test_drill.py
│   │   ├── test_duckdb.py
│   │   ├── test_e6data.py
│   │   ├── test_elasticsearch2.py
│   │   ├── test_google_analytics4.py
│   │   ├── test_google_search_console.py
│   │   ├── test_google_spreadsheets.py
│   │   ├── test_http.py
│   │   ├── test_ignite.py
│   │   ├── test_influx_db.py
│   │   ├── test_influx_db_v2.py
│   │   ├── test_jql.py
│   │   ├── test_json_ds.py
│   │   ├── test_mongodb.py
│   │   ├── test_oracle.py
│   │   ├── test_pg.py
│   │   ├── test_prometheus.py
│   │   ├── test_python.py
│   │   ├── test_query_results.py
│   │   ├── test_script.py
│   │   ├── test_tinybird.py
│   │   ├── test_trino.py
│   │   ├── test_utils.py
│   │   ├── test_yandex_disk.py
│   │   └── test_yandex_metrica.py
│   ├── serializers/
│   │   ├── __init__.py
│   │   └── test_query_results.py
│   ├── tasks/
│   │   ├── __init__.py
│   │   ├── test_alerts.py
│   │   ├── test_empty_schedule.py
│   │   ├── test_failure_report.py
│   │   ├── test_queries.py
│   │   ├── test_refresh_queries.py
│   │   ├── test_refresh_schemas.py
│   │   ├── test_schedule.py
│   │   └── test_worker.py
│   ├── test_authentication.py
│   ├── test_cli.py
│   ├── test_configuration.py
│   ├── test_handlers.py
│   ├── test_migrations.py
│   ├── test_models.py
│   ├── test_monitor.py
│   ├── test_permissions.py
│   ├── test_utils.py
│   └── utils/
│       ├── __init__.py
│       └── test_json_dumps.py
├── viz-lib/
│   ├── .babelrc
│   ├── .gitignore
│   ├── CHANGELOG.md
│   ├── README.md
│   ├── __tests__/
│   │   ├── enzyme_setup.js
│   │   └── mocks.js
│   ├── package.json
│   ├── prettier.config.js
│   ├── src/
│   │   ├── components/
│   │   │   ├── ColorPicker/
│   │   │   │   ├── Input.tsx
│   │   │   │   ├── Label.tsx
│   │   │   │   ├── Swatch.tsx
│   │   │   │   ├── index.less
│   │   │   │   ├── index.tsx
│   │   │   │   ├── input.less
│   │   │   │   ├── label.less
│   │   │   │   ├── swatch.less
│   │   │   │   └── utils.ts
│   │   │   ├── ErrorBoundary.tsx
│   │   │   ├── HtmlContent.tsx
│   │   │   ├── TextAlignmentSelect/
│   │   │   │   ├── index.less
│   │   │   │   └── index.tsx
│   │   │   ├── json-view-interactive/
│   │   │   │   ├── JsonViewInteractive.tsx
│   │   │   │   └── json-view-interactive.less
│   │   │   ├── sortable/
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.less
│   │   │   └── visualizations/
│   │   │       └── editor/
│   │   │           ├── ContextHelp.tsx
│   │   │           ├── Section.less
│   │   │           ├── Section.tsx
│   │   │           ├── Switch.less
│   │   │           ├── Switch.tsx
│   │   │           ├── TextArea.less
│   │   │           ├── TextArea.tsx
│   │   │           ├── context-help.less
│   │   │           ├── control-label.less
│   │   │           ├── createTabbedEditor.tsx
│   │   │           ├── index.ts
│   │   │           └── withControlLabel.tsx
│   │   ├── index.ts
│   │   ├── lib/
│   │   │   ├── chooseTextColorForBackground.ts
│   │   │   ├── hooks/
│   │   │   │   └── useMemoWithDeepCompare.ts
│   │   │   ├── referenceCountingCache.ts
│   │   │   ├── utils.ts
│   │   │   └── value-format.tsx
│   │   ├── services/
│   │   │   ├── resizeObserver.ts
│   │   │   └── sanitize.ts
│   │   └── visualizations/
│   │       ├── ColorPalette.ts
│   │       ├── Editor.tsx
│   │       ├── Renderer.tsx
│   │       ├── box-plot/
│   │       │   ├── Editor.tsx
│   │       │   ├── Renderer.tsx
│   │       │   ├── d3box.ts
│   │       │   ├── index.ts
│   │       │   └── renderer.less
│   │       ├── chart/
│   │       │   ├── Editor/
│   │       │   │   ├── AxisSettings.tsx
│   │       │   │   ├── ChartTypeSelect.tsx
│   │       │   │   ├── ColorsSettings.test.tsx
│   │       │   │   ├── ColorsSettings.tsx
│   │       │   │   ├── ColumnMappingSelect.tsx
│   │       │   │   ├── CustomChartSettings.tsx
│   │       │   │   ├── DataLabelsSettings.test.tsx
│   │       │   │   ├── DataLabelsSettings.tsx
│   │       │   │   ├── DefaultColorsSettings.tsx
│   │       │   │   ├── GeneralSettings.test.tsx
│   │       │   │   ├── GeneralSettings.tsx
│   │       │   │   ├── HeatmapColorsSettings.tsx
│   │       │   │   ├── PieColorsSettings.tsx
│   │       │   │   ├── SeriesSettings.test.tsx
│   │       │   │   ├── SeriesSettings.tsx
│   │       │   │   ├── XAxisSettings.test.tsx
│   │       │   │   ├── XAxisSettings.tsx
│   │       │   │   ├── YAxisSettings.test.tsx
│   │       │   │   ├── YAxisSettings.tsx
│   │       │   │   ├── __snapshots__/
│   │       │   │   │   ├── ColorsSettings.test.tsx.snap
│   │       │   │   │   ├── DataLabelsSettings.test.tsx.snap
│   │       │   │   │   ├── GeneralSettings.test.tsx.snap
│   │       │   │   │   ├── SeriesSettings.test.tsx.snap
│   │       │   │   │   ├── XAxisSettings.test.tsx.snap
│   │       │   │   │   └── YAxisSettings.test.tsx.snap
│   │       │   │   ├── editor.less
│   │       │   │   ├── index.test.tsx
│   │       │   │   └── index.tsx
│   │       │   ├── Renderer/
│   │       │   │   ├── CustomPlotlyChart.tsx
│   │       │   │   ├── PlotlyChart.tsx
│   │       │   │   ├── index.tsx
│   │       │   │   ├── initChart.ts
│   │       │   │   └── renderer.less
│   │       │   ├── fixtures/
│   │       │   │   └── getChartData/
│   │       │   │       ├── multiple-series-grouped.json
│   │       │   │       ├── multiple-series-multiple-y.json
│   │       │   │       ├── multiple-series-sorted.json
│   │       │   │       └── single-series.json
│   │       │   ├── getChartData.test.ts
│   │       │   ├── getChartData.ts
│   │       │   ├── getOptions.ts
│   │       │   ├── index.ts
│   │       │   └── plotly/
│   │       │       ├── customChartUtils.ts
│   │       │       ├── fixtures/
│   │       │       │   ├── prepareData/
│   │       │       │   │   ├── bar/
│   │       │       │   │   │   ├── default.json
│   │       │       │   │   │   ├── normalized.json
│   │       │       │   │   │   └── stacked.json
│   │       │       │   │   ├── box/
│   │       │       │   │   │   ├── default.json
│   │       │       │   │   │   └── with-points.json
│   │       │       │   │   ├── bubble/
│   │       │       │   │   │   └── default.json
│   │       │       │   │   ├── heatmap/
│   │       │       │   │   │   ├── default.json
│   │       │       │   │   │   ├── reversed.json
│   │       │       │   │   │   ├── sorted-reversed.json
│   │       │       │   │   │   ├── sorted.json
│   │       │       │   │   │   └── with-labels.json
│   │       │       │   │   ├── line-area/
│   │       │       │   │   │   ├── default.json
│   │       │       │   │   │   ├── keep-missing-values.json
│   │       │       │   │   │   ├── missing-values-0.json
│   │       │       │   │   │   ├── normalized-stacked.json
│   │       │       │   │   │   ├── normalized.json
│   │       │       │   │   │   └── stacked.json
│   │       │       │   │   ├── pie/
│   │       │       │   │   │   ├── custom-tooltip.json
│   │       │       │   │   │   ├── default.json
│   │       │       │   │   │   ├── without-labels.json
│   │       │       │   │   │   └── without-x.json
│   │       │       │   │   └── scatter/
│   │       │       │   │       ├── default.json
│   │       │       │   │       └── without-labels.json
│   │       │       │   └── prepareLayout/
│   │       │       │       ├── box-single-axis.json
│   │       │       │       ├── box-with-second-axis.json
│   │       │       │       ├── default-single-axis.json
│   │       │       │       ├── default-with-second-axis.json
│   │       │       │       ├── default-with-stacking.json
│   │       │       │       ├── default-without-legend.json
│   │       │       │       ├── pie-multiple-series.json
│   │       │       │       ├── pie-without-annotations.json
│   │       │       │       └── pie.json
│   │       │       ├── index.ts
│   │       │       ├── locales.ts
│   │       │       ├── prepareData.test.ts
│   │       │       ├── prepareData.ts
│   │       │       ├── prepareDefaultData.ts
│   │       │       ├── prepareHeatmapData.ts
│   │       │       ├── prepareLayout.test.ts
│   │       │       ├── prepareLayout.ts
│   │       │       ├── preparePieData.ts
│   │       │       ├── updateAxes.ts
│   │       │       ├── updateChartSize.ts
│   │       │       ├── updateData.ts
│   │       │       └── utils.ts
│   │       ├── choropleth/
│   │       │   ├── ColorPalette.ts
│   │       │   ├── Editor/
│   │       │   │   ├── BoundsSettings.tsx
│   │       │   │   ├── ColorsSettings.tsx
│   │       │   │   ├── FormatSettings.tsx
│   │       │   │   ├── GeneralSettings.tsx
│   │       │   │   ├── index.ts
│   │       │   │   └── utils.ts
│   │       │   ├── Renderer/
│   │       │   │   ├── Legend.tsx
│   │       │   │   ├── index.tsx
│   │       │   │   ├── initChoropleth.tsx
│   │       │   │   ├── renderer.less
│   │       │   │   └── utils.ts
│   │       │   ├── getOptions.ts
│   │       │   ├── hooks/
│   │       │   │   └── useLoadGeoJson.ts
│   │       │   ├── index.ts
│   │       │   └── maps/
│   │       │       ├── convert-projection.ts
│   │       │       ├── countries.geo.json
│   │       │       ├── japan.prefectures.geo.json
│   │       │       ├── usa-albers.geo.json
│   │       │       └── usa.geo.json
│   │       ├── cohort/
│   │       │   ├── Cornelius.tsx
│   │       │   ├── Editor/
│   │       │   │   ├── AppearanceSettings.tsx
│   │       │   │   ├── ColorsSettings.tsx
│   │       │   │   ├── ColumnsSettings.tsx
│   │       │   │   ├── OptionsSettings.tsx
│   │       │   │   └── index.ts
│   │       │   ├── Renderer.tsx
│   │       │   ├── cornelius.less
│   │       │   ├── getOptions.ts
│   │       │   ├── index.ts
│   │       │   ├── prepareData.ts
│   │       │   └── renderer.less
│   │       ├── counter/
│   │       │   ├── Editor/
│   │       │   │   ├── FormatSettings.tsx
│   │       │   │   ├── GeneralSettings.tsx
│   │       │   │   └── index.ts
│   │       │   ├── Renderer.tsx
│   │       │   ├── index.ts
│   │       │   ├── render.less
│   │       │   ├── utils.test.ts
│   │       │   └── utils.ts
│   │       ├── details/
│   │       │   ├── Editor/
│   │       │   │   ├── ColumnEditor.tsx
│   │       │   │   ├── ColumnsSettings.test.tsx
│   │       │   │   ├── ColumnsSettings.tsx
│   │       │   │   ├── __snapshots__/
│   │       │   │   │   └── ColumnsSettings.test.tsx.snap
│   │       │   │   ├── editor.less
│   │       │   │   └── index.tsx
│   │       │   ├── Renderer.test.tsx
│   │       │   ├── Renderer.tsx
│   │       │   ├── details.less
│   │       │   ├── getOptions.test.ts
│   │       │   ├── getOptions.ts
│   │       │   └── index.ts
│   │       ├── funnel/
│   │       │   ├── Editor/
│   │       │   │   ├── AppearanceSettings.tsx
│   │       │   │   ├── GeneralSettings.tsx
│   │       │   │   └── index.ts
│   │       │   ├── Renderer/
│   │       │   │   ├── FunnelBar.tsx
│   │       │   │   ├── funnel-bar.less
│   │       │   │   ├── index.less
│   │       │   │   ├── index.tsx
│   │       │   │   └── prepareData.ts
│   │       │   ├── getOptions.ts
│   │       │   └── index.ts
│   │       ├── index.ts
│   │       ├── map/
│   │       │   ├── Editor/
│   │       │   │   ├── FormatSettings.tsx
│   │       │   │   ├── GeneralSettings.tsx
│   │       │   │   ├── GroupsSettings.tsx
│   │       │   │   ├── StyleSettings.tsx
│   │       │   │   └── index.ts
│   │       │   ├── Renderer.tsx
│   │       │   ├── getOptions.ts
│   │       │   ├── index.ts
│   │       │   ├── initMap.ts
│   │       │   └── prepareData.ts
│   │       ├── pivot/
│   │       │   ├── Editor.tsx
│   │       │   ├── Renderer.tsx
│   │       │   ├── index.ts
│   │       │   └── renderer.less
│   │       ├── prop-types.ts
│   │       ├── registeredVisualizations.ts
│   │       ├── sankey/
│   │       │   ├── Editor.tsx
│   │       │   ├── Renderer.tsx
│   │       │   ├── d3sankey.ts
│   │       │   ├── index.ts
│   │       │   ├── initSankey.ts
│   │       │   └── renderer.less
│   │       ├── shared/
│   │       │   ├── columnUtils.ts
│   │       │   ├── columns/
│   │       │   │   ├── __snapshots__/
│   │       │   │   │   ├── boolean.test.tsx.snap
│   │       │   │   │   ├── datetime.test.tsx.snap
│   │       │   │   │   ├── image.test.tsx.snap
│   │       │   │   │   ├── link.test.tsx.snap
│   │       │   │   │   ├── number.test.tsx.snap
│   │       │   │   │   └── text.test.tsx.snap
│   │       │   │   ├── boolean.test.tsx
│   │       │   │   ├── boolean.tsx
│   │       │   │   ├── datetime.test.tsx
│   │       │   │   ├── datetime.tsx
│   │       │   │   ├── image.test.tsx
│   │       │   │   ├── image.tsx
│   │       │   │   ├── index.ts
│   │       │   │   ├── json.tsx
│   │       │   │   ├── link.test.tsx
│   │       │   │   ├── link.tsx
│   │       │   │   ├── number.test.tsx
│   │       │   │   ├── number.tsx
│   │       │   │   ├── text.test.tsx
│   │       │   │   └── text.tsx
│   │       │   └── components/
│   │       │       ├── ColumnEditor.test.tsx
│   │       │       ├── ColumnEditor.tsx
│   │       │       └── ColumnsSettings.tsx
│   │       ├── sunburst/
│   │       │   ├── Editor.tsx
│   │       │   ├── Renderer.tsx
│   │       │   ├── index.ts
│   │       │   ├── initSunburst.ts
│   │       │   └── renderer.less
│   │       ├── table/
│   │       │   ├── Editor/
│   │       │   │   ├── ColumnEditor.tsx
│   │       │   │   ├── ColumnsSettings.test.tsx
│   │       │   │   ├── ColumnsSettings.tsx
│   │       │   │   ├── GridSettings.test.tsx
│   │       │   │   ├── GridSettings.tsx
│   │       │   │   ├── __snapshots__/
│   │       │   │   │   ├── ColumnsSettings.test.tsx.snap
│   │       │   │   │   └── GridSettings.test.tsx.snap
│   │       │   │   ├── editor.less
│   │       │   │   └── index.tsx
│   │       │   ├── Renderer.tsx
│   │       │   ├── getOptions.ts
│   │       │   ├── index.ts
│   │       │   ├── renderer.less
│   │       │   └── utils.tsx
│   │       ├── variables.less
│   │       ├── visualizationsSettings.tsx
│   │       └── word-cloud/
│   │           ├── Editor.tsx
│   │           ├── Renderer.tsx
│   │           ├── index.ts
│   │           └── renderer.less
│   ├── tsconfig.json
│   └── webpack.config.js
├── webpack.config.js
└── worker.conf
Download .txt
Showing preview only (390K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (4438 symbols across 734 files)

FILE: bin/get_changes.py
  function get_change_log (line 8) | def get_change_log(previous_sha):

FILE: bin/release_manager.py
  function _github_request (line 16) | def _github_request(method, path, params=None, headers={}):
  function exception_from_error (line 29) | def exception_from_error(message, response):
  function rc_tag_name (line 33) | def rc_tag_name(version):
  function get_rc_release (line 37) | def get_rc_release(version):
  function create_release (line 49) | def create_release(version, commit_sha):
  function upload_asset (line 67) | def upload_asset(release, filepath):
  function remove_previous_builds (line 83) | def remove_previous_builds(release):
  function get_changelog (line 90) | def get_changelog(commit_sha):
  function update_release_commit_sha (line 130) | def update_release_commit_sha(release, commit_sha):
  function update_release (line 143) | def update_release(version, build_filepath, commit_sha):

FILE: client/app/components/AceEditorInput.jsx
  function AceEditorInput (line 6) | function AceEditorInput(props, ref) {

FILE: client/app/components/ApplicationArea/ApplicationLayout/DesktopNavbar.jsx
  function NavbarSection (line 23) | function NavbarSection({ children, ...props }) {
  function useNavbarActiveState (line 31) | function useNavbarActiveState() {
  function DesktopNavbar (line 65) | function DesktopNavbar() {

FILE: client/app/components/ApplicationArea/ApplicationLayout/MobileNavbar.jsx
  function MobileNavbar (line 15) | function MobileNavbar({ getPopupContainer }) {

FILE: client/app/components/ApplicationArea/ApplicationLayout/VersionInfo.jsx
  function VersionInfo (line 6) | function VersionInfo() {

FILE: client/app/components/ApplicationArea/ApplicationLayout/index.jsx
  function ApplicationLayout (line 9) | function ApplicationLayout({ children }) {

FILE: client/app/components/ApplicationArea/ErrorMessage.jsx
  function getErrorMessageByStatus (line 9) | function getErrorMessageByStatus(status, defaultMessage) {
  function getErrorMessage (line 21) | function getErrorMessage(error) {
  function ErrorMessage (line 36) | function ErrorMessage({ error, message }) {

FILE: client/app/components/ApplicationArea/ErrorMessage.test.js
  function mockAxiosError (line 11) | function mockAxiosError(status = 500, response = {}) {
  function expectErrorMessageToBe (line 25) | function expectErrorMessageToBe(error, errorMessage) {

FILE: client/app/components/ApplicationArea/ErrorMessageDetails.jsx
  function ErrorMessageDetails (line 4) | function ErrorMessageDetails(props) {

FILE: client/app/components/ApplicationArea/Router.jsx
  function generateRouteKey (line 11) | function generateRouteKey() {
  function useCurrentRoute (line 19) | function useCurrentRoute() {
  function stripBase (line 23) | function stripBase(href) {
  function Router (line 39) | function Router({ routes, onRouteChange }) {

FILE: client/app/components/ApplicationArea/handleNavigationIntent.js
  function handleNavigationIntent (line 4) | function handleNavigationIntent(event) {

FILE: client/app/components/ApplicationArea/index.jsx
  function ApplicationArea (line 7) | function ApplicationArea() {

FILE: client/app/components/ApplicationArea/navigateTo.js
  function navigateTo (line 7) | function navigateTo(href, replace = false) {

FILE: client/app/components/ApplicationArea/routeWithApiKeySession.jsx
  function ApiKeySessionWrapper (line 13) | function ApiKeySessionWrapper({ apiKey, currentRoute, renderChildren }) {
  function routeWithApiKeySession (line 56) | function routeWithApiKeySession({ render, getApiKey, ...rest }) {

FILE: client/app/components/ApplicationArea/routeWithUserSession.tsx
  type UserSessionWrapperRenderChildrenProps (line 11) | type UserSessionWrapperRenderChildrenProps<P> = {
  type UserSessionWrapperProps (line 16) | interface UserSessionWrapperProps<P> {
  function UserSessionWrapper (line 28) | function UserSessionWrapper<P>({ bodyClass, currentRoute, render }: User...
  type RouteWithUserSessionOptions (line 79) | type RouteWithUserSessionOptions<P> = {
  function routeWithUserSession (line 88) | function routeWithUserSession<P extends {} = {}>({

FILE: client/app/components/BeaconConsent.jsx
  function BeaconConsent (line 13) | function BeaconConsent() {

FILE: client/app/components/BigMessage.jsx
  function BigMessage (line 6) | function BigMessage({ message, icon, children, className }) {

FILE: client/app/components/CodeBlock.jsx
  class CodeBlock (line 8) | class CodeBlock extends React.Component {
    method constructor (line 21) | constructor(props) {
    method componentWillUnmount (line 28) | componentWillUnmount() {
    method render (line 58) | render() {

FILE: client/app/components/Collapse.jsx
  function Collapse (line 6) | function Collapse({ collapsed, children, className, ...props }) {

FILE: client/app/components/CreateSourceDialog.jsx
  class CreateSourceDialog (line 26) | class CreateSourceDialog extends React.Component {
    method renderTypeSelector (line 77) | renderTypeSelector() {
    method renderForm (line 103) | renderForm() {
    method renderItem (line 136) | renderItem(item) {
    method render (line 152) | render() {

FILE: client/app/components/DialogWrapper.d.ts
  type DialogProps (line 3) | interface DialogProps<ROk, RCancel> {
  type DialogWrapperChildProps (line 9) | type DialogWrapperChildProps<ROk, RCancel> = {
  type DialogComponentType (line 13) | type DialogComponentType<ROk = void, P = {}, RCancel = void> = React.Com...

FILE: client/app/components/DialogWrapper.jsx
  function openDialog (line 110) | function openDialog(DialogComponent, props) {
  function wrap (line 217) | function wrap(DialogComponent) {

FILE: client/app/components/DynamicComponent.jsx
  function registerComponent (line 8) | function registerComponent(name, component) {
  function unregisterComponent (line 20) | function unregisterComponent(name) {
  class DynamicComponent (line 24) | class DynamicComponent extends React.Component {
    method componentDidMount (line 35) | componentDidMount() {
    method componentWillUnmount (line 39) | componentWillUnmount() {
    method render (line 43) | render() {

FILE: client/app/components/EditInPlace.jsx
  class EditInPlace (line 7) | class EditInPlace extends React.Component {
    method constructor (line 31) | constructor(props) {
    method componentDidUpdate (line 38) | componentDidUpdate(_, prevState) {
    method render (line 98) | render() {

FILE: client/app/components/EditParameterSettingsDialog.jsx
  function getDefaultTitle (line 20) | function getDefaultTitle(text) {
  function isTypeDateRange (line 24) | function isTypeDateRange(type) {
  function joinExampleList (line 28) | function joinExampleList(multiValuesOptions) {
  function NameInput (line 33) | function NameInput({ name, type, onChange, existingNames, setValidation ...
  function EditParameterSettingsDialog (line 71) | function EditParameterSettingsDialog(props) {

FILE: client/app/components/EditVisualizationButton/QueryControlDropdown.jsx
  function QueryControlDropdown (line 17) | function QueryControlDropdown(props) {

FILE: client/app/components/EditVisualizationButton/QueryResultsLink.jsx
  function QueryResultsLink (line 5) | function QueryResultsLink(props) {

FILE: client/app/components/EditVisualizationButton/index.jsx
  function EditVisualizationButton (line 6) | function EditVisualizationButton(props) {

FILE: client/app/components/EmailSettingsWarning.jsx
  function EmailSettingsWarning (line 9) | function EmailSettingsWarning({ featureName, className, mode, adminOnly ...

FILE: client/app/components/FavoritesControl.jsx
  class FavoritesControl (line 5) | class FavoritesControl extends React.Component {
    method toggleItem (line 17) | toggleItem(event, item, callback) {
    method render (line 28) | render() {

FILE: client/app/components/Filters.jsx
  constant ALL_VALUES (line 8) | const ALL_VALUES = "###Redash::Filters::SelectAll###";
  constant NONE_VALUES (line 9) | const NONE_VALUES = "###Redash::Filters::Clear###";
  function createFilterChangeHandler (line 21) | function createFilterChangeHandler(filters, onChange) {
  function filterData (line 41) | function filterData(rows, filters = []) {
  function Filters (line 69) | function Filters({ filters, onChange }) {

FILE: client/app/components/HelpTrigger.jsx
  constant DOMAIN (line 15) | const DOMAIN = "https://redash.io";
  constant HELP_PATH (line 16) | const HELP_PATH = "/help";
  constant IFRAME_TIMEOUT (line 17) | const IFRAME_TIMEOUT = 20000;
  constant IFRAME_URL_UPDATE_MESSAGE (line 18) | const IFRAME_URL_UPDATE_MESSAGE = "iframe_url";
  constant TYPES (line 20) | const TYPES = mapValues(
  function helpTriggerWithTypes (line 75) | function helpTriggerWithTypes(types, allowedDomains = [], drawerClassNam...
  function HelpTrigger (line 263) | function HelpTrigger(props) {

FILE: client/app/components/InputWithCopy.jsx
  class InputWithCopy (line 7) | class InputWithCopy extends React.Component {
    method constructor (line 8) | constructor(props) {
    method componentWillUnmount (line 16) | componentWillUnmount() {
    method render (line 43) | render() {

FILE: client/app/components/Link.tsx
  function DefaultLinkComponent (line 4) | function DefaultLinkComponent({ children, ...props }: React.AnchorHTMLAt...
  type LinkProps (line 10) | interface LinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorEl...
  function Link (line 13) | function Link({ children, ...props }: LinkProps) {
  type LinkWithIconProps (line 17) | interface LinkWithIconProps extends LinkProps {
  function LinkWithIcon (line 24) | function LinkWithIcon({ icon, alt, children, ...props }: LinkWithIconPro...
  function ExternalLink (line 34) | function ExternalLink({
  function DefaultButtonLinkComponent (line 45) | function DefaultButtonLinkComponent(props: ButtonProps) {
  type ButtonProps (line 51) | interface ButtonProps extends AntdButtonProps {
  function ButtonLink (line 55) | function ButtonLink(props: ButtonProps) {

FILE: client/app/components/NoTaggedObjectsFound.jsx
  function NoTaggedObjectsFound (line 6) | function NoTaggedObjectsFound({ objectType, tags }) {

FILE: client/app/components/PageHeader/index.jsx
  function PageHeader (line 6) | function PageHeader({ title, actions }) {

FILE: client/app/components/Paginator.jsx
  constant MIN_ITEMS_PER_PAGE (line 5) | const MIN_ITEMS_PER_PAGE = 5;
  function Paginator (line 7) | function Paginator({ page, showPageSizeSelect, pageSize, onPageSizeChang...

FILE: client/app/components/ParameterApplyButton.jsx
  function ParameterApplyButton (line 8) | function ParameterApplyButton({ paramCount, onClick }) {

FILE: client/app/components/ParameterMappingInput.jsx
  function parameterMappingsToEditableMappings (line 35) | function parameterMappingsToEditableMappings(mappings, parameters, exist...
  function editableMappingsToParameterMappings (line 60) | function editableMappingsToParameterMappings(mappings) {
  function synchronizeWidgetTitles (line 95) | function synchronizeWidgetTitles(sourceMappings, widgets) {
  class ParameterMappingInput (line 122) | class ParameterMappingInput extends React.Component {
    method renderMappingTypeSelector (line 175) | renderMappingTypeSelector() {
    method renderDashboardAddNew (line 200) | renderDashboardAddNew() {
    method renderDashboardMapToExisting (line 213) | renderDashboardMapToExisting() {
    method renderStaticValue (line 220) | renderStaticValue() {
    method renderInputBlock (line 235) | renderInputBlock() {
    method render (line 249) | render() {
  class MappingEditor (line 272) | class MappingEditor extends React.Component {
    method constructor (line 279) | constructor(props) {
    method renderContent (line 323) | renderContent() {
    method render (line 347) | render() {
  class TitleEditor (line 365) | class TitleEditor extends React.Component {
    method getMappingTitle (line 392) | getMappingTitle() {
    method renderPopover (line 420) | renderPopover() {
    method renderEditButton (line 447) | renderEditButton() {
    method render (line 474) | render() {
  class ParameterMappingListInput (line 488) | class ParameterMappingListInput extends React.Component {
    method getStringValue (line 501) | static getStringValue(value) {
    method getDefaultValue (line 521) | static getDefaultValue(mapping, existingParams) {
    method getSourceTypeLabel (line 548) | static getSourceTypeLabel({ type, mapTo }) {
    method updateParamMapping (line 566) | updateParamMapping(oldMapping, newMapping) {
    method render (line 578) | render() {

FILE: client/app/components/ParameterValueInput.jsx
  class ParameterValueInput (line 20) | class ParameterValueInput extends React.Component {
    method constructor (line 43) | constructor(props) {
    method renderDateParameter (line 68) | renderDateParameter() {
    method renderDateRangeParameter (line 82) | renderDateRangeParameter() {
    method renderEnumInput (line 96) | renderEnumInput() {
    method renderQueryBasedInput (line 118) | renderQueryBasedInput() {
    method renderNumberInput (line 135) | renderNumberInput() {
    method renderTextPatternInput (line 151) | renderTextPatternInput() {
    method renderTextInput (line 169) | renderTextInput() {
    method renderInput (line 184) | renderInput() {
    method render (line 208) | render() {

FILE: client/app/components/Parameters.jsx
  function updateUrl (line 15) | function updateUrl(parameters) {
  class Parameters (line 23) | class Parameters extends React.Component {
    method constructor (line 53) | constructor(props) {
    method renderParameter (line 134) | renderParameter(param, index) {
    method render (line 172) | render() {

FILE: client/app/components/PermissionsEditorDialog/index.jsx
  constant DEBOUNCE_SEARCH_DURATION (line 22) | const DEBOUNCE_SEARCH_DURATION = 200;
  function useGrantees (line 24) | function useGrantees(url) {
  function PermissionsEditorDialogHeader (line 64) | function PermissionsEditorDialogHeader({ context }) {
  function UserSelect (line 79) | function UserSelect({ onSelect, shouldShowUser }) {
  function PermissionsEditorDialog (line 138) | function PermissionsEditorDialog({ dialog, author, context, aclUrl }) {

FILE: client/app/components/PlainButton.tsx
  type PlainButtonProps (line 6) | interface PlainButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLB...
  function PlainButton (line 10) | function PlainButton({ className, type, ...rest }: PlainButtonProps) {

FILE: client/app/components/PreviewCard.jsx
  function PreviewCard (line 8) | function PreviewCard({ imageUrl, roundedImage, title, body, children, cl...
  function UserPreviewCard (line 45) | function UserPreviewCard({ user, withLink, children, ...props }) {
  function DataSourcePreviewCard (line 71) | function DataSourcePreviewCard({ dataSource, withLink, children, ...prop...

FILE: client/app/components/QueryBasedParameterInput.jsx
  class QueryBasedParameterInput (line 6) | class QueryBasedParameterInput extends React.Component {
    method constructor (line 25) | constructor(props) {
    method componentDidMount (line 34) | componentDidMount() {
    method componentDidUpdate (line 38) | componentDidUpdate(prevProps) {
    method setValue (line 47) | setValue(value) {
    method _loadOptions (line 62) | async _loadOptions(queryId) {
    method render (line 79) | render() {

FILE: client/app/components/QueryLink.jsx
  function QueryLink (line 9) | function QueryLink({ query, visualization, readOnly }) {

FILE: client/app/components/QuerySelector.jsx
  function search (line 14) | function search(term) {
  function QuerySelector (line 28) | function QuerySelector(props) {

FILE: client/app/components/Resizable/index.jsx
  function Resizable (line 9) | function Resizable({ toggleShortcut, direction, sizeAttribute, children ...

FILE: client/app/components/SelectItemsDialog.jsx
  function ItemsList (line 17) | function ItemsList({ items, renderItem, onItemClick }) {
  function SelectItemsDialog (line 48) | function SelectItemsDialog({

FILE: client/app/components/SelectWithVirtualScroll.tsx
  constant MIN_LEN_FOR_VIRTUAL_SCROLL (line 6) | const MIN_LEN_FOR_VIRTUAL_SCROLL = 400;
  type VirtualScrollLabeledValue (line 8) | interface VirtualScrollLabeledValue extends LabeledValue {
  type VirtualScrollSelectProps (line 12) | interface VirtualScrollSelectProps extends Omit<SelectProps<string>, "op...
  function SelectWithVirtualScroll (line 15) | function SelectWithVirtualScroll({ options, ...props }: VirtualScrollSel...

FILE: client/app/components/SettingsWrapper.jsx
  function wrapSettingsTab (line 8) | function wrapSettingsTab(id, options, WrappedComponent) {

FILE: client/app/components/TagsList.tsx
  type Tag (line 11) | type Tag = {
  type TagsListProps (line 16) | type TagsListProps = {
  function TagsList (line 22) | function TagsList({ tagsUrl, showUnselectAll = false, onUpdate }: TagsLi...

FILE: client/app/components/TimeAgo.jsx
  function toMoment (line 9) | function toMoment(value) {
  function TimeAgo (line 14) | function TimeAgo({ date, placeholder, autoUpdate, variation }) {

FILE: client/app/components/Timer.jsx
  function Timer (line 6) | function Timer({ from }) {

FILE: client/app/components/Tooltip.tsx
  function Tooltip (line 5) | function Tooltip({ title, ...restProps }: TooltipProps) {

FILE: client/app/components/UserGroups.jsx
  function UserGroups (line 9) | function UserGroups({ groups, linkGroups, ...props }) {

FILE: client/app/components/admin/Layout.jsx
  function Layout (line 9) | function Layout({ activeTab, children }) {

FILE: client/app/components/admin/RQStatus.jsx
  function CounterCard (line 13) | function CounterCard({ title, value, loading }) {
  function WorkersTable (line 83) | function WorkersTable({ loading, items }) {
  function QueuesTable (line 101) | function QueuesTable({ loading, items }) {
  function QueryJobsTable (line 119) | function QueryJobsTable({ loading, items }) {
  function OtherJobsTable (line 137) | function OtherJobsTable({ loading, items }) {

FILE: client/app/components/admin/StatusBlock.jsx
  function General (line 12) | function General({ info }) {
  function DatabaseMetrics (line 31) | function DatabaseMetrics({ info }) {
  function Queues (line 49) | function Queues({ info }) {
  function Manager (line 68) | function Manager({ info }) {

FILE: client/app/components/cards-list/CardsList.tsx
  type CardsListItem (line 11) | interface CardsListItem {
  type CardsListProps (line 18) | interface CardsListProps {
  type ListItemProps (line 23) | interface ListItemProps {
  function ListItem (line 28) | function ListItem({ item, keySuffix }: ListItemProps) {
  function CardsList (line 44) | function CardsList({ items = [], showSearch = false }: CardsListProps) {

FILE: client/app/components/dashboards/AddWidgetDialog.jsx
  function VisualizationSelect (line 13) | function VisualizationSelect({ query, visualization, onChange }) {
  function AddWidgetDialog (line 68) | function AddWidgetDialog({ dialog, dashboard }) {

FILE: client/app/components/dashboards/AutoHeightController.js
  constant WIDGET_SELECTOR (line 5) | const WIDGET_SELECTOR = '[data-widgetid="{0}"]';
  constant WIDGET_CONTENT_SELECTOR (line 6) | const WIDGET_CONTENT_SELECTOR = [
  constant INTERVAL (line 13) | const INTERVAL = 200;
  class AutoHeightController (line 15) | class AutoHeightController {
    method constructor (line 22) | constructor(handler) {
    method update (line 26) | update(widgets) {

FILE: client/app/components/dashboards/CreateDashboardDialog.jsx
  function CreateDashboardDialog (line 12) | function CreateDashboardDialog({ dialog }) {

FILE: client/app/components/dashboards/DashboardGrid.jsx
  constant SINGLE (line 33) | const SINGLE = "single-column";
  constant MULTI (line 34) | const MULTI = "multi-column";
  class DashboardGrid (line 86) | class DashboardGrid extends React.Component {
    method normalizeFrom (line 112) | static normalizeFrom(widget) {
    method constructor (line 135) | constructor(props) {
    method componentDidMount (line 148) | componentDidMount() {
    method componentDidUpdate (line 157) | componentDidUpdate() {
    method componentWillUnmount (line 162) | componentWillUnmount() {
    method render (line 228) | render() {

FILE: client/app/components/dashboards/EditParameterMappingsDialog.jsx
  function getParamValuesSnapshot (line 15) | function getParamValuesSnapshot(mappings, dashboardParameters) {
  class EditParameterMappingsDialog (line 35) | class EditParameterMappingsDialog extends React.Component {
    method constructor (line 44) | constructor(props) {
    method saveWidget (line 64) | saveWidget() {
    method updateParamMappings (line 94) | updateParamMappings(parameterMappings) {
    method render (line 98) | render() {

FILE: client/app/components/dashboards/ExpandedWidgetDialog.jsx
  function ExpandedWidgetDialog (line 10) | function ExpandedWidgetDialog({ dialog, widget, filters }) {

FILE: client/app/components/dashboards/TextboxDialog.jsx
  function TextboxDialog (line 17) | function TextboxDialog({ dialog, isNew, ...props }) {

FILE: client/app/components/dashboards/dashboard-widget/RestrictedWidget.jsx
  function RestrictedWidget (line 4) | function RestrictedWidget(props) {

FILE: client/app/components/dashboards/dashboard-widget/TextboxWidget.jsx
  function TextboxWidget (line 9) | function TextboxWidget(props) {

FILE: client/app/components/dashboards/dashboard-widget/VisualizationWidget.jsx
  function visualizationWidgetMenuOptions (line 25) | function visualizationWidgetMenuOptions({ widget, canEditDashboard, onPa...
  function RefreshIndicator (line 75) | function RefreshIndicator({ refreshStartedAt }) {
  function VisualizationWidgetHeader (line 90) | function VisualizationWidgetHeader({
  function VisualizationWidgetFooter (line 147) | function VisualizationWidgetFooter({ widget, isPublic, onRefresh, onExpa...
  class VisualizationWidget (line 211) | class VisualizationWidget extends React.Component {
    method constructor (line 238) | constructor(props) {
    method componentDidMount (line 246) | componentDidMount() {
    method renderVisualization (line 276) | renderVisualization() {
    method render (line 319) | render() {

FILE: client/app/components/dashboards/dashboard-widget/Widget.jsx
  function WidgetDropdownButton (line 14) | function WidgetDropdownButton({ extraOptions, showDeleteOption, onDelete...
  function WidgetDeleteButton (line 46) | function WidgetDeleteButton({ onClick }) {
  class Widget (line 64) | class Widget extends React.Component {
    method componentDidMount (line 92) | componentDidMount() {
    method render (line 111) | render() {

FILE: client/app/components/dynamic-form/DynamicForm.jsx
  function normalizeEmptyValuesToNull (line 39) | function normalizeEmptyValuesToNull(fields, values) {
  function DynamicFormFields (line 49) | function DynamicFormFields({ fields, feedbackIcons, form }) {
  function DynamicFormActions (line 107) | function DynamicFormActions({ actions, isFormDirty }) {
  function DynamicForm (line 143) | function DynamicForm({

FILE: client/app/components/dynamic-form/DynamicFormField.jsx
  function DynamicFormField (line 62) | function DynamicFormField({ form, field, ...otherProps }) {

FILE: client/app/components/dynamic-form/dynamicFormHelper.js
  function orderedInputs (line 4) | function orderedInputs(properties, order, targetOptions) {
  function normalizeSchema (line 32) | function normalizeSchema(configurationSchema) {
  function setDefaultValueToFields (line 67) | function setDefaultValueToFields(configurationSchema, options = {}) {
  function getFields (line 83) | function getFields(type = {}, target = { options: {} }) {
  function updateTargetWithValues (line 109) | function updateTargetWithValues(target, values) {
  function getBase64 (line 118) | function getBase64(file) {
  function hasFilledExtraField (line 127) | function hasFilledExtraField(type, target) {

FILE: client/app/components/dynamic-form/fields/AceEditorField.jsx
  function AceEditorField (line 4) | function AceEditorField({ form, field, ...otherProps }) {

FILE: client/app/components/dynamic-form/fields/CheckboxField.jsx
  function CheckboxField (line 5) | function CheckboxField({ form, field, ...otherProps }) {

FILE: client/app/components/dynamic-form/fields/ContentField.jsx
  function ContentField (line 1) | function ContentField({ field }) {

FILE: client/app/components/dynamic-form/fields/FileField.jsx
  function FileField (line 6) | function FileField({ form, field, ...otherProps }) {

FILE: client/app/components/dynamic-form/fields/InputField.jsx
  function InputField (line 4) | function InputField({ form, field, ...otherProps }) {

FILE: client/app/components/dynamic-form/fields/NumberField.jsx
  function NumberField (line 4) | function NumberField({ form, field, ...otherProps }) {

FILE: client/app/components/dynamic-form/fields/SelectField.jsx
  function SelectField (line 4) | function SelectField({ form, field, ...otherProps }) {

FILE: client/app/components/dynamic-form/fields/TextAreaField.jsx
  function TextAreaField (line 4) | function TextAreaField({ form, field, ...otherProps }) {

FILE: client/app/components/dynamic-form/getFieldLabel.js
  function getFieldLabel (line 3) | function getFieldLabel(field) {

FILE: client/app/components/dynamic-parameters/DateParameter.jsx
  constant DYNAMIC_DATE_OPTIONS (line 6) | const DYNAMIC_DATE_OPTIONS = [
  function DateParameter (line 25) | function DateParameter(props) {

FILE: client/app/components/dynamic-parameters/DateRangeParameter.jsx
  constant DYNAMIC_DATE_OPTIONS (line 7) | const DYNAMIC_DATE_OPTIONS = [
  constant DYNAMIC_DATETIME_OPTIONS (line 91) | const DYNAMIC_DATETIME_OPTIONS = [
  function DateRangeParameter (line 105) | function DateRangeParameter(props) {

FILE: client/app/components/dynamic-parameters/DynamicButton.jsx
  function DynamicButton (line 18) | function DynamicButton({ options, selectedDynamicValue, onSelect, enable...

FILE: client/app/components/dynamic-parameters/DynamicDatePicker.jsx
  class DynamicDatePicker (line 13) | class DynamicDatePicker extends React.Component {
    method constructor (line 44) | constructor(props) {
    method render (line 65) | render() {

FILE: client/app/components/dynamic-parameters/DynamicDateRangePicker.jsx
  function isValidDateRangeValue (line 13) | function isValidDateRangeValue(value) {
  class DynamicDateRangePicker (line 17) | class DynamicDateRangePicker extends React.Component {
    method constructor (line 48) | constructor(props) {
    method render (line 69) | render() {

FILE: client/app/components/empty-state/EmptyState.d.ts
  type DefaultStepKey (line 3) | type DefaultStepKey = "dataSources" | "queries" | "alerts" | "dashboards...
  type StepKey (line 4) | type StepKey<K> = DefaultStepKey | K;
  type StepItem (line 6) | interface StepItem<K> {
  type EmptyStateHelpMessageProps (line 11) | interface EmptyStateHelpMessageProps {
  type EmptyStateProps (line 17) | interface EmptyStateProps<K = unknown> {
  class EmptyState (line 36) | class EmptyState<R> extends React.Component<EmptyStateProps<R>> {}
  type StepProps (line 40) | interface StepProps {

FILE: client/app/components/empty-state/EmptyState.jsx
  function Step (line 15) | function Step({ show, completed, text, url, urlText, onClick }) {
  function EmptyStateHelpMessage (line 47) | function EmptyStateHelpMessage({ helpTriggerType }) {
  function EmptyState (line 62) | function EmptyState({

FILE: client/app/components/groups/CreateGroupDialog.jsx
  class CreateGroupDialog (line 6) | class CreateGroupDialog extends React.Component {
    method render (line 21) | render() {

FILE: client/app/components/groups/DeleteGroupButton.jsx
  function deleteGroup (line 10) | function deleteGroup(event, group, onGroupDeleted) {
  function DeleteGroupButton (line 26) | function DeleteGroupButton({ group, title, onClick, children, ...props }) {

FILE: client/app/components/groups/DetailsPageSidebar.jsx
  function DetailsPageSidebar (line 12) | function DetailsPageSidebar({

FILE: client/app/components/groups/GroupName.jsx
  function updateGroupName (line 7) | function updateGroupName(group, name, onChange) {
  function GroupName (line 13) | function GroupName({ group, onChange, ...props }) {

FILE: client/app/components/groups/ListItemAddon.jsx
  function ListItemAddon (line 5) | function ListItemAddon({ isSelected, isStaged, alreadyInGroup, deselecte...

FILE: client/app/components/items-list/ItemsList.tsx
  type PaginationOptions (line 8) | interface PaginationOptions {
  type SearchOptions (line 13) | interface SearchOptions {
  type Controller (line 17) | interface Controller<I, P = any> {
  type GenericItemSourceError (line 79) | type GenericItemSourceError = AxiosError | Error;
  type ItemsListWrapperProps (line 81) | interface ItemsListWrapperProps {
  type ItemsListWrapperState (line 86) | interface ItemsListWrapperState<I, P = any> extends Controller<I, P> {
  type ItemsSource (line 91) | type ItemsSource = any;
  type StateStorage (line 92) | type StateStorage = any;
  type ItemsListWrappedComponentProps (line 94) | interface ItemsListWrappedComponentProps<I, P = any> {
  function wrap (line 98) | function wrap<I, P = any>(

FILE: client/app/components/items-list/classes/ItemsFetcher.js
  class ItemsFetcher (line 3) | class ItemsFetcher {
    method _getRequest (line 4) | _getRequest(state, context) {
    method _processResults (line 8) | _processResults({ results, count }, state, context) {
    method constructor (line 15) | constructor({ getRequest, doRequest, processResults }) {
    method fetch (line 21) | fetch(changes, state, context) {
  class PlainListFetcher (line 29) | class PlainListFetcher extends ItemsFetcher {
    method _getRequest (line 32) | _getRequest({ searchTerm, selectedTags }, context) {
    method _processResults (line 42) | _processResults(data, { paginator, sorter }, context) {
    method fetch (line 52) | fetch(changes, state, context) {
  class PaginatedListFetcher (line 72) | class PaginatedListFetcher extends ItemsFetcher {
    method _getRequest (line 73) | _getRequest({ paginator, sorter, searchTerm, selectedTags }, context) {

FILE: client/app/components/items-list/classes/ItemsSource.d.ts
  type ItemsSourceOptions (line 1) | interface ItemsSourceOptions<I = any> extends Partial<ItemsSourceState> {
  type GetResourceContext (line 9) | interface GetResourceContext extends ItemsSourceState {
  type GetResourceRequest (line 16) | type GetResourceRequest = any;
  type ItemsPage (line 18) | interface ItemsPage<INPUT = any> {
  type ResourceItemsSourceOptions (line 25) | interface ResourceItemsSourceOptions<INPUT = any, ITEM = any> extends It...
  type ItemsSourceState (line 30) | type ItemsSourceState<ITEM = any> = {
  class ItemsSource (line 45) | class ItemsSource {
  class ResourceItemsSource (line 49) | class ResourceItemsSource<I> {

FILE: client/app/components/items-list/classes/ItemsSource.js
  class ItemsSource (line 6) | class ItemsSource {
    method _beforeUpdate (line 17) | _beforeUpdate() {
    method _afterUpdate (line 24) | _afterUpdate() {
    method _changed (line 32) | _changed(changes) {
    method constructor (line 64) | constructor({
    method getState (line 88) | getState() {
    method setState (line 103) | setState(state) {
  class ResourceItemsSource (line 168) | class ResourceItemsSource extends ItemsSource {
    method constructor (line 169) | constructor({ getResource, getItemProcessor, ...rest }) {

FILE: client/app/components/items-list/classes/Paginator.js
  class Paginator (line 3) | class Paginator {
    method totalPages (line 10) | get totalPages() {
    method setPage (line 14) | setPage(value, validate = true) {
    method setItemsPerPage (line 26) | setItemsPerPage(value, validate = true) {
    method setTotalCount (line 37) | setTotalCount(value, validate = true) {
    method constructor (line 48) | constructor({ page, itemsPerPage, totalCount, validate = true } = {}) {
    method getItemsForPage (line 54) | getItemsForPage(items) {

FILE: client/app/components/items-list/classes/Sorter.js
  constant ORDER_BY_REVERSE (line 3) | const ORDER_BY_REVERSE = "-";
  function compile (line 5) | function compile(field, reverse) {
  function parse (line 12) | function parse(compiled) {
  class Sorter (line 22) | class Sorter {
    method compiled (line 29) | get compiled() {
    method compiled (line 33) | set compiled(value) {
    method setField (line 39) | setField(value) {
    method setReverse (line 43) | setReverse(value) {
    method constructor (line 47) | constructor({ orderByField, orderByReverse } = {}, sortByIteratees = u...
    method toggleField (line 53) | toggleField(field) {
    method sort (line 65) | sort(items) {

FILE: client/app/components/items-list/classes/StateStorage.js
  class StateStorage (line 6) | class StateStorage {
    method constructor (line 7) | constructor(state = {}) {
    method getState (line 11) | getState() {
    method setState (line 23) | setState() {}
  class UrlStateStorage (line 26) | class UrlStateStorage extends StateStorage {
    method getState (line 27) | getState() {
    method setState (line 49) | setState({ page, itemsPerPage, orderByField, orderByReverse, searchTer...

FILE: client/app/components/items-list/components/EmptyState.jsx
  function EmptyState (line 5) | function EmptyState(props) {

FILE: client/app/components/items-list/components/ItemsTable.jsx
  function sortable (line 13) | function sortable(...args) {
  method favorites (line 18) | favorites(overrides) {
  method avatar (line 27) | avatar(overrides, formatTitle) {
  method date (line 44) | date(overrides) {
  method dateTime (line 52) | dateTime(overrides) {
  method duration (line 60) | duration(overrides) {
  method timeAgo (line 70) | timeAgo(overrides, timeAgoCustomProps = undefined) {
  method custom (line 78) | custom(render, overrides) {
  class ItemsTable (line 94) | class ItemsTable extends React.Component {
    method prepareColumns (line 130) | prepareColumns() {
    method render (line 164) | render() {

FILE: client/app/components/items-list/components/LoadingState.jsx
  function LoadingState (line 5) | function LoadingState(props) {

FILE: client/app/components/items-list/components/Sidebar.jsx
  function SearchInput (line 13) | function SearchInput({ placeholder, value, showIcon, onChange, label }) {
  function Menu (line 61) | function Menu({ items, selected }) {
  function MenuIcon (line 109) | function MenuIcon({ icon }) {
  function ProfileImage (line 125) | function ProfileImage({ user }) {
  function Tags (line 143) | function Tags({ url, onChange, showUnselectAll }) {

FILE: client/app/components/items-list/hooks/useItemsListExtraActions.js
  function useItemsListExtraActions (line 6) | function useItemsListExtraActions(controller, listColumns, ExtraActionsC...

FILE: client/app/components/layouts/ContentWithSidebar.jsx
  function Sidebar (line 19) | function Sidebar({ className, children, ...props }) {
  function Content (line 32) | function Content({ className, children, ...props }) {
  function Layout (line 45) | function Layout({ children, className = undefined, ...props }) {

FILE: client/app/components/proptypes.js
  function checkMoment (line 93) | function checkMoment(isRequired, props, propName, componentName) {

FILE: client/app/components/queries/AddToDashboardDialog.jsx
  function AddToDashboardDialog (line 18) | function AddToDashboardDialog({ dialog, visualization }) {

FILE: client/app/components/queries/ApiKeyDialog/index.jsx
  function ApiKeyDialog (line 17) | function ApiKeyDialog({ dialog, ...props }) {

FILE: client/app/components/queries/EmbedQueryDialog.jsx
  class EmbedQueryDialog (line 16) | class EmbedQueryDialog extends React.Component {
    method constructor (line 29) | constructor(props) {
    method render (line 44) | render() {

FILE: client/app/components/queries/QueryEditor/AutoLimitCheckbox.jsx
  function AutoLimitCheckbox (line 7) | function AutoLimitCheckbox({ available, checked, onChange }) {

FILE: client/app/components/queries/QueryEditor/AutocompleteToggle.jsx
  function AutocompleteToggle (line 8) | function AutocompleteToggle({ available, enabled, onToggle }) {

FILE: client/app/components/queries/QueryEditor/QueryEditorControls.jsx
  function ButtonTooltip (line 13) | function ButtonTooltip({ title, shortcut, ...props }) {
  function EditorControl (line 36) | function EditorControl({

FILE: client/app/components/queries/QueryEditor/ace.js
  function defineDummySnippets (line 18) | function defineDummySnippets(mode) {
  function buildTableColumnKeywords (line 34) | function buildTableColumnKeywords(table) {
  function buildKeywordsFromSchema (line 48) | function buildKeywordsFromSchema(schema) {
  function updateSchemaCompleter (line 81) | function updateSchemaCompleter(editorKey, schema = null) {

FILE: client/app/components/queries/QueryEditor/index.jsx
  function resize (line 59) | function resize() {

FILE: client/app/components/queries/ScheduleDialog.jsx
  constant WEEKDAYS_SHORT (line 16) | const WEEKDAYS_SHORT = moment.weekdaysShort();
  constant WEEKDAYS_FULL (line 17) | const WEEKDAYS_FULL = moment.weekdays();
  constant DATE_FORMAT (line 18) | const DATE_FORMAT = "YYYY-MM-DD";
  constant HOUR_FORMAT (line 19) | const HOUR_FORMAT = "HH:mm";
  function TimeEditor (line 22) | function TimeEditor(props) {
  class ScheduleDialog (line 52) | class ScheduleDialog extends React.Component {
    method getState (line 65) | getState() {
    method intervals (line 81) | get intervals() {
    method newSchedule (line 98) | set newSchedule(newProps) {
    method save (line 172) | save() {
    method render (line 191) | render() {

FILE: client/app/components/queries/ScheduleDialog.test.js
  function getWrapper (line 35) | function getWrapper(schedule = {}, { onConfirm, onCancel, ...props } = {...
  function findByTestID (line 61) | function findByTestID(wrapper, id) {

FILE: client/app/components/queries/SchedulePhrase.jsx
  class SchedulePhrase (line 10) | class SchedulePhrase extends React.Component {
    method content (line 24) | get content() {
    method render (line 46) | render() {

FILE: client/app/components/queries/SchemaBrowser.jsx
  function SchemaItem (line 31) | function SchemaItem({ item, expanded, onToggle, onSelect, ...props }) {
  function SchemaLoadingState (line 132) | function SchemaLoadingState() {
  function SchemaList (line 140) | function SchemaList({ loading, schema, expandedFlags, onTableExpand, onI...
  function applyFilterOnSchema (line 187) | function applyFilterOnSchema(schema, filterString) {
  function SchemaBrowser (line 223) | function SchemaBrowser({

FILE: client/app/components/queries/editor-components/databricks/DatabricksSchemaBrowser.jsx
  function DatabricksSchemaBrowser (line 16) | function DatabricksSchemaBrowser({

FILE: client/app/components/queries/editor-components/databricks/useDatabricksSchema.js
  function getDatabases (line 6) | function getDatabases(dataSource, refresh = false) {
  function getSchema (line 17) | function getSchema(dataSource, databaseName, refresh = false) {
  function addDisplayNameWithoutDatabaseName (line 28) | function addDisplayNameWithoutDatabaseName(schema, databaseName) {
  function useDatabricksSchema (line 43) | function useDatabricksSchema(dataSource, options = null, onOptionsUpdate...

FILE: client/app/components/queries/editor-components/editorComponents.js
  function registerEditorComponent (line 10) | function registerEditorComponent(componentName, component, dataSourceTyp...
  function getEditorComponents (line 24) | function getEditorComponents(dataSourceType) {

FILE: client/app/components/query-snippets/QuerySnippetDialog.jsx
  function QuerySnippetDialog (line 10) | function QuerySnippetDialog({ querySnippet, dialog, readOnly }) {

FILE: client/app/components/tags-control/EditTagsDialog.jsx
  function EditTagsDialog (line 8) | function EditTagsDialog({ dialog, tags, getAvailableTags }) {

FILE: client/app/components/tags-control/TagsControl.jsx
  class TagsControl (line 8) | class TagsControl extends React.Component {
    method renderEditButton (line 35) | renderEditButton() {
    method render (line 58) | render() {
  function modelTagsControl (line 78) | function modelTagsControl({ archivedTooltip }) {

FILE: client/app/components/visualizations/EditVisualizationDialog.jsx
  function updateQueryVisualizations (line 24) | function updateQueryVisualizations(query, visualization) {
  function saveVisualization (line 35) | function saveVisualization(visualization) {
  function confirmDialogClose (line 53) | function confirmDialogClose(isDirty) {
  function EditVisualizationDialog (line 70) | function EditVisualizationDialog({ dialog, visualization, query, queryRe...

FILE: client/app/components/visualizations/VisualizationName.jsx
  function VisualizationName (line 6) | function VisualizationName({ visualization }) {

FILE: client/app/components/visualizations/VisualizationRenderer.jsx
  function combineFilters (line 10) | function combineFilters(localFilters, globalFilters) {
  function areFiltersEqual (line 28) | function areFiltersEqual(a, b) {
  function VisualizationRenderer (line 39) | function VisualizationRenderer(props) {

FILE: client/app/components/visualizations/visualizationComponents.jsx
  function wrapComponentWithSettings (line 12) | function wrapComponentWithSettings(WrappedComponent) {

FILE: client/app/config/index.js
  function requireImages (line 33) | function requireImages() {
  function registerExtensions (line 39) | function registerExtensions() {

FILE: client/app/lib/accessibility.ts
  type SrNotifyProps (line 3) | interface SrNotifyProps {
  function srNotify (line 10) | function srNotify({ text, expiry = 1000, container = document.body, poli...

FILE: client/app/lib/calculateTextWidth.ts
  function calculateTextWidth (line 5) | function calculateTextWidth(text: string, container = document.body) {

FILE: client/app/lib/hooks/useFullscreenHandler.js
  function useFullscreenHandler (line 5) | function useFullscreenHandler() {

FILE: client/app/lib/hooks/useImmutableCallback.js
  function useImmutableCallback (line 9) | function useImmutableCallback(callback) {

FILE: client/app/lib/hooks/useLazyRef.ts
  function useLazyRef (line 3) | function useLazyRef<T>(getInitialValue: () => T) {

FILE: client/app/lib/hooks/useSearchResults.js
  function useSearchResults (line 4) | function useSearchResults(fetch, { initialResults = null, debounceTimeou...

FILE: client/app/lib/hooks/useUniqueId.ts
  function useUniqueId (line 4) | function useUniqueId(prefix: string) {

FILE: client/app/lib/localOptions.js
  constant PREFIX (line 1) | const PREFIX = "localOptions:";
  function get (line 3) | function get(key, defaultValue = undefined) {
  function set (line 11) | function set(key, value) {

FILE: client/app/lib/pagination/paginator.js
  class Paginator (line 3) | class Paginator {
    method constructor (line 4) | constructor(rows, { page = 1, itemsPerPage = 20, totalCount = undefine...
    method setPage (line 12) | setPage(page) {
    method getPageRows (line 16) | getPageRows() {
    method updateRows (line 23) | updateRows(rows, totalCount = undefined) {
    method orderBy (line 32) | orderBy(column) {

FILE: client/app/lib/queryFormat.ts
  type QueryFormatterMap (line 4) | interface QueryFormatterMap {
  function isFormatQueryAvailable (line 13) | function isFormatQueryAvailable(syntax: string) {
  function formatQuery (line 17) | function formatQuery(queryText: string, syntax: string) {

FILE: client/app/lib/useQueryResultData.js
  function getQueryResultData (line 4) | function getQueryResultData(queryResult, queryResultStatus = null) {
  function useQueryResultData (line 20) | function useQueryResultData(queryResult) {

FILE: client/app/lib/utils.js
  function formatDateTimeValue (line 23) | function formatDateTimeValue(value, format) {
  function formatDateTime (line 36) | function formatDateTime(value) {
  function formatDateTimePrecise (line 40) | function formatDateTimePrecise(value, withMilliseconds = false) {
  function formatDate (line 44) | function formatDate(value) {
  function localizeTime (line 48) | function localizeTime(time) {
  function secondsToInterval (line 58) | function secondsToInterval(count) {
  function pluralize (line 83) | function pluralize(text, count) {
  function durationHumanize (line 88) | function durationHumanize(durationInSeconds, options = {}) {
  function toHuman (line 102) | function toHuman(text) {
  function remove (line 106) | function remove(items, item) {
  function formatNumber (line 136) | function formatNumber(value, fractionDigits = 3) {
  function prettyNumberWithUnit (line 148) | function prettyNumberWithUnit(value, divisor, units = [], fractionDigits) {
  function prettySizeWithUnit (line 173) | function prettySizeWithUnit(bytes, fractionDigits) {
  function prettySize (line 177) | function prettySize(bytes) {
  function join (line 185) | function join(arr) {
  function formatColumnValue (line 193) | function formatColumnValue(value, columnType = null) {

FILE: client/app/pages/admin/Jobs.jsx
  class Jobs (line 17) | class Jobs extends React.Component {
    method componentDidMount (line 31) | componentDidMount() {
    method componentWillUnmount (line 36) | componentWillUnmount() {
    method render (line 81) | render() {

FILE: client/app/pages/admin/OutdatedQueries.jsx
  class OutdatedQueries (line 25) | class OutdatedQueries extends React.Component {
    method componentDidMount (line 75) | componentDidMount() {
    method componentWillUnmount (line 80) | componentWillUnmount() {
    method render (line 91) | render() {
  method doRequest (line 145) | doRequest(request, context) {
  method processResults (line 156) | processResults(items) {

FILE: client/app/pages/admin/SystemStatus.jsx
  class SystemStatus (line 15) | class SystemStatus extends React.Component {
    method componentDidMount (line 33) | componentDidMount() {
    method componentWillUnmount (line 38) | componentWillUnmount() {
    method render (line 61) | render() {

FILE: client/app/pages/alert/Alert.jsx
  constant MODES (line 21) | const MODES = {
  function getDefaultName (line 29) | function getDefaultName(alert) {
  class Alert (line 36) | class Alert extends React.Component {
    method componentDidMount (line 59) | componentDidMount() {
    method componentWillUnmount (line 106) | componentWillUnmount() {
    method render (line 229) | render() {

FILE: client/app/pages/alert/AlertEdit.jsx
  class AlertEdit (line 19) | class AlertEdit extends React.Component {
    method componentDidMount (line 26) | componentDidMount() {
    method componentWillUnmount (line 30) | componentWillUnmount() {
    method render (line 47) | render() {

FILE: client/app/pages/alert/AlertNew.jsx
  class AlertNew (line 17) | class AlertNew extends React.Component {
    method render (line 29) | render() {

FILE: client/app/pages/alert/AlertView.jsx
  function AlertState (line 24) | function AlertState({ state, lastTriggered }) {
  class AlertView (line 51) | class AlertView extends React.Component {
    method render (line 63) | render() {

FILE: client/app/pages/alert/components/AlertDestinations.jsx
  constant USER_EMAIL_DEST_ID (line 24) | const USER_EMAIL_DEST_ID = -1;
  function normalizeSub (line 26) | function normalizeSub(sub) {
  function ListItem (line 38) | function ListItem({ destination: { name, type }, user, unsubscribe }) {
  class AlertDestinations (line 66) | class AlertDestinations extends React.Component {
    method componentDidMount (line 76) | componentDidMount() {
    method render (line 175) | render() {

FILE: client/app/pages/alert/components/Criteria.jsx
  constant CONDITIONS (line 14) | const CONDITIONS = {
  constant VALID_STRING_CONDITIONS (line 23) | const VALID_STRING_CONDITIONS = ["==", "!="];
  function DisabledInput (line 25) | function DisabledInput({ children, minWidth }) {
  function Criteria (line 38) | function Criteria({ columnNames, resultValues, alertOptions, onChange, e...

FILE: client/app/pages/alert/components/HorizontalFormItem.jsx
  function HorizontalFormItem (line 6) | function HorizontalFormItem({ children, label, className, ...props }) {

FILE: client/app/pages/alert/components/MenuButton.jsx
  function MenuButton (line 14) | function MenuButton({ doDelete, canEdit, mute, unmute, evaluate, muted }) {

FILE: client/app/pages/alert/components/NotificationTemplate.jsx
  function normalizeCustomTemplateData (line 16) | function normalizeCustomTemplateData(alert, query, columnNames, resultVa...
  function NotificationTemplate (line 33) | function NotificationTemplate({ alert, query, columnNames, resultValues,...

FILE: client/app/pages/alert/components/Query.jsx
  function QueryFormItem (line 17) | function QueryFormItem({ query, queryResult, onChange, editMode }) {

FILE: client/app/pages/alert/components/Rearm.jsx
  constant DURATIONS (line 10) | const DURATIONS = [
  function RearmByDuration (line 18) | function RearmByDuration({ value, onChange, editMode }) {
  function RearmEditor (line 79) | function RearmEditor({ value, onChange }) {
  function RearmViewer (line 114) | function RearmViewer({ value }) {
  function Rearm (line 138) | function Rearm({ editMode, ...props }) {

FILE: client/app/pages/alert/components/Title.jsx
  function Title (line 10) | function Title({ alert, editMode, name, onChange, children }) {

FILE: client/app/pages/alerts/AlertsList.jsx
  constant STATE_CLASS (line 19) | const STATE_CLASS = {
  class AlertsList (line 25) | class AlertsList extends React.Component {
    method render (line 80) | render() {
  method getRequest (line 140) | getRequest() {
  method getResource (line 143) | getResource() {

FILE: client/app/pages/dashboards/DashboardList.jsx
  function DashboardListExtraActions (line 79) | function DashboardListExtraActions(props) {
  function DashboardList (line 83) | function DashboardList({ controller }) {
  method getResource (line 172) | getResource({ params: { currentPage } }) {
  method getItemProcessor (line 179) | getItemProcessor() {

FILE: client/app/pages/dashboards/DashboardPage.jsx
  function DashboardSettings (line 27) | function DashboardSettings({ dashboardConfiguration }) {
  function AddWidgetContainer (line 46) | function AddWidgetContainer({ dashboardConfiguration, className, ...prop...
  function DashboardComponent (line 74) | function DashboardComponent(props) {
  function DashboardPage (line 173) | function DashboardPage({ dashboardSlug, dashboardId, onError }) {

FILE: client/app/pages/dashboards/PublicDashboardPage.jsx
  function PublicDashboard (line 22) | function PublicDashboard({ dashboard }) {
  class PublicDashboardPage (line 59) | class PublicDashboardPage extends React.Component {
    method componentDidMount (line 74) | componentDidMount() {
    method render (line 80) | render() {

FILE: client/app/pages/dashboards/components/DashboardHeader.jsx
  function getDashboardTags (line 24) | function getDashboardTags() {
  function buttonType (line 28) | function buttonType(value) {
  function DashboardPageTitle (line 32) | function DashboardPageTitle({ dashboardConfiguration }) {
  function RefreshButton (line 66) | function RefreshButton({ dashboardConfiguration }) {
  function DashboardMoreOptionsButton (line 114) | function DashboardMoreOptionsButton({ dashboardConfiguration }) {
  function DashboardControl (line 183) | function DashboardControl({ dashboardConfiguration, headerExtra }) {
  function DashboardEditControl (line 253) | function DashboardEditControl({ dashboardConfiguration, headerExtra }) {
  function DashboardHeader (line 302) | function DashboardHeader({ dashboardConfiguration, headerExtra }) {

FILE: client/app/pages/dashboards/components/DashboardListEmptyState.tsx
  type DashboardListEmptyStateProps (line 12) | interface DashboardListEmptyStateProps {
  function DashboardListEmptyState (line 18) | function DashboardListEmptyState({ page, searchTerm, selectedTags }: Das...

FILE: client/app/pages/dashboards/components/ShareDashboardDialog.jsx
  constant API_SHARE_URL (line 14) | const API_SHARE_URL = "api/dashboards/{id}/share";
  class ShareDashboardDialog (line 16) | class ShareDashboardDialog extends React.Component {
    method constructor (line 29) | constructor(props) {
    method headerContent (line 41) | static get headerContent() {
    method render (line 96) | render() {

FILE: client/app/pages/dashboards/hooks/useDashboard.js
  function getAffectedWidgets (line 23) | function getAffectedWidgets(widgets, updatedParameters = []) {
  function useDashboard (line 38) | function useDashboard(dashboardData) {

FILE: client/app/pages/dashboards/hooks/useDataSources.js
  function useDataSources (line 8) | function useDataSources() {

FILE: client/app/pages/dashboards/hooks/useDuplicateDashboard.js
  function keepCurrentUrlParams (line 7) | function keepCurrentUrlParams(targetUrl) {
  function useDuplicateDashboard (line 18) | function useDuplicateDashboard(dashboard) {

FILE: client/app/pages/dashboards/hooks/useEditModeHandler.js
  function getChangedPositions (line 12) | function getChangedPositions(widgets, nextPositions = {}) {
  function useEditModeHandler (line 20) | function useEditModeHandler(canEditDashboard, widgets) {

FILE: client/app/pages/dashboards/hooks/useRefreshRateHandler.js
  function getLimitedRefreshRate (line 7) | function getLimitedRefreshRate(refreshRate) {
  function getRefreshRateFromUrl (line 12) | function getRefreshRateFromUrl() {
  function useRefreshRateHandler (line 17) | function useRefreshRateHandler(refreshDashboard) {

FILE: client/app/pages/data-sources/DataSourcesList.jsx
  function DataSourcesListComponent (line 21) | function DataSourcesListComponent({ dataSources, onClickCreate }) {
  class DataSourcesList (line 47) | class DataSourcesList extends React.Component {
    method componentDidMount (line 66) | componentDidMount() {
    method componentWillUnmount (line 90) | componentWillUnmount() {
    method render (line 130) | render() {

FILE: client/app/pages/data-sources/EditDataSource.jsx
  class EditDataSource (line 18) | class EditDataSource extends React.Component {
    method componentDidMount (line 34) | componentDidMount() {
    method renderForm (line 102) | renderForm() {
    method render (line 139) | render() {

FILE: client/app/pages/destinations/DestinationsList.jsx
  class DestinationsList (line 19) | class DestinationsList extends React.Component {
    method componentDidMount (line 36) | componentDidMount() {
    method renderDestinations (line 88) | renderDestinations() {
    method render (line 113) | render() {

FILE: client/app/pages/destinations/EditDestination.jsx
  class EditDestination (line 17) | class EditDestination extends React.Component {
    method componentDidMount (line 33) | componentDidMount() {
    method renderForm (line 80) | renderForm() {
    method render (line 105) | render() {

FILE: client/app/pages/groups/GroupDataSources.jsx
  class GroupDataSources (line 33) | class GroupDataSources extends React.Component {
    method componentDidMount (line 101) | componentDidMount() {
    method render (line 172) | render() {
  method getRequest (line 237) | getRequest(unused, { params: { groupId } }) {
  method getResource (line 240) | getResource() {

FILE: client/app/pages/groups/GroupMembers.jsx
  class GroupMembers (line 30) | class GroupMembers extends React.Component {
    method componentDidMount (line 82) | componentDidMount() {
    method render (line 135) | render() {
  method getRequest (line 200) | getRequest(unused, { params: { groupId } }) {
  method getResource (line 203) | getResource() {

FILE: client/app/pages/groups/GroupsList.jsx
  class GroupsList (line 25) | class GroupsList extends React.Component {
    method render (line 88) | render() {
  method getRequest (line 143) | getRequest() {
  method getResource (line 146) | getResource() {

FILE: client/app/pages/home/Home.jsx
  function DeprecatedEmbedFeatureAlert (line 22) | function DeprecatedEmbedFeatureAlert() {
  function EmailNotVerifiedAlert (line 45) | function EmailNotVerifiedAlert() {
  function Home (line 70) | function Home() {

FILE: client/app/pages/home/components/FavoritesList.jsx
  function FavoriteList (line 11) | function FavoriteList({ title, resource, itemUrl, emptyState }) {
  function DashboardAndQueryFavoritesList (line 55) | function DashboardAndQueryFavoritesList() {

FILE: client/app/pages/queries-list/QueriesList.jsx
  function QueriesListExtraActions (line 90) | function QueriesListExtraActions(props) {
  function QueriesList (line 94) | function QueriesList({ controller }) {
  method getResource (line 205) | getResource({ params: { currentPage } }) {
  method getItemProcessor (line 213) | getItemProcessor() {

FILE: client/app/pages/queries-list/QueriesListEmptyState.jsx
  function QueriesListEmptyState (line 11) | function QueriesListEmptyState({ page, searchTerm, selectedTags }) {

FILE: client/app/pages/queries/QuerySource.jsx
  function chooseDataSourceId (line 49) | function chooseDataSourceId(dataSourceIds, availableDataSources) {
  function QuerySource (line 54) | function QuerySource(props) {

FILE: client/app/pages/queries/QueryView.jsx
  function QueryView (line 43) | function QueryView(props) {

FILE: client/app/pages/queries/VisualizationEmbed.jsx
  function VisualizationEmbedHeader (line 35) | function VisualizationEmbedHeader({ queryName, queryDescription, visuali...
  function VisualizationEmbedFooter (line 59) | function VisualizationEmbedFooter({
  function VisualizationEmbed (line 160) | function VisualizationEmbed({ queryId, visualizationId, apiKey, onError ...

FILE: client/app/pages/queries/components/QueryExecutionMetadata.jsx
  function QueryExecutionMetadata (line 16) | function QueryExecutionMetadata({

FILE: client/app/pages/queries/components/QueryExecutionStatus.jsx
  function QueryExecutionStatus (line 8) | function QueryExecutionStatus({ status, updatedAt, error, isCancelling, ...

FILE: client/app/pages/queries/components/QueryMetadata.jsx
  function QueryMetadata (line 12) | function QueryMetadata({ query, dataSource, layout, onEditSchedule }) {

FILE: client/app/pages/queries/components/QueryPageHeader.jsx
  function getQueryTags (line 27) | function getQueryTags() {
  function createMenu (line 31) | function createMenu(menu) {
  function QueryPageHeader (line 65) | function QueryPageHeader({

FILE: client/app/pages/queries/components/QuerySourceAlerts.jsx
  function QuerySourceAlerts (line 13) | function QuerySourceAlerts({ query, dataSourcesAvailable }) {

FILE: client/app/pages/queries/components/QuerySourceDropdown.jsx
  function QuerySourceDropdown (line 9) | function QuerySourceDropdown(props) {

FILE: client/app/pages/queries/components/QuerySourceDropdownItem.jsx
  function QuerySourceDropdownItem (line 6) | function QuerySourceDropdownItem({ dataSource, children }) {

FILE: client/app/pages/queries/components/QuerySourceTypeIcon.jsx
  function QuerySourceTypeIcon (line 4) | function QuerySourceTypeIcon(props) {

FILE: client/app/pages/queries/components/QueryViewButton.jsx
  function QueryViewButton (line 7) | function QueryViewButton({ title, shortcut, disabled, children, onClick,...

FILE: client/app/pages/queries/components/QueryVisualizationTabs.jsx
  function EmptyState (line 16) | function EmptyState({ title, message, refreshButton }) {
  function TabWithDeleteButton (line 41) | function TabWithDeleteButton({ visualizationName, canDelete, onDelete, ....
  function QueryVisualizationTabs (line 86) | function QueryVisualizationTabs({

FILE: client/app/pages/queries/components/wrapQueryPage.jsx
  function wrapQueryPage (line 7) | function wrapQueryPage(WrappedComponent) {

FILE: client/app/pages/queries/hooks/useAddNewParameterDialog.js
  function useAddNewParameterDialog (line 6) | function useAddNewParameterDialog(query, onParameterAdded) {

FILE: client/app/pages/queries/hooks/useAddToDashboardDialog.js
  function useAddToDashboardDialog (line 5) | function useAddToDashboardDialog(query) {

FILE: client/app/pages/queries/hooks/useAddVisualizationDialog.js
  function useAddVisualizationDialog (line 5) | function useAddVisualizationDialog(query, queryResult, saveQuery, onChan...

FILE: client/app/pages/queries/hooks/useApiKeyDialog.js
  function useApiKeyDialog (line 5) | function useApiKeyDialog(query, onChange) {

FILE: client/app/pages/queries/hooks/useArchiveQuery.jsx
  function confirmArchive (line 8) | function confirmArchive() {
  function doArchiveQuery (line 32) | function doArchiveQuery(query) {
  function useArchiveQuery (line 43) | function useArchiveQuery(query, onChange) {

FILE: client/app/pages/queries/hooks/useAutoLimitFlags.js
  function isAutoLimitAvailable (line 5) | function isAutoLimitAvailable(dataSource) {
  function useAutoLimitFlags (line 9) | function useAutoLimitFlags(dataSource, query, setQuery) {

FILE: client/app/pages/queries/hooks/useAutocompleteFlags.js
  function useAutocompleteFlags (line 4) | function useAutocompleteFlags(schema) {

FILE: client/app/pages/queries/hooks/useDataSourceSchema.js
  function getSchema (line 5) | function getSchema(dataSource, refresh = undefined) {
  function useDataSourceSchema (line 16) | function useDataSourceSchema(dataSource) {

FILE: client/app/pages/queries/hooks/useDeleteVisualization.js
  function useDeleteVisualization (line 7) | function useDeleteVisualization(query, onChange) {

FILE: client/app/pages/queries/hooks/useDuplicateQuery.js
  function keepCurrentUrlParams (line 7) | function keepCurrentUrlParams(targetUrl) {
  function useDuplicateQuery (line 18) | function useDuplicateQuery(query) {

FILE: client/app/pages/queries/hooks/useEditScheduleDialog.js
  function useEditScheduleDialog (line 10) | function useEditScheduleDialog(query, onChange) {

FILE: client/app/pages/queries/hooks/useEditVisualizationDialog.js
  function useEditVisualizationDialog (line 6) | function useEditVisualizationDialog(query, queryResult, onChange) {

FILE: client/app/pages/queries/hooks/useEmbedDialog.js
  function useEmbedDialog (line 5) | function useEmbedDialog(query) {

FILE: client/app/pages/queries/hooks/usePermissionsEditorDialog.js
  function usePermissionsEditorDialog (line 4) | function usePermissionsEditorDialog(query) {

FILE: client/app/pages/queries/hooks/usePublishQuery.js
  function usePublishQuery (line 5) | function usePublishQuery(query, onChange) {

FILE: client/app/pages/queries/hooks/useQuery.js
  function useQuery (line 6) | function useQuery(originalQuery) {

FILE: client/app/pages/queries/hooks/useQueryDataSources.js
  function useQueryDataSources (line 5) | function useQueryDataSources(query) {

FILE: client/app/pages/queries/hooks/useQueryExecute.js
  function getMaxAge (line 8) | function getMaxAge() {
  function useQueryExecute (line 21) | function useQueryExecute(query) {

FILE: client/app/pages/queries/hooks/useQueryFlags.js
  function useQueryFlags (line 6) | function useQueryFlags(query, dataSource = null) {

FILE: client/app/pages/queries/hooks/useQueryParameters.js
  function useQueryParameters (line 4) | function useQueryParameters(query) {

FILE: client/app/pages/queries/hooks/useRenameQuery.js
  function useRenameQuery (line 6) | function useRenameQuery(query, onChange) {

FILE: client/app/pages/queries/hooks/useUnpublishQuery.js
  function useUnpublishQuery (line 5) | function useUnpublishQuery(query, onChange) {

FILE: client/app/pages/queries/hooks/useUnsavedChangesAlert.js
  function useUnsavedChangesAlert (line 4) | function useUnsavedChangesAlert(shouldShowAlert = false) {

FILE: client/app/pages/queries/hooks/useUpdateQuery.jsx
  class SaveQueryError (line 9) | class SaveQueryError extends Error {
    method constructor (line 10) | constructor(message, detailedMessage = null) {
  class SaveQueryConflictError (line 16) | class SaveQueryConflictError extends SaveQueryError {
    method constructor (line 17) | constructor() {
  function confirmOverwrite (line 28) | function confirmOverwrite() {
  function doSaveQuery (line 52) | function doSaveQuery(data, { canOverwrite = false } = {}) {
  function useUpdateQuery (line 74) | function useUpdateQuery(query, onChange) {

FILE: client/app/pages/queries/hooks/useUpdateQueryDescription.js
  function useUpdateQueryDescription (line 5) | function useUpdateQueryDescription(query, onChange) {

FILE: client/app/pages/queries/hooks/useUpdateQueryTags.js
  function useUpdateQueryTags (line 5) | function useUpdateQueryTags(query, onChange) {

FILE: client/app/pages/queries/hooks/useVisualizationTabHandler.js
  function useVisualizationTabHandler (line 5) | function useVisualizationTabHandler(visualizations) {

FILE: client/app/pages/query-snippets/QuerySnippetsList.jsx
  class QuerySnippetsList (line 30) | class QuerySnippetsList extends React.Component {
    method componentDidMount (line 77) | componentDidMount() {
    method render (line 139) | render() {
  method getRequest (line 206) | getRequest() {
  method getResource (line 209) | getResource() {

FILE: client/app/pages/settings/OrganizationSettings.jsx
  function OrganizationSettings (line 17) | function OrganizationSettings({ onError }) {

FILE: client/app/pages/settings/components/AuthSettings/GoogleLoginSettings.jsx
  function GoogleLoginSettings (line 10) | function GoogleLoginSettings(props) {

FILE: client/app/pages/settings/components/AuthSettings/PasswordLoginSettings.jsx
  function PasswordLoginSettings (line 11) | function PasswordLoginSettings(props) {

FILE: client/app/pages/settings/components/AuthSettings/SAMLSettings.jsx
  function SAMLSettings (line 9) | function SAMLSettings(props) {

FILE: client/app/pages/settings/components/AuthSettings/index.jsx
  function AuthSettings (line 11) | function AuthSettings(props) {

FILE: client/app/pages/settings/components/GeneralSettings/BeaconConsentSettings.jsx
  function BeaconConsentSettings (line 9) | function BeaconConsentSettings(props) {

FILE: client/app/pages/settings/components/GeneralSettings/FeatureFlagsSettings.jsx
  function FeatureFlagsSettings (line 9) | function FeatureFlagsSettings(props) {

FILE: client/app/pages/settings/components/GeneralSettings/FormatSettings.jsx
  function FormatSettings (line 9) | function FormatSettings(props) {

FILE: client/app/pages/settings/components/GeneralSettings/PlotlySettings.jsx
  function PlotlySettings (line 8) | function PlotlySettings(props) {

FILE: client/app/pages/settings/components/GeneralSettings/index.jsx
  function GeneralSettings (line 9) | function GeneralSettings(props) {

FILE: client/app/pages/settings/hooks/useOrganizationSettings.js
  function useOrganizationSettings (line 8) | function useOrganizationSettings({ onError }) {

FILE: client/app/pages/users/UserProfile.jsx
  function UserProfile (line 20) | function UserProfile({ userId, onError }) {

FILE: client/app/pages/users/UsersList.jsx
  function UsersListActions (line 36) | function UsersListActions({ user, enableUser, disableUser, deleteUser }) {
  class UsersList (line 69) | class UsersList extends React.Component {
    method componentDidMount (line 139) | componentDidMount() {
    method renderPageHeader (line 193) | renderPageHeader() {
    method render (line 208) | render() {
  method getRequest (line 265) | getRequest(request, { params: { currentPage } }) {
  method getResource (line 280) | getResource() {

FILE: client/app/pages/users/components/ApiKeyForm.jsx
  function ApiKeyForm (line 13) | function ApiKeyForm(props) {

FILE: client/app/pages/users/components/CreateUserDialog.jsx
  function CreateUserDialog (line 15) | function CreateUserDialog({ dialog }) {

FILE: client/app/pages/users/components/EditableUserProfile.jsx
  function EditableUserProfile (line 9) | function EditableUserProfile(props) {

FILE: client/app/pages/users/components/PasswordForm/ChangePasswordDialog.jsx
  class ChangePasswordDialog (line 11) | class ChangePasswordDialog extends React.Component {
    method constructor (line 17) | constructor(props) {
    method render (line 99) | render() {

FILE: client/app/pages/users/components/PasswordForm/PasswordLinkAlert.jsx
  function PasswordLinkAlert (line 10) | function PasswordLinkAlert(props) {

FILE: client/app/pages/users/components/PasswordForm/PasswordResetForm.jsx
  function PasswordResetForm (line 8) | function PasswordResetForm(props) {

FILE: client/app/pages/users/components/PasswordForm/ResendInvitationForm.jsx
  function ResendInvitationForm (line 8) | function ResendInvitationForm(props) {

FILE: client/app/pages/users/components/PasswordForm/index.jsx
  function PasswordForm (line 11) | function PasswordForm(props) {

FILE: client/app/pages/users/components/ReadOnlyUserProfile.jsx
  function ReadOnlyUserProfile (line 7) | function ReadOnlyUserProfile({ user }) {

FILE: client/app/pages/users/components/ToggleUserForm.jsx
  function ToggleUserForm (line 10) | function ToggleUserForm(props) {

FILE: client/app/pages/users/components/UserInfoForm.jsx
  function UserInfoForm (line 15) | function UserInfoForm(props) {

FILE: client/app/pages/users/hooks/useUserGroups.js
  function useUserGroups (line 5) | function useUserGroups(user) {

FILE: client/app/services/KeyboardShortcuts.js
  function humanReadableShortcut (line 8) | function humanReadableShortcut(shortcut, limit = Infinity) {
  function onShortcut (line 26) | function onShortcut(event, shortcut) {

FILE: client/app/services/auth.js
  method canEdit (line 10) | canEdit(object) {
  method canCreate (line 15) | canCreate() {
  method hasPermission (line 21) | hasPermission(permission) {
  method isAdmin (line 28) | get isAdmin() {
  method isAdmin (line 32) | set isAdmin(isAdmin) {
  function updateClientConfig (line 47) | function updateClientConfig(newClientConfig) {
  function updateSession (line 51) | function updateSession(sessionData) {
  method isAuthenticated (line 60) | isAuthenticated() {
  method getLoginUrl (line 63) | getLoginUrl() {
  method setLoginUrl (line 66) | setLoginUrl(loginUrl) {
  method login (line 69) | login() {
  method logout (line 74) | logout() {
  method loadSession (line 78) | loadSession() {
  method loadConfig (line 91) | loadConfig() {
  method setApiKey (line 98) | setApiKey(apiKey) {
  method getApiKey (line 102) | getApiKey() {
  method requireSession (line 105) | requireSession() {

FILE: client/app/services/dashboard.js
  function collectDashboardFilters (line 11) | function collectDashboardFilters(dashboard, queryResults, urlParams) {
  function prepareWidgetsForDashboard (line 40) | function prepareWidgetsForDashboard(widgets) {
  function calculateNewWidgetPosition (line 83) | function calculateNewWidgetPosition(existingWidgets, newWidget) {
  function Dashboard (line 129) | function Dashboard(dashboard) {
  function prepareDashboardWidgets (line 138) | function prepareDashboardWidgets(widgets) {
  function transformSingle (line 142) | function transformSingle(dashboard) {
  function transformResponse (line 151) | function transformResponse(data) {

FILE: client/app/services/data-source.js
  constant SCHEMA_NOT_SUPPORTED (line 5) | const SCHEMA_NOT_SUPPORTED = 1;
  constant SCHEMA_LOAD_ERROR (line 6) | const SCHEMA_LOAD_ERROR = 2;
  constant IMG_ROOT (line 7) | const IMG_ROOT = "/static/images/db-logos";
  function mapSchemaColumnsToObject (line 9) | function mapSchemaColumnsToObject(columns) {

FILE: client/app/services/databricks-data-source.js
  function fetchDataFromJobOrReturnData (line 6) | function fetchDataFromJobOrReturnData(data) {
  function rejectErrorResponse (line 10) | function rejectErrorResponse(data) {

FILE: client/app/services/destination.js
  constant IMG_ROOT (line 3) | const IMG_ROOT = "static/images/destinations";

FILE: client/app/services/getTags.js
  function processTags (line 3) | function processTags(data) {
  function getTags (line 7) | function getTags(url) {

FILE: client/app/services/location.js
  function normalizeLocation (line 7) | function normalizeLocation(rawLocation) {
  method listen (line 20) | listen(handler) {
  method confirmChange (line 28) | confirmChange(handler) {
  method update (line 38) | update(newLocation, replace = false) {
  method setPath (line 83) | setPath(path, replace = false) {
  method setSearch (line 88) | setSearch(search, replace = false) {
  method setHash (line 93) | setHash(hash, replace = false) {
  function locationChanged (line 98) | function locationChanged() {

FILE: client/app/services/notification.d.ts
  type NotificationConfig (line 3) | type NotificationConfig = Omit<ArgsProps, "message" | "description"> | n...
  type NotificationFunction (line 5) | type NotificationFunction = (

FILE: client/app/services/notifications.js
  function isPageVisible (line 15) | function isPageVisible() {
  function getPermissions (line 19) | function getPermissions() {
  function showNotification (line 25) | function showNotification(title, content) {

FILE: client/app/services/offline-listener.js
  function addOnlineListener (line 3) | function addOnlineListener(notificationKey) {
  method init (line 12) | init() {

FILE: client/app/services/organizationStatus.js
  class OrganizationStatus (line 3) | class OrganizationStatus {
    method constructor (line 4) | constructor() {
    method refresh (line 8) | refresh() {

FILE: client/app/services/parameters/DateParameter.js
  constant DATETIME_FORMATS (line 6) | const DATETIME_FORMATS = {
  constant DYNAMIC_PREFIX (line 13) | const DYNAMIC_PREFIX = "d_";
  constant DYNAMIC_DATES (line 15) | const DYNAMIC_DATES = {
  function isDynamicDateString (line 28) | function isDynamicDateString(value) {
  function isDynamicDate (line 32) | function isDynamicDate(value) {
  function getDynamicDateFromString (line 36) | function getDynamicDateFromString(value) {
  class DateParameter (line 43) | class DateParameter extends Parameter {
    method constructor (line 44) | constructor(parameter, parentQueryId) {
    method hasDynamicValue (line 50) | get hasDynamicValue() {
    method normalizeValue (line 55) | normalizeValue(value) {
    method setValue (line 68) | setValue(value) {
    method getExecutionValue (line 84) | getExecutionValue() {

FILE: client/app/services/parameters/DateRangeParameter.js
  constant DATETIME_FORMATS (line 6) | const DATETIME_FORMATS = {
  constant DYNAMIC_PREFIX (line 12) | const DYNAMIC_PREFIX = "d_";
  constant DYNAMIC_DATE_RANGES (line 24) | const DYNAMIC_DATE_RANGES = {
  function isDynamicDateRangeString (line 109) | function isDynamicDateRangeString(value) {
  function getDynamicDateRangeStringFromName (line 116) | function getDynamicDateRangeStringFromName(dynamicRangeName) {
  function isDynamicDateRange (line 121) | function isDynamicDateRange(value) {
  function getDynamicDateRangeFromString (line 125) | function getDynamicDateRangeFromString(value) {
  class DateRangeParameter (line 132) | class DateRangeParameter extends Parameter {
    method constructor (line 133) | constructor(parameter, parentQueryId) {
    method hasDynamicValue (line 138) | get hasDynamicValue() {
    method normalizeValue (line 143) | normalizeValue(value) {
    method setValue (line 165) | setValue(value) {
    method getExecutionValue (line 184) | getExecutionValue() {
    method toUrlParams (line 193) | toUrlParams() {
    method fromUrlParams (line 203) | fromUrlParams(query) {
    method toQueryTextFragment (line 223) | toQueryTextFragment() {

FILE: client/app/services/parameters/EnumParameter.js
  class EnumParameter (line 4) | class EnumParameter extends Parameter {
    method constructor (line 5) | constructor(parameter, parentQueryId) {
    method normalizeValue (line 12) | normalizeValue(value) {
    method getExecutionValue (line 33) | getExecutionValue(extra = {}) {
    method toUrlParams (line 45) | toUrlParams() {
    method fromUrlParams (line 58) | fromUrlParams(query) {

FILE: client/app/services/parameters/NumberParameter.js
  class NumberParameter (line 4) | class NumberParameter extends Parameter {
    method constructor (line 5) | constructor(parameter, parentQueryId) {
    method normalizeValue (line 11) | normalizeValue(value) {

FILE: client/app/services/parameters/Parameter.js
  class Parameter (line 3) | class Parameter {
    method constructor (line 4) | constructor(parameter, parentQueryId) {
    method getExecutionValue (line 18) | static getExecutionValue(param, extra = {}) {
    method setValue (line 26) | static setValue(param, value) {
    method isEmpty (line 34) | get isEmpty() {
    method hasPendingValue (line 38) | get hasPendingValue() {
    method normalizedValue (line 43) | get normalizedValue() {
    method isEmptyValue (line 47) | isEmptyValue(value) {
    method normalizeValue (line 52) | normalizeValue(value) {
    method updateLocals (line 59) | updateLocals() {
    method setValue (line 67) | setValue(value) {
    method getExecutionValue (line 78) | getExecutionValue() {
    method setPendingValue (line 82) | setPendingValue(value) {
    method applyPendingValue (line 86) | applyPendingValue() {
    method clearPendingValue (line 92) | clearPendingValue() {
    method toUrlParams (line 97) | toUrlParams() {
    method fromUrlParams (line 106) | fromUrlParams(query) {
    method toQueryTextFragment (line 114) | toQueryTextFragment() {
    method toSaveableObject (line 119) | toSaveableObject() {

FILE: client/app/services/parameters/QueryBasedDropdownParameter.js
  class QueryBasedDropdownParameter (line 5) | class QueryBasedDropdownParameter extends Parameter {
    method constructor (line 6) | constructor(parameter, parentQueryId) {
    method normalizeValue (line 13) | normalizeValue(value) {
    method getExecutionValue (line 26) | getExecutionValue(extra = {}) {
    method toUrlParams (line 38) | toUrlParams() {
    method fromUrlParams (line 51) | fromUrlParams(query) {
    method loadDropdownValues (line 68) | loadDropdownValues() {

FILE: client/app/services/parameters/TextParameter.js
  class TextParameter (line 4) | class TextParameter extends Parameter {
    method constructor (line 5) | constructor(parameter, parentQueryId) {
    method normalizeValue (line 11) | normalizeValue(value) {

FILE: client/app/services/parameters/TextPatternParameter.js
  class TextPatternParameter (line 4) | class TextPatternParameter extends Parameter {
    method constructor (line 5) | constructor(parameter, parentQueryId) {
    method normalizeValue (line 12) | normalizeValue(value) {

FILE: client/app/services/parameters/index.js
  function createParameter (line 10) | function createParameter(param, parentQueryId) {
  function cloneParameter (line 33) | function cloneParameter(param) {

FILE: client/app/services/policy/DefaultPolicy.js
  class DefaultPolicy (line 6) | class DefaultPolicy {
    method refresh (line 7) | refresh() {
    method canCreateDataSource (line 11) | canCreateDataSource() {
    method isCreateDataSourceEnabled (line 15) | isCreateDataSourceEnabled() {
    method canCreateDestination (line 19) | canCreateDestination() {
    method isCreateDestinationEnabled (line 23) | isCreateDestinationEnabled() {
    method canCreateDashboard (line 27) | canCreateDashboard() {
    method isCreateDashboardEnabled (line 31) | isCreateDashboardEnabled() {
    method canCreateAlert (line 35) | canCreateAlert() {
    method canCreateUser (line 39) | canCreateUser() {
    method isCreateUserEnabled (line 43) | isCreateUserEnabled() {
    method isCreateQuerySnippetEnabled (line 47) | isCreateQuerySnippetEnabled() {
    method getDashboardRefreshIntervals (line 51) | getDashboardRefreshIntervals() {
    method getQueryRefreshIntervals (line 56) | getQueryRefreshIntervals() {
    method canEdit (line 61) | canEdit(object) {
    method canRun (line 65) | canRun() {

FILE: client/app/services/policy/index.js
  function setPolicy (line 6) | function setPolicy(newPolicy) {

FILE: client/app/services/query-result.js
  function defer (line 11) | function defer() {
  function getColumnNameWithoutType (line 20) | function getColumnNameWithoutType(column) {
  function getColumnFriendlyName (line 42) | function getColumnFriendlyName(column) {
  function handleErrorResponse (line 67) | function handleErrorResponse(queryResult, error) {
  function sleep (line 99) | function sleep(ms) {
  function fetchDataFromJob (line 103) | function fetchDataFromJob(jobId, interval = 1000) {
  function isDateTime (line 116) | function isDateTime(v) {
  class QueryResult (line 120) | class QueryResult {
    method constructor (line 121) | constructor(props) {
    method update (line 137) | update(props) {
    method getId (line 198) | getId() {
    method cancelExecution (line 206) | cancelExecution() {
    method getStatus (line 210) | getStatus() {
    method getError (line 217) | getError() {
    method getLog (line 226) | getLog() {
    method getUpdatedAt (line 234) | getUpdatedAt() {
    method getRuntime (line 238) | getRuntime() {
    method getRawData (line 242) | getRawData() {
    method getData (line 250) | getData() {
    method isEmpty (line 254) | isEmpty() {
    method getColumns (line 258) | getColumns() {
    method getColumnNames (line 266) | getColumnNames() {
    method getColumnFriendlyNames (line 274) | getColumnFriendlyNames() {
    method getTruncated (line 278) | getTruncated() {
    method getFilters (line 282) | getFilters() {
    method toPromise (line 333) | toPromise(statusCallback) {
    method getById (line 340) | static getById(queryId, id) {
    method loadLatestCachedResult (line 362) | loadLatestCachedResult(queryId, parameters) {
    method loadResult (line 373) | loadResult(tryCount) {
    method refreshStatus (line 407) | refreshStatus(query, parameters, tryNumber = 1) {
    method getLink (line 447) | getLink(queryId, fileType, apiKey) {
    method getName (line 455) | getName(queryName, fileType) {
    method getByQueryId (line 459) | static getByQueryId(id, parameters, applyAutoLimit, maxAge) {
    method get (line 478) | static get(dataSourceId, query, parameters, applyAutoLimit, maxAge, qu...

FILE: client/app/services/query-snippet.js
  class QuerySnippet (line 4) | class QuerySnippet {
    method constructor (line 5) | constructor(querySnippet) {
    method getSnippet (line 9) | getSnippet() {

FILE: client/app/services/query.js
  function collectParams (line 33) | function collectParams(parts) {
  class Query (line 47) | class Query {
    method constructor (line 48) | constructor(query) {
    method isNew (line 61) | isNew() {
    method hasDailySchedule (line 65) | hasDailySchedule() {
    method scheduleInLocalTime (line 69) | scheduleInLocalTime() {
    method hasResult (line 79) | hasResult() {
    method paramsRequired (line 83) | paramsRequired() {
    method hasParameters (line 87) | hasParameters() {
    method prepareQueryResultExecution (line 91) | prepareQueryResultExecution(execute, maxAge) {
    method getQueryResult (line 134) | getQueryResult(maxAge) {
    method getQueryResultByText (line 140) | getQueryResultByText(maxAge, selectedQueryText) {
    method getUrl (line 152) | getUrl(source, hash) {
    method getQueryResultPromise (line 179) | getQueryResultPromise() {
    method getParameters (line 183) | getParameters() {
    method getAutoLimit (line 191) | getAutoLimit() {
    method getParametersDefs (line 195) | getParametersDefs(update = true) {
    method favorite (line 199) | favorite() {
    method unfavorite (line 203) | unfavorite() {
    method clone (line 207) | clone() {
  class Parameters (line 215) | class Parameters {
    method constructor (line 216) | constructor(query, queryString) {
    method parseQuery (line 222) | parseQuery() {
    method updateParameters (line 242) | updateParameters(update) {
    method initFromQueryString (line 285) | initFromQueryString(query) {
    method get (line 291) | get(update = true) {
    method add (line 296) | add(parameterDef) {
    method getMissing (line 303) | getMissing() {
    method isRequired (line 310) | isRequired() {
    method getExecutionValues (line 314) | getExecutionValues(extra = {}) {
    method hasPendingValues (line 322) | hasPendingValues() {
    method applyPendingValues (line 326) | applyPendingValues() {
    method toUrlParams (line 330) | toUrlParams() {
  class QueryResultError (line 343) | class QueryResultError {
    method constructor (line 344) | constructor(errorMessage) {
    method getUpdatedAt (line 349) | getUpdatedAt() {
    method getError (line 353) | getError() {
    method toPromise (line 357) | toPromise() {
    method getStatus (line 362) | getStatus() {
    method getData (line 367) | getData() {
    method getLog (line 372) | getLog() {

FILE: client/app/services/recordEvent.js
  function recordEvent (line 13) | function recordEvent(action, objectType, objectId, additionalProperties) {

FILE: client/app/services/resizeObserver.js
  function checkItems (line 3) | function checkItems() {
  function observe (line 22) | function observe(node, callback) {

FILE: client/app/services/restoreSession.jsx
  constant SESSION_RESTORED_MESSAGE (line 6) | const SESSION_RESTORED_MESSAGE = "redash_session_restored";
  function notifySessionRestored (line 8) | function notifySessionRestored() {
  function getPopupPosition (line 14) | function getPopupPosition(width, height) {
  function showRestoreSessionPrompt (line 28) | function showRestoreSessionPrompt(loginUrl, onSuccess) {
  function restoreSession (line 80) | function restoreSession() {

FILE: client/app/services/routes.ts
  type CurrentRoute (line 6) | interface CurrentRoute<P> {
  type RedashRoute (line 13) | interface RedashRoute<P = {}, C extends Context = Context, R = any> exte...
  type RouteItem (line 21) | interface RouteItem extends RedashRoute<any> {
  function getRouteParamsCount (line 25) | function getRouteParamsCount(path: string) {
  class Routes (line 30) | class Routes {
    method items (line 34) | get items(): RouteItem[] {
    method register (line 46) | public register<P>(id: string, route: RedashRoute<P>) {
    method unregister (line 55) | public unregister(id: string | null) {

FILE: client/app/services/settingsMenu.js
  class SettingsMenuItem (line 5) | class SettingsMenuItem {
    method constructor (line 6) | constructor(menuItem) {
    method isActive (line 16) | isActive(path) {
    method isAvailable (line 20) | isAvailable() {
  class SettingsMenu (line 25) | class SettingsMenu {
    method add (line 28) | add(id, item) {
    method remove (line 37) | remove(id) {
    method getAvailableItems (line 44) | getAvailableItems() {
    method getActiveItem (line 48) | getActiveItem(path) {

FILE: client/app/services/url.js
  function parse (line 10) | function parse(url) {
  function stringify (line 15) | function stringify(fragments) {
  function normalize (line 20) | function normalize(url) {

FILE: client/app/services/user.js
  function getErrorMessage (line 7) | function getErrorMessage(error) {
  function disableResource (line 11) | function disableResource(user) {
  function enableUser (line 15) | function enableUser(user) {
  function disableUser (line 31) | function disableUser(user) {
  function deleteUser (line 46) | function deleteUser(user) {
  function convertUserInfo (line 59) | function convertUserInfo(user) {
  function regenerateApiKey (line 72) | function regenerateApiKey(user) {
  function sendPasswordReset (line 84) | function sendPasswordReset(user) {
  function resendInvitation (line 99) | function resendInvitation(user) {

FILE: client/app/services/utils.js
  function absoluteUrl (line 2) | function absoluteUrl(url) {

FILE: client/app/services/widget.js
  function calculatePositionOptions (line 31) | function calculatePositionOptions(widget) {
  class Widget (line 95) | class Widget {
    method constructor (line 98) | constructor(data) {
    method type (line 116) | get type() {
    method getQuery (line 125) | getQuery() {
    method getQueryResult (line 133) | getQueryResult() {
    method getName (line 137) | getName() {
    method load (line 144) | load(force, maxAge) {
    method save (line 186) | save(key, value) {
    method delete (line 206) | delete() {
    method isStaticParam (line 211) | isStaticParam(param) {
    method getParametersDefs (line 217) | getParametersDefs() {
    method getParameterMappings (line 250) | getParameterMappings() {
    method getLocalParameters (line 282) | getLocalParameters() {

FILE: client/app/styles/formStyle.ts
  function getHorizontalFormProps (line 5) | function getHorizontalFormProps(): FormProps {
  function getHorizontalFormItemWithoutLabelProps (line 14) | function getHorizontalFormItemWithoutLabelProps(): FormItemProps {

FILE: client/cypress/cypress.js
  function seedDatabase (line 17) | function seedDatabase(seedValues) {
  function buildServer (line 44) | function buildServer() {
  function startServer (line 49) | function startServer() {
  function stopServer (line 55) | function stopServer() {
  function runCypressCI (line 60) | function runCypressCI() {

FILE: client/cypress/integration/dashboard/filters_spec.js
  constant SQL (line 4) | const SQL = `

FILE: client/cypress/integration/query/filters_spec.js
  constant SQL (line 3) | const SQL = `
  function expectSelectedOptionsToHaveMembers (line 63) | function expectSelectedOptionsToHaveMembers(values) {

FILE: client/cypress/integration/query/parameter_spec.js
  function openAndSearchAntdDropdown (line 4) | function openAndSearchAntdDropdown(testId, paramOption) {

FILE: client/cypress/integration/user/edit_profile_spec.js
  function fillProfileDataAndSave (line 1) | function fillProfileDataAndSave(name, email) {
  function fillChangePasswordAndSave (line 7) | function fillChangePasswordAndSave(currentPassword, newPassword, repeatP...

FILE: client/cypress/integration/visualizations/box_plot_spec.js
  constant SQL (line 3) | const SQL = `

FILE: client/cypress/integration/visualizations/chart_spec.js
  constant SQL (line 12) | const SQL = `

FILE: client/cypress/integration/visualizations/choropleth_spec.js
  constant SQL (line 3) | const SQL = `

FILE: client/cypress/integration/visualizations/cohort_spec.js
  constant SQL (line 3) | const SQL = `

FILE: client/cypress/integration/visualizations/counter_spec.js
  constant SQL (line 3) | const SQL = `

FILE: client/cypress/integration/visualizations/funnel_spec.js
  constant SQL (line 3) | const SQL = `

FILE: client/cypress/integration/visualizations/map_spec.js
  constant SQL (line 3) | const SQL = `

FILE: client/cypress/integration/visualizations/pivot_spec.js
  constant SQL (line 5) | const SQL = `
  function createPivotThroughUI (line 19) | function createPivotThroughUI(visualizationName, options = {}) {

FILE: client/cypress/integration/visualizations/sankey_sunburst_spec.js
  constant SQL (line 5) | const SQL = `

FILE: client/cypress/integration/visualizations/table/.mocks/large-dataset.js
  function pseudoRandom (line 5) | function pseudoRandom(seed) {
  function randomString (line 10) | function randomString(index) {

FILE: client/cypress/integration/visualizations/table/table_spec.js
  function prepareVisualization (line 12) | function prepareVisualization(query, type, name, options) {

FILE: client/cypress/integration/visualizations/word_cloud_spec.js
  constant SQL (line 5) | const SQL = `
  function injectFont (line 24) | function injectFont(document) {

FILE: client/cypress/support/dashboard/index.js
  constant RESIZE_HANDLE_SELECTOR (line 4) | const RESIZE_HANDLE_SELECTOR = ".react-resizable-handle";
  function getWidgetTestId (line 6) | function getWidgetTestId(widget) {
  function createQueryAndAddWidget (line 10) | function createQueryAndAddWidget(dashboardId, queryData = {}, widgetOpti...
  function editDashboard (line 21) | function editDashboard() {
  function shareDashboard (line 29) | function shareDashboard() {
  function resizeBy (line 39) | function resizeBy(wrapper, offsetLeft = 0, offsetTop = 0) {

FILE: client/cypress/support/parameters.js
  function dragParam (line 1) | function dragParam(paramName, offsetLeft, offsetTop) {
  function expectParamOrder (line 11) | function expectParamOrder(expectedOrder) {

FILE: client/cypress/support/tags/index.js
  function expectTagsToContain (line 1) | function expectTagsToContain(tags = []) {
  function typeInTagsSelectAndSave (line 9) | function typeInTagsSelectAndSave(text) {

FILE: client/cypress/support/visualizations/chart.js
  function assertPlotPreview (line 5) | function assertPlotPreview(should = "exist") {
  function createChartThroughUI (line 9) | function createChartThroughUI(chartName, chartSpecificAssertionFn = () =...
  function assertTabbedEditor (line 31) | function assertTabbedEditor(chartSpecificTabbedEditorAssertionFn = () =>...
  function assertAxesAndAddLabels (line 48) | function assertAxesAndAddLabels(xaxisLabel, yaxisLabel) {
  function createDashboardWithCharts (line 64) | function createDashboardWithCharts(title, chartGetters, widgetsAssertion...

FILE: client/cypress/support/visualizations/table.js
  function expectTableToHaveLength (line 1) | function expectTableToHaveLength(length) {
  function expectFirstColumnToHaveMembers (line 5) | function expectFirstColumnToHaveMembers(values) {

FILE: migrations/env.py
  function run_migrations_offline (line 32) | def run_migrations_offline():
  function run_migrations_online (line 51) | def run_migrations_online():

FILE: migrations/versions/0ec979123ba4_.py
  function upgrade (line 19) | def upgrade():
  function downgrade (line 25) | def downgrade():

FILE: migrations/versions/0f740a081d20_inline_tags.py
  function upgrade (line 23) | def upgrade():
  function downgrade (line 37) | def downgrade():

FILE: migrations/versions/1038c2174f5d_make_case_insensitive_hash_of_query_text.py
  function change_query_hash (line 22) | def change_query_hash(conn, table, query_text_to):
  function upgrade (line 32) | def upgrade():
  function downgrade (line 43) | def downgrade():

FILE: migrations/versions/1655999df5e3_default_alert_selector.py
  function upgrade (line 18) | def upgrade():
  function downgrade (line 25) | def downgrade():

FILE: migrations/versions/1daa601d3ae5_add_columns_for_disabled_users.py
  function upgrade (line 19) | def upgrade():
  function downgrade (line 23) | def downgrade():

FILE: migrations/versions/5ec5c84ba61e_.py
  function upgrade (line 21) | def upgrade():
  function downgrade (line 34) | def downgrade():

FILE: migrations/versions/640888ce445d_.py
  function upgrade (line 23) | def upgrade():
  function downgrade (line 82) | def downgrade():

FILE: migrations/versions/65fc9ede4746_add_is_draft_status_to_queries_and_.py
  function upgrade (line 21) | def upgrade():
  function downgrade (line 45) | def downgrade():

FILE: migrations/versions/6b5be7e0a0ef_.py
  function upgrade (line 20) | def upgrade():
  function downgrade (line 41) | def downgrade():

FILE: migrations/versions/71477dadd6ef_favorites_unique_constraint.py
  function upgrade (line 19) | def upgrade():
  function downgrade (line 25) | def downgrade():

FILE: migrations/versions/7205816877ec_change_type_of_json_fields_from_varchar_.py
  function upgrade (line 20) | def upgrade():
  function downgrade (line 79) | def downgrade():

FILE: migrations/versions/73beceabb948_bring_back_null_schedule.py
  function is_empty_schedule (line 21) | def is_empty_schedule(schedule):
  function upgrade (line 39) | def upgrade():
  function downgrade (line 56) | def downgrade():

FILE: migrations/versions/7671dca4e604_.py
  function upgrade (line 19) | def upgrade():
  function downgrade (line 26) | def downgrade():

FILE: migrations/versions/7ce5925f832b_create_sqlalchemy_searchable_expressions.py
  function upgrade (line 20) | def upgrade():
  function downgrade (line 24) | def downgrade():

FILE: migrations/versions/89bc7873a3e0_fix_multiple_heads.py
  function upgrade (line 19) | def upgrade():
  function downgrade (line 23) | def downgrade():

FILE: migrations/versions/969126bd800f_.py
  function upgrade (line 23) | def upgrade():
  function downgrade (line 76) | def downgrade():

FILE: migrations/versions/98af61feea92_add_encrypted_options_to_data_sources.py
  function upgrade (line 30) | def upgrade():
  function downgrade (line 63) | def downgrade():

FILE: migrations/versions/9e8c841d1a30_fix_hash.py
  function update_query_hash (line 24) | def update_query_hash(record):
  function upgrade (line 36) | def upgrade():
  function downgrade (line 63) | def downgrade():

FILE: migrations/versions/a92d92aa678e_inline_tags.py
  function upgrade (line 22) | def upgrade():
  function downgrade (line 31) | def downgrade():

FILE: migrations/versions/d1eae8b9893e_.py
  function upgrade (line 19) | def upgrade():
  function downgrade (line 28) | def downgrade():

FILE: migrations/versions/d4c798575877_create_favorites.py
  function upgrade (line 19) | def upgrade():
  function downgrade (line 33) | def downgrade():

FILE: migrations/versions/d7d747033183_encrypt_alert_destinations.py
  function upgrade (line 30) | def upgrade():
  function downgrade (line 63) | def downgrade():

FILE: migrations/versions/db0aca1ebd32_12_column_dashboard_layout.py
  function upgrade (line 19) | def upgrade():
  function downgrade (line 28) | def downgrade():

FILE: migrations/versions/e5c7a4e2df4d_remove_query_tracker_keys.py
  function prune (line 26) | def prune(list_name, keep_count, max_keys=100):
  function prune_all (line 38) | def prune_all(list_name):
  function upgrade (line 44) | def upgrade():
  function downgrade (line 50) | def downgrade():

FILE: migrations/versions/e7004224f284_add_org_id_to_favorites.py
  function upgrade (line 19) | def upgrade():
  function downgrade (line 24) | def downgrade():

FILE: migrations/versions/e7f8a917aa8e_add_user_details_json_column.py
  function upgrade (line 19) | def upgrade():
  function downgrade (line 31) | def downgrade():

FILE: migrations/versions/fd4fc850d7ea_.py
  function upgrade (line 21) | def upgrade():
  function downgrade (line 41) | def downgrade():

FILE: redash/__init__.py
  function setup_logging (line 27) | def setup_logging():

FILE: redash/app.py
  class Redash (line 7) | class Redash(Flask):
    method __init__ (line 10) | def __init__(self, *args, **kwargs):
  function create_app (line 25) | def create_app():

FILE: redash/authentication/__init__.py
  function get_login_url (line 23) | def get_login_url(external=False, next="/"):
  function sign (line 34) | def sign(key, path, expires):
  function load_user (line 45) | def load_user(user_id_with_identity):
  function request_loader (line 63) | def request_loader(request):
  function hmac_load_user_from_request (line 78) | def hmac_load_user_from_request(request):
  function get_user_from_api_key (line 108) | def get_user_from_api_key(api_key, query_id):
  function get_api_key_from_request (line 138) | def get_api_key_from_request(request):
  function api_key_load_user_from_request (line 153) | def api_key_load_user_from_request(request):
  function jwt_token_load_user_from_request (line 164) | def jwt_token_load_user_from_request(request):
  function log_user_logged_in (line 202) | def log_user_logged_in(app, user):
  function redirect_to_login (line 217) | def redirect_to_login():
  function logout_and_redirect_to_index (line 227) | def logout_and_redirect_to_index():
  function init_app (line 240) | def init_app(app):
  function create_and_login_user (line 271) | def create_and_login_user(org, name, email, picture=None):
  function get_next_path (line 301) | def get_next_path(unsafe_next_path):

FILE: redash/authentication/account.py
  function invite_token (line 14) | def invite_token(user):
  function verify_link_for_user (line 18) | def verify_link_for_user(user):
  function invite_link_for_user (line 25) | def invite_link_for_user(user):
  function reset_link_for_user (line 32) | def reset_link_for_user(user):
  function validate_token (line 39) | def validate_token(token):
  function send_verify_email (line 44) | def send_verify_email(user, org):
  function send_invite_email (line 53) | def send_invite_email(inviter, invited, invite_url, org):
  function send_password_reset_email (line 62) | def send_password_reset_email(user):
  function send_user_disabled_email (line 73) | def send_user_disabled_email(user):

FILE: redash/authentication/google_oauth.py
  function verify_profile (line 16) | def verify_profile(org, profile):
  function get_user_profile (line 32) | def get_user_profile(access_token, logger):
  function build_redirect_uri (line 43) | def build_redirect_uri():
  function build_next_path (line 48) | def build_next_path(org_slug=None):
  function create_google_oauth_blueprint (line 67) | def create_google_oauth_blueprint(app):

FILE: redash/authentication/jwt_auth.py
  function get_public_key_from_file (line 12) | def get_public_key_from_file(url):
  function get_public_key_from_net (line 21) | def get_public_key_from_net(url):
  function get_public_keys (line 38) | def get_public_keys(url):
  function verify_jwt_token (line 58) | def verify_jwt_token(jwt_token, expected_issuer, expected_audience, algo...

FILE: redash/authentication/ldap_auth.py
  function login (line 33) | def login(org_slug=None):
  function auth_ldap_user (line 72) | def auth_ldap_user(username, password):

FILE: redash/authentication/org_resolving.py
  function _get_current_org (line 9) | def _get_current_org():

FILE: redash/authentication/remote_user_auth.py
  function login (line 20) | def login(org_slug=None):

FILE: redash/authentication/saml_auth.py
  function get_saml_client (line 24) | def get_saml_client(org):
  function idp_initiated (line 110) | def idp_initiated(org_slug=None):
  function sp_initiated (line 150) | def sp_initiated(org_slug=None):

FILE: redash/cli/__init__.py
  function create (line 21) | def create():
  function manager (line 34) | def manager():
  function version (line 49) | def version():
  function status (line 55) | def status():
  function check_settings (line 61) | def check_settings():
  function send_test_mail (line 69) | def send_test_mail(email=None):
  function shell (line 85) | def shell():

FILE: redash/cli/data_sources.py
  function list_command (line 26) | def list_command(organization=None):
  function list_types (line 41) | def list_types():
  function validate_data_source_type (line 49) | def validate_data_source_type(type):
  function test (line 68) | def test(name, organization="default"):
  function new (line 98) | def new(name=None, type=None, options=None, organization="default"):
  function delete (line 182) | def delete(name, organization="default"):
  function update_attr (line 197) | def update_attr(obj, attr, new_value):
  function edit (line 215) | def edit(name, new_name=None, options=None, type=None, organization="def...

FILE: redash/cli/database.py
  function _wait_for_db_connection (line 21) | def _wait_for_db_connection(db):
  function is_db_empty (line 33) | def is_db_empty():
  function load_extensions (line 40) | def load_extensions(db):
  function create_tables (line 47) | def create_tables():
  function drop_tables (line 67) | def drop_tables():
  function reencrypt (line 79) | def reencrypt(old_secret, new_secret, show_sql):

FILE: redash/cli/groups.py
  function create (line 29) | def create(name, permissions=None, organization="default"):
  function change_permissions (line 57) | def change_permissions(group_id, permissions=None):
  function extract_permissions_string (line 79) | def extract_permissions_string(permissions):
  function list_command (line 95) | def list_command(organization=None):

FILE: redash/cli/organization.py
  function set_google_apps_domains (line 11) | def set_google_apps_domains(domains):
  function show_google_apps_domains (line 24) | def show_google_apps_domains():
  function create (line 37) | def create(name, slug="default"):
  function list_command (line 49) | def list_command():

FILE: redash/cli/queries.py
  function rehash (line 9) | def rehash():
  function add_tag (line 27) | def add_tag(query_id, tag):
  function remove_tag (line 53) | def remove_tag(query_id, tag):

FILE: redash/cli/rq.py
  function scheduler (line 26) | def scheduler():
  function worker (line 34) | def worker(queues):
  class WorkerHealthcheck (line 50) | class WorkerHealthcheck(base.BaseCheck):
    method __call__ (line 53) | def __call__(self, process_spec):
  function healthcheck (line 92) | def healthcheck():

FILE: redash/cli/users.py
  function build_groups (line 15) | def build_groups(org, groups, is_admin):
  function grant_admin (line 38) | def grant_admin(email, organization="default"):
  function create (line 87) | def create(
  function create_root (line 142) | def create_root(email, name, google_auth=False, password=None, organizat...
  function delete (line 200) | def delete(email, organization=None):
  function password (line 222) | def password(email, password, organization=None):
  function invite (line 259) | def invite(email, name, inviter_email, groups, is_admin=False, organizat...
  function list_command (line 290) | def list_command(organization=None, as_json=False):

FILE: redash/destinations/__init__.py
  class BaseDestination (line 8) | class BaseDestination:
    method __init__ (line 11) | def __init__(self, configuration):
    method name (line 15) | def name(cls):
    method type (line 19) | def type(cls):
    method icon (line 23) | def icon(cls):
    method enabled (line 27) | def enabled(cls):
    method configuration_schema (line 31) | def configuration_schema(cls):
    method notify (line 34) | def notify(self, alert, query, user, new_state, app, host, metadata, o...
    method to_dict (line 38) | def to_dict(cls):
  function register (line 51) | def register(destination_class):
  function get_destination (line 67) | def get_destination(destination_type, configuration):
  function get_configuration_schema_for_destination_type (line 74) | def get_configuration_schema_for_destination_type(destination_type):
  function import_destinations (line 82) | def import_destinations(destination_imports):

FILE: redash/destinations/asana.py
  class Asana (line 10) | class Asana(BaseDestination):
    method configuration_schema (line 12) | def configuration_schema(cls):
    method icon (line 24) | def icon(cls):
    method api_base_url (line 28) | def api_base_url(self):
    method notify (line 31) | def notify(self, alert, query, user, new_state, app, host, metadata, o...

FILE: redash/destinations/chatwork.py
  class ChatWork (line 8) | class ChatWork(BaseDestination):
    method configuration_schema (line 12) | def configuration_schema(cls):
    method icon (line 29) | def icon(cls):
    method notify (line 32) | def notify(self, alert, query, user, new_state, app, host, metadata, o...

FILE: redash/destinations/datadog.py
  class Datadog (line 10) | class Datadog(BaseDestination):
    method configuration_schema (line 12) | def configuration_schema(cls):
    method icon (line 27) | def icon(cls):
    method notify (line 30) | def notify(self, alert, query, user, new_state, app, host, metadata, o...

FILE: redash/destinations/discord.py
  class Discord (line 17) | class Discord(BaseDestination):
    method configuration_schema (line 19) | def configuration_schema(cls):
    method icon (line 28) | def icon(cls):
    method notify (line 31) | def notify(self, alert, query, user, new_state, app, host, metadata, o...

FILE: redash/destinations/email.py
  class Email (line 9) | class Email(BaseDestination):
    method configuration_schema (line 11) | def configuration_schema(cls):
    method icon (line 27) | def icon(cls):
    method notify (line 30) | def notify(self, alert, query, user, new_state, app, host, metadata, o...

FILE: redash/destinations/hangoutschat.py
  class HangoutsChat (line 9) | class HangoutsChat(BaseDestination):
    method name (line 11) | def name(cls):
    method type (line 15) | def type(cls):
    method configuration_schema (line 19) | def configuration_schema(cls):
    method icon (line 37) | def icon(cls):
    method notify (line 40) | def notify(self, alert, query, user, new_state, app, host, metadata, o...

FILE: redash/destinations/mattermost.py
  class Mattermost (line 9) | class Mattermost(BaseDestination):
    method configuration_schema (line 11) | def configuration_schema(cls):
    method icon (line 24) | def icon(cls):
    method notify (line 27) | def notify(self, alert, query, user, new_state, app, host, metadata, o...

FILE: redash/destinations/microsoft_teams_webhook.py
  function json_string_substitute (line 10) | def json_string_substitute(j, substitutions):
  class MicrosoftTeamsWebhook (line 28) | class MicrosoftTeamsWebhook(BaseDestination):
    method name (line 51) | def name(cls):
    method type (line 55) | def type(cls):
    method configuration_schema (line 59) | def configuration_schema(cls):
    method icon (line 74) | def icon(cls):
    method notify (line 77) | def notify(self, alert, query, user, new_state, app, host, metadata, o...

FILE: redash/destinations/pagerduty.py
  class PagerDuty (line 13) | class PagerDuty(BaseDestination):
    method enabled (line 18) | def enabled(cls):
    method configuration_schema (line 22) | def configuration_schema(cls):
    method icon (line 40) | def icon(cls):
    method notify (line 43) | def notify(self, alert, query, user, new_state, app, host, metadata, o...

FILE: redash/destinations/slack.py
  class Slack (line 9) | class Slack(BaseDestination):
    method configuration_schema (line 11) | def configuration_schema(cls):
    method icon (line 21) | def icon(cls):
    method notify (line 24) | def notify(self, alert, query, user, new_state, app, host, metadata, o...

FILE: redash/destinations/webex.py
  class Webex (line 12) | class Webex(BaseDestination):
    method configuration_schema (line 14) | def configuration_schema(cls):
    method icon (line 33) | def icon(cls):
    method api_base_url (line 37) | def api_base_url(self):
    method formatted_attachments_template (line 41) | def formatted_attachments_template(subject, description, query_link, a...
    method notify (line 177) | def notify(self, alert, query, user, new_state, app, host, metadata, o...
    method post_message (line 215) | def post_message(self, payload, headers):

FILE: redash/destinations/webhook.py
  class Webhook (line 11) | class Webhook(BaseDestination):
    method configuration_schema (line 13) | def configuration_schema(cls):
    method icon (line 26) | def icon(cls):
    method notify (line 29) | def notify(self, alert, query, user, new_state, app, host, metadata, o...

FILE: redash/handlers/__init__.py
  function ping (line 13) | def ping():
  function status_api (line 20) | def status_api():
  function init_app (line 25) | def init_app(app):

FILE: redash/handlers/admin.py
  function outdated_queries (line 16) | def outdated_queries():
  function queries_rq_status (line 47) | def queries_rq_status():

FILE: redash/handlers/alerts.py
  class AlertResource (line 23) | class AlertResource(BaseResource):
    method get (line 24) | def get(self, alert_id):
    method post (line 30) | def post(self, alert_id):
    method delete (line 43) | def delete(self, alert_id):
  class AlertEvaluateResource (line 50) | class AlertEvaluateResource(BaseResource):
    method post (line 51) | def post(self, alert_id):
  class AlertMuteResource (line 65) | class AlertMuteResource(BaseResource):
    method post (line 66) | def post(self, alert_id):
    method delete (line 75) | def delete(self, alert_id):
  class AlertListResource (line 85) | class AlertListResource(BaseResource):
    method post (line 86) | def post(self):
    method get (line 110) | def get(self):
  class AlertSubscriptionListResource (line 115) | class AlertSubscriptionListResource(BaseResource):
    method post (line 116) | def post(self, alert_id):
    method get (line 143) | def get(self, alert_id):
  class AlertSubscriptionResource (line 151) | class AlertSubscriptionResource(BaseResource):
    method delete (line 152) | def delete(self, alert_id, subscriber_id):

FILE: redash/handlers/api.py
  class ApiExt (line 100) | class ApiExt(Api):
    method add_org_resource (line 101) | def add_org_resource(self, resource, *urls, **kwargs):
  function json_representation (line 110) | def json_representation(data, code, headers=None):

FILE: redash/handlers/authentication.py
  function get_google_auth_url (line 23) | def get_google_auth_url(next_path):
  function render_token_login_page (line 31) | def render_token_login_page(template, org_slug, token, invite):
  function invite (line 110) | def invite(token, org_slug=None):
  function reset (line 115) | def reset(token, org_slug=None):
  function verify (line 120) | def verify(token, org_slug=None):
  function forgot_password (line 147) | def forgot_password(org_slug=None):
  function verification_email (line 169) | def verification_email(org_slug=None):
  function login (line 178) | def login(org_slug=None):
  function logout (line 224) | def logout(org_slug=None):
  function base_href (line 229) | def base_href():
  function date_time_format_config (line 238) | def date_time_format_config():
  function number_format_config (line 251) | def number_format_config():
  function null_value_config (line 258) | def null_value_config():
  function client_config (line 264) | def client_config():
  function messages (line 304) | def messages():
  function config (line 317) | def config(org_slug=None):
  function session (line 323) | def session(org_slug=None):

FILE: redash/handlers/base.py
  class BaseResource (line 21) | class BaseResource(Resource):
    method __init__ (line 24) | def __init__(self, *args, **kwargs):
    method dispatch_request (line 28) | def dispatch_request(self, *args, **kwargs):
    method current_user (line 34) | def current_user(self):
    method current_org (line 38) | def current_org(self):
    method record_event (line 41) | def record_event(self, options):
    method update_model (line 45) | def update_model(self, model, updates):
  function record_event (line 50) | def record_event(org, user, options):
  function require_fields (line 64) | def require_fields(req, fields):
  function get_object_or_404 (line 70) | def get_object_or_404(fn, *args, **kwargs):
  function paginate (line 80) | def paginate(query_set, page, page_size, serializer, **kwargs):
  function org_scoped_rule (line 103) | def org_scoped_rule(rule):
  function json_response (line 110) | def json_response(response):
  function filter_by_tags (line 114) | def filter_by_tags(result_set, column):
  function order_results (line 121) | def order_results(results, default_order, allowed_orders, fallback=True):

FILE: redash/handlers/dashboards.py
  class DashboardListResource (line 36) | class DashboardListResource(BaseResource):
    method get (line 38) | def get(self):
    method post (line 87) | def post(self):
  class MyDashboardsResource (line 108) | class MyDashboardsResource(BaseResource):
    method get (line 110) | def get(self):
  class DashboardResource (line 140) | class DashboardResource(BaseResource):
    method get (line 142) | def get(self, dashboard_id=None):
    method post (line 202) | def post(self, dashboard_id):
    method delete (line 255) | def delete(self, dashboard_id):
  class PublicDashboardResource (line 275) | class PublicDashboardResource(BaseResource):
    method get (line 278) | def get(self, token):
  class DashboardShareResource (line 297) | class DashboardShareResource(BaseResource):
    method post (line 298) | def post(self, dashboard_id):
    method delete (line 329) | def delete(self, dashboard_id):
  class DashboardTagsResource (line 353) | class DashboardTagsResource(BaseResource):
    method get (line 355) | def get(self):
  class DashboardFavoriteListResource (line 363) | class DashboardFavoriteListResource(BaseResource):
    method get (line 364) | def get(self):
  class DashboardForkResource (line 405) | class DashboardForkResource(BaseResource):
    method post (line 407) | def post(self, dashboard_id):

FILE: redash/handlers/data_sources.py
  class DataSourceTypeListResource (line 31) | class DataSourceTypeListResource(BaseResource):
    method get (line 33) | def get(self):
  class DataSourceResource (line 37) | class DataSourceResource(BaseResource):
    method get (line 38) | def get(self, data_source_id):
    method post (line 53) | def post(self, data_source_id):
    method delete (line 86) | def delete(self, data_source_id):
  class DataSourceListResource (line 101) | class DataSourceListResource(BaseResource):
    method get (line 103) | def get(self):
    method post (line 132) | def post(self):
  class DataSourceSchemaResource (line 170) | class DataSourceSchemaResource(BaseResource):
    method get (line 171) | def get(self, data_source_id):
  class DataSourcePauseResource (line 187) | class DataSourcePauseResource(BaseResource):
    method post (line 189) | def post(self, data_source_id):
    method delete (line 209) | def delete(self, data_source_id):
  class DataSourceTestResource (line 223) | class DataSourceTestResource(BaseResource):
    method post (line 225) | def post(self, data_source_id):

FILE: redash/handlers/databricks.py
  function _get_databricks_data_source (line 17) | def _get_databricks_data_source(data_source_id, user, org):
  function _databases_key (line 27) | def _databases_key(data_source_id):
  function _tables_key (line 31) | def _tables_key(data_source_id, database_name):
  function _get_databases_from_cache (line 35) | def _get_databases_from_cache(data_source_id):
  function _get_tables_from_cache (line 40) | def _get_tables_from_cache(data_source_id, database_name):
  class DatabricksDatabaseListResource (line 45) | class DatabricksDatabaseListResource(BaseResource):
    method get (line 46) | def get(self, data_source_id):
  class DatabricksSchemaResource (line 60) | class DatabricksSchemaResource(BaseResource):
    method get (line 61) | def get(self, data_source_id, database_name):
  class DatabricksTableColumnListResource (line 80) | class DatabricksTableColumnListResource(BaseResource):
    method get (line 81) | def get(self, data_source_id, database_name, table_name):

FILE: redash/handlers/destinations.py
  class DestinationTypeListResource (line 15) | class DestinationTypeListResource(BaseResource):
    method get (line 17) | def get(self):
  class DestinationResource (line 21) | class DestinationResource(BaseResource):
    method get (line 23) | def get(self, destination_id):
    method post (line 36) | def post(self, destination_id):
    method delete (line 64) | def delete(self, destination_id):
  class DestinationListResource (line 80) | class DestinationListResource(BaseResource):
    method get (line 81) | def get(self):
    method post (line 103) | def post(self):

FILE: redash/handlers/embed.py
  function embed (line 23) | def embed(query_id, visualization_id, org_slug=None):
  function public_dashboard (line 42) | def public_dashboard(token, org_slug=None):

FILE: redash/handlers/events.py
  function get_location (line 10) | def get_location(ip):
  function event_details (line 22) | def event_details(event):
  function serialize_event (line 36) | def serialize_event(event):
  class EventsResource (line 59) | class EventsResource(BaseResource):
    method post (line 60) | def post(self):
    method get (line 66) | def get(self):

FILE: redash/handlers/favorites.py
  class QueryFavoriteResource (line 8) | class QueryFavoriteResource(BaseResource):
    method post (line 9) | def post(self, query_id):
    method delete (line 26) | def delete(self, query_id):
  class DashboardFavoriteResource (line 40) | class DashboardFavoriteResource(BaseResource):
    method post (line 41) | def post(self, object_id):
    method delete (line 62) | def delete(self, object_id):

FILE: redash/handlers/groups.py
  class GroupListResource (line 9) | class GroupListResource(BaseResource):
    method post (line 11) | def post(self):
    method get (line 21) | def get(self):
  class GroupResource (line 32) | class GroupResource(BaseResource):
    method post (line 34) | def post(self, group_id):
    method get (line 47) | def get(self, group_id):
    method delete (line 58) | def delete(self, group_id):
  class GroupMemberListResource (line 72) | class GroupMemberListResource(BaseResource):
    method post (line 74) | def post(self, group_id):
    method get (line 92) | def get(self, group_id):
  class GroupMemberResource (line 100) | class GroupMemberResource(BaseResource):
    method delete (line 102) | def delete(self, group_id, user_id):
  function serialize_data_source_with_group (line 117) | def serialize_data_source_with_group(data_source, data_source_group):
  class GroupDataSourceListResource (line 123) | class GroupDataSourceListResource(BaseResource):
    method post (line 125) | def post(self, group_id):
    method get (line 145) | def get(self, group_id):
  class GroupDataSourceResource (line 158) | class GroupDataSourceResource(BaseResource):
    method post (line 160) | def post(self, group_id, data_source_id):
    method delete (line 181) | def delete(self, group_id, data_source_id):

FILE: redash/handlers/organization.py
  function organization_status (line 11) | def organization_status(org_slug=None):

FILE: redash/handlers/permissions.py
  function get_model_from_type (line 14) | def get_model_from_type(type):
  class ObjectPermissionsListResource (line 21) | class ObjectPermissionsListResource(BaseResource):
    method get (line 22) | def get(self, object_type, object_id):
    method post (line 36) | def post(self, object_type, object_id):
    method delete (line 69) | def delete(self, object_type, object_id):
  class CheckPermissionResource (line 97) | class CheckPermissionResource(BaseResource):
    method get (line 98) | def get(self, object_type, object_id, access_type):

FILE: redash/handlers/queries.py
  function format_sql_query (line 56) | def format_sql_query(org_slug=None):
  class QuerySearchResource (line 69) | class QuerySearchResource(BaseResource):
    method get (line 71) | def get(self):
  class QueryRecentResource (line 98) | class QueryRecentResource(BaseResource):
    method get (line 100) | def get(self):
  class BaseQueryListResource (line 111) | class BaseQueryListResource(BaseResource):
    method get_queries (line 112) | def get_queries(self, search_term):
    method get (line 126) | def get(self):
  function require_access_to_dropdown_queries (line 169) | def require_access_to_dropdown_queries(user, query_def):
  class QueryListResource (line 186) | class QueryListResource(BaseQueryListResource):
    method post (line 188) | def post(self):
  class QueryArchiveResource (line 252) | class QueryArchiveResource(BaseQueryListResource):
    method get_queries (line 253) | def get_queries(self, search_term):
  class MyQueriesResource (line 272) | class MyQueriesResource(BaseResource):
    method get (line 274) | def get(self):
  class QueryResource (line 314) | class QueryResource(BaseResource):
    method post (line 316) | def post(self, query_id):
    method get (line 377) | def get(self, query_id):
    method delete (line 396) | def delete(self, query_id):
  class QueryRegenerateApiKeyResource (line 408) | class QueryRegenerateApiKeyResource(BaseResource):
    method post (line 410) | def post(self, query_id):
  class QueryForkResource (line 428) | class QueryForkResource(BaseResource):
    method post (line 430) | def post(self, query_id):
  class QueryRefreshResource (line 448) | class QueryRefreshResource(BaseResource):
    method post (line 449) | def post(self, query_id):
  class QueryTagsResource (line 472) | class QueryTagsResource(BaseResource):
    method get (line 473) | def get(self):
  class QueryFavoriteListResource (line 481) | class QueryFavoriteListResource(BaseResource):
    method get (line 482) | def get(self):

FILE: redash/handlers/query_results.py
  function error_response (line 40) | def error_response(message, http_status=400):
  function run_query (line 59) | def run_query(query, parameters, data_source, query_id, should_apply_aut...
  function get_download_filename (line 116) | def get_download_filename(query_result, query, filetype):
  function content_disposition_filenames (line 126) | def content_disposition_filenames(attachment_filename):
  class QueryResultListResource (line 143) | class QueryResultListResource(BaseResource):
    method post (line 145) | def post(self):
  class QueryResultDropdownResource (line 194) | class QueryResultDropdownResource(BaseResource):
    method get (line 195) | def get(self, query_id):
  class QueryDropdownsResource (line 204) | class QueryDropdownsResource(BaseResource):
    method get (line 205) | def get(self, query_id, dropdown_query_id):
  class QueryResultResource (line 217) | class QueryResultResource(BaseResource):
    method add_cors_headers (line 219) | def add_cors_headers(headers):
    method options (line 228) | def options(self, query_id=None, query_result_id=None, filetype="json"):
    method post (line 241) | def post(self, query_id):
    method get (line 288) | def get(self, query_id=None, query_result_id=None, filetype="json"):
    method make_json_response (line 378) | def make_json_response(query_result):
    method make_csv_response (line 384) | def make_csv_response(query_result):
    method make_tsv_response (line 389) | def make_tsv_response(query_result):
    method make_excel_response (line 394) | def make_excel_response(query_result):
  class JobResource (line 399) | class JobResource(BaseResource):
    method get (line 400) | def get(self, job_id, query_id=None):
    method delete (line 407) | def delete(self, job_id):

FILE: redash/handlers/query_snippets.py
  class QuerySnippetResource (line 13) | class QuerySnippetResource(BaseResource):
    method get (line 14) | def get(self, snippet_id):
    method post (line 21) | def post(self, snippet_id):
    method delete (line 33) | def delete(self, snippet_id):
  class QuerySnippetListResource (line 48) | class QuerySnippetListResource(BaseResource):
    method post (line 49) | def post(self):
    method get (line 74) | def get(self):

FILE: redash/handlers/settings.py
  function get_settings_with_defaults (line 9) | def get_settings_with_defaults(defaults, org):
  class OrganizationSettings (line 28) | class OrganizationSettings(BaseResource):
    method get (line 30) | def get(self):
    method post (line 36) | def post(self):

FILE: redash/handlers/setup.py
  class SetupForm (line 13) | class SetupForm(Form):
  function create_org (line 22) | def create_org(org_name, user_name, email, password):
  function setup (line 55) | def setup():

FILE: redash/handlers/static.py
  function render_index (line 12) | def render_index():
  function dashboard (line 25) | def dashboard(slug, org_slug=None):
  function index (line 32) | def index(**kwargs):

FILE: redash/handlers/users.py
  function invite_user (line 47) | def invite_user(org, inviter, user, send_email=True):
  function require_allowed_email (line 59) | def require_allowed_email(email):
  class UserListResource (line 67) | class UserListResource(BaseResource):
    method get_users (line 70) | def get_users(self, disabled, pending, search_term):
    method get (line 98) | def get(self):
    method post (line 131) | def post(self):
  class UserInviteResource (line 161) | class UserInviteResource(BaseResource):
    method post (line 163) | def post(self, user_id):
  class UserResetPasswordResource (line 168) | class UserResetPasswordResource(BaseResource):
    method post (line 170) | def post(self, user_id):
  class UserRegenerateApiKeyResource (line 179) | class UserRegenerateApiKeyResource(BaseResource):
    method post (line 180) | def post(self, user_id):
  class UserResource (line 195) | class UserResource(BaseResource):
    method get (line 198) | def get(self, user_id):
    method post (line 206) | def post(self, user_id):  # noqa: C901
    method delete (line 277) | def delete(self, user_id):
  class UserDisableResource (line 299) | class UserDisableResource(BaseResource):
    method post (line 301) | def post(self, user_id):
    method delete (line 317) | def delete(self, user_id):

FILE: redash/handlers/visualizations.py
  class VisualizationListResource (line 12) | class VisualizationListResource(BaseResource):
    method post (line 14) | def post(self):
  class VisualizationResource (line 28) | class VisualizationResource(BaseResource):
    method post (line 30) | def post(self, visualization_id):
    method delete (line 45) | def delete(self, visualization_id):

FILE: redash/handlers/webpack.py
  function configure_webpack (line 9) | def configure_webpack(app):

FILE: redash/handlers/widgets.py
  class WidgetListResource (line 14) | class WidgetListResource(BaseResource):
    method post (line 16) | def post(self):
  class WidgetResource (line 50) | class WidgetResource(BaseResource):
    method post (line 52) | def post(self, widget_id):
    method delete (line 70) | def delete(self, widget_id):

FILE: redash/metrics/database.py
  function _table_name_from_select_element (line 15) | def _table_name_from_select_element(elt):
  function before_execute (line 28) | def before_execute(conn, elt, multiparams, params):
  function after_execute (line 33) | def after_execute(conn, elt, multiparams, params, result):

FILE: redash/metrics/request.py
  function record_request_start_time (line 12) | def record_request_start_time():
  function calculate_metrics (line 16) | def calculate_metrics(response):
  function calculate_metrics_on_exception (line 46) | def calculate_metrics_on_exception(error):
  function init_app (line 51) | def init_app(app):

FILE: redash/models/__init__.py
  class ScheduledQueriesExecutions (line 88) | class ScheduledQueriesExecutions:
    method __init__ (line 91) | def __init__(self):
    method refresh (line 94) | def refresh(self):
    method update (line 97) | def update(self, query_id):
    method get (line 100) | def get(self, query_id):
  class DataSource (line 112) | class DataSource(BelongsToOrgMixin, db.Model):
    method __eq__ (line 136) | def __eq__(self, other):
    method __hash__ (line 139) | def __hash__(self):
    method to_dict (line 142) | def to_dict(self, all=False, with_permissions_for=None):
    method __str__ (line 173) | def __str__(self):
    method create_with_group (line 177) | def create_with_group(cls, *args, **kwargs):
    method all (line 184) | def all(cls, org, group_ids=None):
    method get_by_id (line 193) | def get_by_id(cls, _id):
    method delete (line 196) | def delete(self):
    method get_cached_schema (line 206) | def get_cached_schema(self):
    method get_schema (line 210) | def get_schema(self, refresh=False):
    method _sort_schema (line 230) | def _sort_schema(self, schema):
    method _schema_key (line 237) | def _schema_key(self):
    method _pause_key (line 241) | def _pause_key(self):
    method paused (line 245) | def paused(self):
    method pause_reason (line 249) | def pause_reason(self):
    method pause (line 252) | def pause(self, reason=None):
    method resume (line 255) | def resume(self):
    method add_group (line 258) | def add_group(self, group, view_only=False):
    method remove_group (line 263) | def remove_group(self, group):
    method update_group_permission (line 267) | def update_group_permission(self, group, view_only):
    method uses_ssh_tunnel (line 274) | def uses_ssh_tunnel(self):
    method query_runner (line 278) | def query_runner(self):
    method get_by_name (line 287) | def get_by_name(cls, name):
    method groups (line 292) | def groups(self):
  class DataSourceGroup (line 298) | class DataSourceGroup(db.Model):
  class QueryResult (line 312) | class QueryResult(db.Model, BelongsToOrgMixin):
    method __str__ (line 326) | def __str__(self):
    method to_dict (line 329) | def to_dict(self):
    method unused (line 341) | def unused(cls, days=7):
    method get_latest (line 348) | def get_latest(cls, data_source, query, max_age=0):
    method store_result (line 369) | def store_result(cls, org, data_source, query_hash, query, data, run_t...
    method groups (line 386) | def groups(self):
  function should_schedule_next (line 390) | def should_schedule_next(previous_iteration, now, interval, time=None, d...
  class Query (line 446) | class Query(ChangeTrackingMixin, TimestampMixin, BelongsToOrgMixin, db.M...
    method __str__ (line 487) | def __str__(self):
    method archive (line 490) | def archive(self, user=None):
    method regenerate_api_key (line 505) | def regenerate_api_key(self):
    method create (line 509) | def create(cls, **kwargs):
    method all_queries (line 523) | def all_queries(cls, group_ids, user_id=None, include_drafts=False, in...
    method favorites (line 547) | def favorites(cls, user, base_query=None):
    method all_tags (line 558) | def all_tags(cls, user, include_drafts=False):
    method by_user (line 573) | def by_user(cls, user):
    method by_api_key (line 577) | def by_api_key(cls, api_key):
    method past_scheduled_queries (line 581) | def past_scheduled_queries(cls):
    method outdated_queries (line 593) | def outdated_queries(cls):
    method _do_multi_byte_search (line 649) | def _do_multi_byte_search(cls, all_queries, term, limit=None):
    method search (line 686) | def search(
    method search_by_user (line 711) | def search_by_user(cls, term, user, limit=None, multi_byte_search=False):
    method recent (line 719) | def recent(cls, group_ids, user_id=None, limit=20):
    method get_by_id (line 744) | def get_by_id(cls, _id):
    method all_groups_for_query_ids (line 748) | def all_groups_for_query_ids(cls, query_ids):
    method update_latest_result_by_query_hash (line 756) | def update_latest_result_by_query_hash(self):
    method update_latest_result (line 774) | def update_latest_result(cls, query_result):
    method fork (line 797) | def fork(self, user):
    method runtime (line 823) | def runtime(self):
    method retrieved_at (line 827) | def retrieved_at(self):
    method groups (line 831) | def groups(self):
    method lowercase_name (line 838) | def lowercase_name(self):
    method lowercase_name (line 843) | def lowercase_name(cls):
    method parameters (line 848) | def parameters(self):
    method parameterized (line 852) | def parameterized(self):
    method dashboard_api_keys (line 856) | def dashboard_api_keys(self):
    method update_query_hash (line 869) | def update_query_hash(self):
  function receive_before_insert_update (line 890) | def receive_before_insert_update(mapper, connection, target):
  function query_last_modified_by (line 895) | def query_last_modified_by(target, val, oldval, initiator):
  class Favorite (line 900) | class Favorite(TimestampMixin, db.Model):
    method is_favorite (line 915) | def is_favorite(cls, user, object):
    method are_favorites (line 919) | def are_favorites(cls, user, objects):
  function next_state (line 949) | def next_state(op, value, threshold):
  class Alert (line 982) | class Alert(TimestampMixin, BelongsToOrgMixin, db.Model):
    method all (line 1003) | def all(cls, group_ids):
    method get_by_id_and_org (line 1012) | def get_by_id_and_org(cls, object_id, org):
    method evaluate (line 1015) | def evaluate(self):
    method subscribers (line 1051) | def subscribers(self):
    method render_template (line 1054) | def render_template(self, template):
    method custom_body (line 1087) | def custom_body(self):
    method custom_subject (line 1092) | def custom_subject(self):
    method groups (line 1097) | def groups(self):
    method muted (line 1101) | def muted(self):
  function generate_slug (line 1105) | def generate_slug(ctx):
  class Dashboard (line 1116) | class Dashboard(ChangeTrackingMixin, TimestampMixin, BelongsToOrgMixin, ...
    method __str__ (line 1137) | def __str__(self):
    method name_as_slug (line 1141) | def name_as_slug(self):
    method all (line 1145) | def all(cls, org, group_ids, user_id):
    method search (line 1165) | def search(cls, org, groups_ids, user_id, search_term):
    method search_by_user (line 1170) | def search_by_user(cls, term, user, limit=None):
    method all_tags (line 1174) | def all_tags(cls, org, user):
    method favorites (line 1189) | def favorites(cls, user, base_query=None):
    method by_user (line 1207) | def by_user(cls, user):
    method get_by_slug_and_org (line 1211) | def get_by_slug_and_org(cls, slug, org):
    method fork (line 1214) | def fork(self, user):
    method lowercase_name (line 1230) | def lowercase_name(self):
    method lowercase_name (line 1235) | def lowercase_name(cls):
  class Visualization (line 1241) | class Visualization(TimestampMixin, BelongsToOrgMixin, db.Model):
    method __str__ (line 1253) | def __str__(self):
    method get_by_id_and_org (line 1257) | def get_by_id_and_org(cls, object_id, org):
    method copy (line 1260) | def copy(self):
  class Widget (line 1270) | class Widget(TimestampMixin, BelongsToOrgMixin, db.Model):
    method __str__ (line 1281) | def __str__(self):
    method get_by_id_and_org (line 1285) | def get_by_id_and_org(cls, object_id, org):
    method copy (line 1288) | def copy(self, dashboard_id):
  class Event (line 1299) | class Event(db.Model):
    method __str__ (line 1313) | def __str__(self):
    method to_dict (line 1321) | def to_dict(self):
    method record (line 1333) | def record(cls, event):
  class ApiKey (line 1356) | class ApiKey(TimestampMixin, GFKBase, db.Model):
    method get_by_api_key (line 1371) | def get_by_api_key(cls, api_key):
    method get_by_object (line 1375) | def get_by_object(cls, object):
    method create_for_object (line 1383) | def create_for_object(cls, object, user):
  class NotificationDestination (line 1390) | class NotificationDestination(BelongsToOrgMixin, db.Model):
    method __str__ (line 1409) | def __str__(self):
    method to_dict (line 1412) | def to_dict(self, all=False):
    method destination (line 1428) | def destination(self):
    method all (line 1432) | def all(cls, org):
    method notify (line 1437) | def notify(self, alert, query, user, new_state, app, host, metadata):
  class AlertSubscription (line 1444) | class AlertSubscription(TimestampMixin, db.Model):
    method to_dict (line 1465) | def to_dict(self):
    method all (line 1474) | def all(cls, alert_id):
    method notify (line 1477) | def notify(self, alert, query, user, new_state, app, host, metadata):
  class QuerySnippet (line 1490) | class QuerySnippet(TimestampMixin, db.Model, BelongsToOrgMixin):
    method all (line 1503) | def all(cls, org):
    method to_dict (line 1506) | def to_dict(self):
  function init_db (line 1520) | def init_db():

FILE: redash/models/base.py
  class RedashSQLAlchemy (line 13) | class RedashSQLAlchemy(SQLAlchemy):
    method apply_driver_hacks (line 14) | def apply_driver_hacks(self, app, info, options):
    method apply_pool_defaults (line 20) | def apply_pool_defaults(self, app, options):
  class SearchBaseQuery (line 45) | class SearchBaseQuery(BaseQuery, SearchQueryMixin):
  function integer_vectorizer (line 52) | def integer_vectorizer(column):
  function uuid_vectorizer (line 57) | def uuid_vectorizer(column):
  function gfk_type (line 69) | def gfk_type(cls):
  class GFKBase (line 74) | class GFKBase:
    method object (line 85) | def object(self):
    method object (line 95) | def object(self, value):
  function key_type (line 104) | def key_type(name):
  function primary_key (line 108) | def primary_key(name):

FILE: redash/models/changes.py
  class Change (line 9) | class Change(GFKBase, db.Model):
    method to_dict (line 21) | def to_dict(self, full=True):
    method last_change (line 40) | def last_change(cls, obj):
  class ChangeTrackingMixin (line 48) | class ChangeTrackingMixin:
    method __init__ (line 52) | def __init__(self, *a, **kw):
    method prep_cleanvalues (line 56) | def prep_cleanvalues(self):
    method __setattr__ (line 63) | def __setattr__(self, key, value):
    method record_changes (line 73) | def record_changes(self, changed_by):

FILE: redash/models/mixins.py
  class TimestampMixin (line 6) | class TimestampMixin:
  function timestamp_before_update (line 12) | def timestamp_before_update(mapper, connection, target):
  class BelongsToOrgMixin (line 20) | class BelongsToOrgMixin:
    method get_by_id_and_org (line 22) | def get_by_id_and_org(cls, object_id, org, org_cls=None):

FILE: redash/models/organizations.py
  class Organization (line 14) | class Organization(TimestampMixin, db.Model):
    method __str__ (line 27) | def __str__(self):
    method get_by_slug (line 31) | def get_by_slug(cls, slug):
    method get_by_id (line 35) | def get_by_id(cls, _id):
    method default_group (line 39) | def default_group(self):
    method google_apps_domains (line 43) | def google_apps_domains(self):
    method is_public (line 47) | def is_public(self):
    method is_disabled (line 51) | def is_disabled(self):
    method disable (line 54) | def disable(self):
    method enable (line 57) | def enable(self):
    method set_setting (line 60) | def set_setting(self, key, value):
    method get_setting (line 68) | def get_setting(self, key, raise_on_missing=True):
    method admin_group (line 81) | def admin_group(self):
    method has_user (line 84) | def has_user(self, email):

FILE: redash/models/parameterized_query.py
  function _pluck_name_and_value (line 12) | def _pluck_name_and_value(default_column, row):
  function _load_result (line 20) | def _load_result(query_id, org):
  function dropdown_values (line 32) | def dropdown_values(query_id, org):
  function join_parameter_list_values (line 39) | def join_parameter_list_values(parameters, schema):
  function _collect_key_names (line 54) | def _collect_key_names(nodes):
  function _collect_query_parameters (line 66) | def _collect_query_parameters(query):
  function _parameter_names (line 72) | def _parameter_names(parameter_values):
  function _is_number (line 84) | def _is_number(string):
  function _is_regex_pattern (line 92) | def _is_regex_pattern(value, regex):
  function _is_date (line 102) | def _is_date(string):
  function _is_date_range (line 107) | def _is_date_range(obj):
  function _is_value_within_options (line 111) | def _is_value_within_options(value, dropdown_options, allow_list=False):
  class ParameterizedQuery (line 117) | class ParameterizedQuery:
    method __init__ (line 118) | def __init__(self, template, schema=None, org=None):
    method apply (line 125) | def apply(self, parameters):
    method _valid (line 135) | def _valid(self, name, value):
    method is_safe (line 185) | def is_safe(self):
    method missing_params (line 190) | def missing_params(self):
    method text (line 195) | def text(self):
  class InvalidParameterError (line 199) | class InvalidParameterError(Exception):
    method __init__ (line 200) | def __init__(self, parameters):
  class QueryDetachedFromDataSourceError (line 206) | class QueryDetachedFromDataSourceError(Exception):
    method __init__ (line 207) | def __init__(self, query_id):

FILE: redash/models/types.py
  class Configuration (line 12) | class Configuration(TypeDecorator):
    method process_bind_param (line 15) | def process_bind_param(self, value, dialect):
    method process_result_value (line 18) | def process_result_value(self, value, dialect):
  class EncryptedConfiguration (line 22) | class EncryptedConfiguration(EncryptedType):
    method process_bind_param (line 23) | def process_bind_param(self, value, dialect):
    method process_result_value (line 26) | def process_result_value(self, value, dialect):
  class JSONText (line 33) | class JSONText(TypeDecorator):
    method process_bind_param (line 36) | def process_bind_param(self, value, dialect):
    method process_result_value (line 42) | def process_result_value(self, value, dialect):
  class MutableDict (line 48) | class MutableDict(Mutable, dict):
    method coerce (line 50) | def coerce(cls, key, value):
    method __setitem__ (line 62) | def __setitem__(self, key, value):
    method __delitem__ (line 68) | def __delitem__(self, key):
  class MutableList (line 75) | class MutableList(Mutable, list):
    method append (line 76) | def append(self, value):
    method remove (line 80) | def remove(self, value):
    method coerce (line 85) | def coerce(cls, key, value):
  class json_cast_property (line 94) | class json_cast_property(index_property):
    method __init__ (line 101) | def __init__(self, cast_type, *args, **kwargs):
    method expr (line 105) | def expr(self, model):

FILE: redash/models/users.py
  function sync_last_active_at (line 28) | def sync_last_active_at():
  function update_user_active_at (line 46) | def update_user_active_at(sender, *args, **kwargs):
  function init_app (line 55) | def init_app(app):
  class PermissionsCheckMixin (line 63) | class PermissionsCheckMixin:
    method has_permission (line 64) | def has_permission(self, permission):
    method has_permissions (line 67) | def has_permissions(self, permissions):
  class User (line 78) | class User(TimestampMixin, db.Model, BelongsToOrgMixin, UserMixin, Permi...
    method __str__ (line 107) | def __str__(self):
    method __init__ (line 110) | def __init__(self, *args, **kwargs):
    method is_disabled (line 116) | def is_disabled(self):
    method disable (line 119) | def disable(self):
    method enable (line 122) | def enable(self):
    method regenerate_api_key (line 125) | def regenerate_api_key(self):
    method to_dict (line 128) | def to_dict(self, with_api_key=False):
    method is_api_user (line 161) | def is_api_user():
    method profile_image_url (line 165) | def profile_image_url(self):
    method permissions (line 173) | def permissions(self):
    method get_by_org (line 178) | def get_by_org(cls, org):
    method get_by_id (line 182) | def get_by_id(cls, _id):
    method get_by_email_and_org (line 186) | def get_by_email_and_org(cls, email, org):
    method get_by_api_key_and_org (line 190) | def get_by_api_key_and_org(cls, api_key, org):
    method all (line 194) | def all(cls, org):
    method all_disabled (line 198) | def all_disabled(cls, org):
    method search (line 202) | def search(cls, base_query, term):
    method pending (line 209) | def pending(cls, base_query, pending):
    method find_by_email (line 216) | def find_by_email(cls, email):
    method hash_password (line 219) | def hash_password(self, password):
    method verify_password (line 222) | def verify_password(self, password):
    method update_group_assignments (line 225) | def update_group_assignments(self, group_names):
    method has_access (line 232) | def has_access(self, obj, access_type):
    method get_id (line 235) | def get_id(self):
    method get_actual_user (line 241) | def get_actual_user(self):
  class Group (line 246) | class Group(db.Model, BelongsToOrgMixin):
    method __str__ (line 277) | def __str__(self):
    method to_dict (line 280) | def to_dict(self):
    method all (line 290) | def all(cls, org):
    method members (line 294) | def members(cls, group_id):
    method find_by_name (line 298) | def find_by_name(cls, org, group_names):
  class AccessPermission (line 304) | class AccessPermission(GFKBase, db.Model):
    method grant (line 316) | def grant(cls, obj, access_type, grantee, grantor):
    method revoke (line 338) | def revoke(cls, obj, grantee, access_type=None):
    method find (line 343) | def find(cls, obj, access_type=None, grantee=None, grantor=None):
    method exists (line 347) | def exists(cls, obj, access_type, grantee):
    method _query (line 351) | def _query(cls, obj, access_type=None, grantee=None, grantor=None):
    method to_dict (line 365) | def to_dict(self):
  class AnonymousUser (line 377) | class AnonymousUser(AnonymousUserMixin, PermissionsCheckMixin):
    method permissions (line 379) | def permissions(self):
    method is_api_user (line 383) | def is_api_user():
  class ApiUser (line 387) | class ApiUser(UserMixin, PermissionsCheckMixin):
    method __init__ (line 388) | def __init__(self, api_key, org, groups, name=None):
    method __repr__ (line 400) | def __repr__(self):
    method is_api_user (line 404) | def is_api_user():
    method org_id (line 408) | def org_id(self):
    method permissions (line 414) | def permissions(self):
    method has_access (line 418) | def has_access(obj, access_type):
    method get_actual_user (line 421) | def get_actual_user(self):

FILE: redash/monitor.py
  function get_redis_status (line 10) | def get_redis_status():
  function get_object_counts (line 18) | def get_object_counts():
  function get_queues_status (line 29) | def get_queues_status():
  function get_db_sizes (line 33) | def get_db_sizes():
  function get_status (line 49) | def get_status():
  function rq_job_ids (line 61) | def rq_job_ids():
  function fetch_jobs (line 70) | def fetch_jobs(job_ids):
  function rq_queues (line 85) | def rq_queues():
  function describe_job (line 96) | def describe_job(job):
  function rq_workers (line 100) | def rq_workers():
  function rq_status (line 119) | def rq_status():

FILE: redash/permissions.py
  function has_access (line 17) | def has_access(obj, user, need_view_only):
  function has_access_to_object (line 24) | def has_access_to_object(obj, api_key, need_view_only):
  function has_access_to_groups (line 34) | def has_access_to_groups(obj, user, need_view_only):
  function require_access (line 52) | def require_access(obj, user, need_view_only):
  class require_permissions (line 57) | class require_permissions:
    method __init__ (line 58) | def __init__(self, permissions, allow_one=False):
    method __call__ (line 62) | def __call__(self, fn):
  function require_permission (line 78) | def require_permission(permission):
  function require_any_of_permission (line 82) | def require_any_of_permission(permissions):
  function require_admin (line 86) | def require_admin(fn):
  function require_super_admin (line 90) | def require_super_admin(fn):
  function has_permission_or_owner (line 94) | def has_permission_or_owner(permission, object_owner_id):
  function is_admin_or_owner (line 98) | def is_admin_or_owner(object_owner_id):
  function require_permission_or_owner (line 102) | def require_permission_or_owner(permission, object_owner_id):
  function require_admin_or_owner (line 107) | def require_admin_or_owner(object_owner_id):
  function can_modify (line 112) | def can_modify(obj, user):
  function require_object_modify_permission (line 116) | def require_object_modify_permission(obj, user):

FILE: redash/query_runner/__init__.py
  function split_sql_statements (line 50) | def split_sql_statements(query):
  function combine_sql_statements (line 97) | def combine_sql_statements(queries):
  function find_last_keyword_idx (line 101) | def find_last_keyword_idx(parsed_query):
  class InterruptException (line 108) | class InterruptException(Exception):
  class NotSupported (line 112) | class NotSupported(Exception):
  class BaseQueryRunner (line 116) | class BaseQueryRunner:
    method __init__ (line 124) | def __init__(self, configuration):
    method name (line 129) | def name(cls):
    method type (line 133) | def type(cls):
    method enabled (line 137) | def enabled(cls):
    method host (line 141) | def host(self):
    method host (line 154) | def host(self, host):
    method port (line 167) | def port(self):
    method port (line 180) | def port(self, port):
    method configuration_schema (line 193) | def configuration_schema(cls):
    method annotate_query (line 196) | def annotate_query(self, query, metadata):
    method test_connection (line 204) | def test_connection(self):
    method run_query (line 212) | def run_query(self, query, user):
    method fetch_columns (line 215) | def fetch_columns(self, columns):
    method get_schema (line 231) | def get_schema(self, get_stats=False):
    method _handle_run_query_error (line 234) | def _handle_run_query_error(self, error):
    method _run_query_internal (line 241) | def _run_query_internal(self, query):
    method to_dict (line 249) | def to_dict(cls):
    method supports_auto_limit (line 258) | def supports_auto_limit(self):
    method apply_auto_limit (line 261) | def apply_auto_limit(self, query_text, should_apply_auto_limit):
    method gen_query_hash (line 264) | def gen_query_hash(self, query_text, set_auto_limit=False):
  class BaseSQLQueryRunner (line 269) | class BaseSQLQueryRunner(BaseQueryRunner):
    method get_schema (line 270) | def get_schema(self, get_stats=False):
    method _get_tables (line 277) | def _get_tables(self, schema_dict):
    method _get_tables_stats (line 280) | def _get_tables_stats(self, tables_dict):
    method supports_auto_limit (line 287) | def supports_auto_limit(self):
    method query_is_select_no_limit (line 290) | def query_is_select_no_limit(self, query):
    method add_limit_to_query (line 304) | def add_limit_to_query(self, query):
    method apply_auto_limit (line 323) | def apply_auto_limit(self, query_text, should_apply_auto_limit):
  class BaseHTTPQueryRunner (line 333) | class BaseHTTPQueryRunner(BaseQueryRunner):
    method configuration_schema (line 343) | def configuration_schema(cls):
    method get_auth (line 365) | def get_auth(self):
    method get_response (line 375) | def get_response(self, url, auth=None, http_method="get", **kwargs):
  function register (line 414) | def register(query_runner_class):
  function get_query_runner (line 431) | def get_query_runner(query_runner_type, configuration):
  function get_configuration_schema_for_query_runner_type (line 439) | def get_configuration_schema_for_query_runner_type(query_runner_type):
  function import_query_runners (line 447) | def import_query_runners(query_runner_imports):
  function guess_type (line 452) | def guess_type(value):
  function guess_type_from_string (line 463) | def guess_type_from_string(string_value):
  function with_ssh_tunnel (line 491) | def with_ssh_tunnel(query_runner, details):

FILE: redash/query_runner/amazon_elasticsearch.py
  class AmazonElasticsearchService (line 13) | class AmazonElasticsearchService(ElasticSearch2):
    method name (line 15) | def name(cls):
    method enabled (line 19) | def enabled(cls):
    method type (line 23) | def type(cls):
    method configuration_schema (line 27) | def configuration_schema(cls):
    method __init__ (line 51) | def __init__(self, configuration):
    method get_auth (line 66) | def get_auth(self):

FILE: redash/query_runner/arango.py
  class Arango (line 30) | class Arango(BaseQueryRunner):
    method name (line 34) | def name(cls):
    method configuration_schema (line 38) | def configuration_schema(cls):
    method enabled (line 55) | def enabled(cls):
    method type (line 64) | def type(cls):
    method run_query (line 67) | def run_query(self, query, user):

FILE: redash/query_runner/athena.py
  class SimpleFormatter (line 49) | class SimpleFormatter:
    method format (line 50) | def format(self, operation, parameters=None):
  class Athena (line 54) | class Athena(BaseQueryRunner):
    method name (line 58) | def name(cls):
    method configuration_schema (line 62) | def configuration_schema(cls):
    method enabled (line 156) | def enabled(cls):
    method annotate_query (line 159) | def annotate_query(self, query, metadata):
    method type (line 165) | def type(cls):
    method _get_iam_credentials (line 168) | def _get_iam_credentials(self, user=None):
    method __get_schema_from_glue (line 190) | def __get_schema_from_glue(self, catalog_id=""):
    method get_schema (line 229) | def get_schema(self, get_stats=False):
    method run_query (line 253) | def run_query(self, query, user):

FILE: redash/query_runner/axibase_tsd.py
  function resolve_redash_type (line 43) | def resolve_redash_type(type_in_atsd):
  function generate_rows_and_columns (line 56) | def generate_rows_and_columns(csv_response):
  class AxibaseTSD (line 86) | class AxibaseTSD(BaseQueryRunner):
    method enabled (line 90) | def enabled(cls):
    method name (line 94) | def name(cls):
    method configuration_schema (line 98) | def configuration_schema(cls):
    method __init__ (line 131) | def __init__(self, configuration):
    method run_query (line 139) | def run_query(self, query, user):
    method get_schema (line 171) | def get_schema(self, get_stats=False):

FILE: redash/query_runner/azure_kusto.py
  function _get_data_scanned (line 40) | def _get_data_scanned(kusto_response):
  class AzureKusto (line 68) | class AzureKusto(BaseQueryRunner):
    method __init__ (line 72) | def __init__(self, configuration):
    method configuration_schema (line 77) | def configuration_schema(cls):
    method enabled (line 110) | def enabled(cls):
    method type (line 114) | def type(cls):
    method name (line 118) | def name(cls):
    method run_query (line 121) | def run_query(self, query, user):
    method get_schema (line 196) | def get_schema(self, get_stats=False):

FILE: redash/query_runner/big_query.py
  function transform_cell (line 46) | def transform_cell(field_type, cell_value):
  function transform_row (line 60) | def transform_row(row, fields):
  function _load_key (line 75) | def _load_key(filename):
  function _get_query_results (line 83) | def _get_query_results(jobs, project_id, location, job_id, start_index):
  function _get_total_bytes_processed_for_resp (line 95) | def _get_total_bytes_processed_for_resp(bq_response):
  class BigQuery (line 101) | class BigQuery(BaseSQLQueryRunner):
    method __init__ (line 104) | def __init__(self, configuration):
    method enabled (line 109) | def enabled(cls):
    method configuration_schema (line 113) | def configuration_schema(cls):
    method annotate_query (line 159) | def annotate_query(self, query, metadata):
    method _get_bigquery_service (line 164) | def _get_bigquery_service(self):
    method _get_project_id (line 180) | def _get_project_id(self):
    method _get_location (line 183) | def _get_location(self):
    method _get_total_bytes_processed (line 186) | def _get_total_bytes_processed(self, jobs, query):
    method _get_job_data (line 198) | def _get_job_data(self, query):
    method _get_query_result (line 218) | def _get_query_result(self, jobs, query):
    method _get_columns_schema (line 269) | def _get_columns_schema(self, table_data):
    method _get_columns_schema_column (line 278) | def _get_columns_schema_column(self, column):
    method _get_project_datasets (line 288) | def _get_project_datasets(self, project_id):
    method get_schema (line 303) | def get_schema(self, get_stats=False):
    method run_query (line 378) | def run_query(self, query, user):

FILE: redash/query_runner/big_query_gce.py
  class BigQueryGCE (line 16) | class BigQueryGCE(BigQuery):
    method type (line 18) | def type(cls):
    method enabled (line 22) | def enabled(cls):
    method configuration_schema (line 35) | def configuration_schema(cls):
    method _get_project_id (line 61) | def _get_project_id(self):
    method _get_bigquery_service (line 64) | def _get_bigquery_service(self):

FILE: redash/query_runner/cass.py
  function generate_ssl_options_dict (line 21) | def generate_ssl_options_dict(protocol, cert_path=None):
  class Cassandra (line 29) | class Cassandra(BaseQueryRunner):
    method enabled (line 33) | def enabled(cls):
    method custom_json_encoder (line 37) | def custom_json_encoder(cls, dec, o):
    method configuration_schema (line 43) | def configuration_schema(cls):
    method type (line 79) | def type(cls):
    method get_schema (line 82) | def get_schema(self, get_stats=False):
    method run_query (line 118) | def run_query(self, query, user):
    method _generate_cert_file (line 157) | def _generate_cert_file(self):
    method _cleanup_cert_file (line 166) | def _cleanup_cert_file(self, cert_path):
    method _get_ssl_options (line 170) | def _get_ssl_options(self, cert_path):
  class ScyllaDB (line 177) | class ScyllaDB(Cassandra):
    method type (line 179) | def type(cls):

FILE: redash/query_runner/clickhouse.py
  function split_multi_query (line 22) | def split_multi_query(query):
  class ClickHouse (line 26) | class ClickHouse(BaseSQLQueryRunner):
    method configuration_schema (line 30) | def configuration_schema(cls):
    method _url (line 56) | def _url(self):
    method _url (line 60) | def _url(self, url):
    method host (line 64) | def host(self):
    method host (line 68) | def host(self, host):
    method port (line 72) | def port(self):
    method port (line 76) | def port(self, port):
    method _get_tables (line 79) | def _get_tables(self, schema):
    method _send_query (line 101) | def _send_query(self, data, session_id=None, session_check=None):
    method _define_column_type (line 149) | def _define_column_type(column):
    method _clickhouse_query (line 165) | def _clickhouse_query(self, query, session_id=None, session_check=None):
    method run_query (line 204) | def run_query(self, query, user):

FILE: redash/query_runner/cloudwatch.py
  function parse_response (line 16) | def parse_response(results):
  function parse_query (line 40) | def parse_query(query):
  class CloudWatch (line 52) | class CloudWatch(BaseQueryRunner):
    method name (line 56) | def name(cls):
    method configuration_schema (line 60) | def configuration_schema(cls):
    method enabled (line 74) | def enabled(cls):
    method __init__ (line 77) | def __init__(self, configuration):
    method test_connection (line 81) | def test_connection(self):
    method _get_client (line 84) | def _get_client(self):
    method get_schema (line 93) | def get_schema(self, get_stats=False):
    method run_query (line 112) | def run_query(self, query, user):

FILE: redash/query_runner/cloudwatch_insights.py
  function parse_response (line 21) | def parse_response(response):
  function parse_query (line 53) | def parse_query(query):
  class CloudWatchInsights (line 65) | class CloudWatchInsights(BaseQueryRunner):
    method name (line 69) | def name(cls):
    method type (line 73) | def type(cls):
    method configuration_schema (line 77) | def configuration_schema(cls):
    method enabled (line 91) | def enabled(cls):
    method __init__ (line 94) | def __init__(self, configuration):
    method test_connection (line 98) | def test_connection(self):
    method _get_client (line 101) | def _get_client(self):
    method get_schema (line 110) | def get_schema(self, get_stats=False):
    method run_query (line 129) | def run_query(self, query, user):

FILE: redash/query_runner/corporate_memory.py
  class CorporateMemoryQueryRunner (line 30) | class CorporateMemoryQueryRunner(BaseQueryRunner):
    method __init__ (line 60) | def __init__(self, configuration):
    method _setup_environment (line 76) | def _setup_environment(self):
    method _transform_sparql_results (line 94) | def _transform_sparql_results(results):
    method name (line 138) | def name(cls):
    method enabled (line 142) | def enabled(cls):
    method type (line 146) | def type(cls):
    method run_query (line 149) | def run_query(self, query, user):
    method configuration_schema (line 183) | def configuration_schema(cls):
    method get_schema (line 236) | def get_schema(self, get_stats=False):
    method _get_graphs_schema (line 248) | def _get_graphs_schema(self):
    method _get_common_prefixes_schema (line 257) | def _get_common_prefixes_schema():

FILE: redash/query_runner/couchbase.py
  function _get_column_by_name (line 33) | def _get_column_by_name(columns, column_name):
  function parse_results (line 40) | def parse_results(results):
  class Couchbase (line 77) | class Couchbase(BaseQueryRunner):
    method configuration_schema (line 82) | def configuration_schema(cls):
    method __init__ (line 101) | def __init__(self, configuration):
    method enabled (line 105) | def enabled(cls):
    method test_connection (line 108) | def test_connection(self):
    method get_buckets (line 111) | def get_buckets(self, query, name_param):
    method get_schema (line 121) | def get_schema(self, get_stats=False):
    method call_service (line 132) | def call_service(self, query, user):
    method run_query (line 151) | def run_query(self, query, user):
    method name (line 160) | def name(cls):

FILE: redash/query_runner/csv.py
  class CSV (line 23) | class CSV(BaseQueryRunner):
    method name (line 27) | def name(cls):
    method enabled (line 31) | def enabled(cls):
    method configuration_schema (line 35) | def configuration_schema(cls):
    method __init__ (line 41) | def __init__(self, configuration):
    method test_connection (line 45) | def test_connection(self):
    method run_query (line 48) | def run_query(self, query, user):
    method get_schema (line 111) | def get_schema(self):

FILE: redash/query_runner/databend.py
  class Databend (line 21) | class Databend(BaseQueryRunner):
    method configuration_schema (line 25) | def configuration_schema(cls):
    method name (line 42) | def name(cls):
    method type (line 46) | def type(cls):
    method enabled (line 50) | def enabled(cls):
    method _define_column_type (line 54) | def _define_column_type(column_type):
    method run_query (line 70) | def run_query(self, query, user):
    method get_schema (line 92) | def get_schema(self, get_stats=False):
    method _get_tables (line 118) | def _get_tables(self):

FILE: redash/query_runner/databricks.py
  function _build_odbc_connection_string (line 41) | def _build_odbc_connection_string(**kwargs):
  class Databricks (line 45) | class Databricks(BaseSQLQueryRunner):
    method type (line 50) | def type(cls):
    method enabled (line 54) | def enabled(cls):
    method configuration_schema (line 58) | def configuration_schema(cls):
    method _get_cursor (line 72) | def _get_cursor(self):
    method run_query (line 97) | def run_query(self, query, user):
    method get_schema (line 135) | def get_schema(self):
    method get_databases (line 138) | def get_databases(self):
    method get_database_tables (line 148) | def get_database_tables(self, database_name):
    method get_database_tables_with_columns (line 162) | def get_database_tables_with_columns(self, database_name):
    method get_table_columns (line 187) | def get_table_columns(self, database_name, table_name):

FILE: redash/query_runner/db2.py
  class DB2 (line 42) | class DB2(BaseSQLQueryRunner):
    method configuration_schema (line 46) | def configuration_schema(cls):
    method type (line 62) | def type(cls):
    method enabled (line 66) | def enabled(cls):
    method _get_definitions (line 74) | def _get_definitions(self, schema, query):
    method _get_tables (line 91) | def _get_tables(self, schema):
    method _get_connection (line 105) | def _get_connection(self):
    method run_query (line 117) | def run_query(self, query, user):

FILE: redash/query_runner/dgraph.py
  function reduce_item (line 13) | def reduce_item(reduced_item, key, value):
  class Dgraph (line 31) | class Dgraph(BaseQueryRunner):
    method configuration_schema (line 41) | def configuration_schema(cls):
    method type (line 55) | def type(cls):
    method enabled (line 59) | def enabled(cls):
    method run_dgraph_query_raw (line 62) | def run_dgraph_query_raw(self, query):
    method run_query (line 82) | def run_query(self, query, user):
    method get_schema (line 116) | def get_schema(self, get_stats=False):

FILE: redash/query_runner/drill.py
  function convert_type (line 21) | def convert_type(string_value, actual_type):
  function parse_response (line 41) | def parse_response(data):
  class Drill (line 65) | class Drill(BaseHTTPQueryRunner):
    method name (line 75) | def name(cls):
    method configuration_schema (line 79) | def configuration_schema(cls):
    method run_query (line 91) | def run_query(self, query, user):
    method get_schema (line 102) | def get_schema(self, get_stats=False):

FILE: redash/query_runner/druid.py
  class Druid (line 19) | class Druid(BaseQueryRunner):
    method configuration_schema (line 23) | def configuration_schema(cls):
    method enabled (line 39) | def enabled(cls):
    method run_query (line 42) | def run_query(self, query, user):
    method get_schema (line 66) | def get_schema(self, get_stats=False):

FILE: redash/query_runner/duckdb.py
  class DuckDB (line 50) | class DuckDB(BaseSQLQueryRunner):
    method __init__ (line 53) | def __init__(self, configuration):
    method configuration_schema (line 61) | def configuration_schema(cls):
    method enabled (line 80) | def enabled(cls) -> bool:
    method _connect (line 83) | def _connect(self) -> None:
    method run_query (line 100) | def run_query(self, query, user) -> tuple:
    method get_schema (line 116) | def get_schema(self, get_stats=False) -> list:
    method _expand_struct_fields (line 158) | def _expand_struct_fields(self, base_name: str, struct_type: str) -> l...

FILE: redash/query_runner/e6data.py
  class e6data (line 48) | class e6data(BaseQueryRunner):
    method __init__ (line 53) | def __init__(self, configuration):
    method configuration_schema (line 64) | def configuration_schema(cls):
    method enabled (line 88) | def enabled(cls):
    method type (line 92) | def type(cls):
    method run_query (line 95) | def run_query(self, query, user):
    method test_connection (line 120) | def test_connection(self):
    method get_schema (line 128) | def get_schema(self, get_stats=False):

FILE: redash/query_runner/elasticsearch.py
  class BaseElasticSearch (line 52) | class BaseElasticSearch(BaseQueryRunner):
    method configuration_schema (line 58) | def configuration_schema(cls):
    method enabled (line 75) | def enabled(cls):
    method __init__ (line 78) | def __init__(self, configuration):
    method _get_mappings (line 104) | def _get_mappings(self, url):
    method _get_query_mappings (line 123) | def _get_query_mappings(self, url):
    method get_schema (line 149) | def get_schema(self, *args, **kwargs):
    method _parse_results (line 180) | def _parse_results(self, mappings, result_fields, raw_result, result_c...
    method test_connection (line 324) | def test_connection(self):
  class Kibana (line 336) | class Kibana(BaseElasticSearch):
    method enabled (line 338) | def enabled(cls):
    method _execute_simple_query (line 341) | def _execute_simple_query(self, url, auth, _from, mappings, result_fie...
    method run_query (line 356) | def run_query(self, query, user):
  class ElasticSearch (line 425) | class ElasticSearch(BaseElasticSearch):
    method enabled (line 427) | def enabled(cls):
    method name (line 431) | def name(cls):
    method run_query (line 434) | def run_query(self, query, user):

FILE: redash/query_runner/elasticsearch2.py
  class ElasticSearch2 (line 37) | class ElasticSearch2(BaseHTTPQueryRunner):
    method name (line 41) | def name(cls):
    method __init__ (line 44) | def __init__(self, *args, **kwargs):
    method get_response (line 48) | def get_response(self, url, auth=None, http_method="get", **kwargs):
    method test_connection (line 54) | def test_connection(self):
    method run_query (line 59) | def run_query(self, query, user):
    method _build_query (line 67) | def _build_query(self, query: str) -> Tuple[dict, str, Optional[list]]:
    method _parse_mappings (line 75) | def _parse_mappings(cls, mappings_data: dict):
    method get_mappings (line 102) | def get_mappings(self):
    method get_schema (line 106) | def get_schema(self, *args, **kwargs):
    method _parse_results (line 113) | def _parse_results(cls, result_fields, raw_result):  # noqa: C901
  class OpenDistroSQLElasticSearch (line 241) | class OpenDistroSQLElasticSearch(ElasticSearch2):
    method __init__ (line 242) | def __init__(self, *args, **kwargs):
    method _build_query (line 246) | def _build_query(self, query: str) -> Tuple[dict, str, Optional[list]]:
    method name (line 252) | def name(cls):
    method type (line 256) | def type(cls):
  class XPackSQLElasticSearch (line 260) | class XPackSQLElasticSearch(ElasticSearch2):
    method __init__ (line 261) | def __init__(self, *args, **kwargs):
    method _build_query (line 265) | def _build_query(self, query: str) -> Tuple[dict, str, Optional[list]]:
    method _parse_results (line 271) | def _parse_results(cls, result_fields, raw_result):
    method name (line 298) | def name(cls):
    method type (line 302) | def type(cls):

FILE: redash/query_runner/exasol.py
  function _exasol_type_mapper (line 14) | def _exasol_type_mapper(val, data_type):
  function _type_mapper (line 40) | def _type_mapper(data_type):
  class Exasol (line 64) | class Exasol(BaseQueryRunner):
    method configuration_schema (line 68) | def configuration_schema(cls):
    method _get_connection (line 83) | def _get_connection(self):
    method run_query (line 98) | def run_query(self, query, user):
    method get_schema (line 119) | def get_schema(self, get_stats=False):
    method enabled (line 153) | def enabled(cls):

FILE: redash/query_runner/excel.py
  class Excel (line 24) | class Excel(BaseQueryRunner):
    method enabled (line 28) | def enabled(cls):
    method configuration_schema (line 32) | def configuration_schema(cls):
    method __init__ (line 38) | def __init__(self, configuration):
    method test_connection (line 42) | def test_connection(self):
    method run_query (line 45) | def run_query(self, query, user):
    method get_schema (line 109) | def get_schema(self):

FILE: redash/query_runner/google_analytics.py
  function parse_ga_response (line 39) | def parse_ga_response(response):
  class GoogleAnalytics (line 89) | class GoogleAnalytics(BaseSQLQueryRunner):
    method type (line 93) | def type(cls):
    method name (line 97) | def name(cls):
    method enabled (line 101) | def enabled(cls):
    method configuration_schema (line 105) | def configuration_schema(cls):
    method __init__ (line 113) | def __init__(self, configuration):
    method _get_analytics_service (line 117) | def _get_analytics_service(self):
    method _get_tables (line 128) | def _get_tables(self, schema):
    method test_connection (line 151) | def test_connection(self):
    method run_query (line 159) | def run_query(self, query, user):

FILE: redash/query_runner/google_analytics4.py
  function format_column_value (line 41) | def format_column_value(column_name, value, columns):
  function get_formatted_column_json (line 57) | def get_formatted_column_json(column_name):
  function parse_ga_response (line 74) | def parse_ga_response(response):
  class GoogleAnalytics4 (line 106) | class GoogleAnalytics4(BaseQueryRunner):
    method type (line 110) | def type(cls):
    method name (line 114) | def name(cls):
    method enabled (line 118) | def enabled(cls):
    method configuration_schema (line 122) | def configuration_schema(cls):
    method _get_access_token (line 133) | def _get_access_token(self):
    method run_query (line 146) | def run_query(self, query, user):
    method test_connection (line 166) | def test_connection(self):

FILE: redash/query_runner/google_search_console.py
  function parse_ga_response (line 38) | def parse_ga_response(response, dimensions):
  function get_formatted_value (line 78) | def get_formatted_value(column_type, value):
  class GoogleSearchConsole (line 93) | class GoogleSearchConsole(BaseSQLQueryRunner):
    method type (line 97) | def type(cls):
    method name (line 101) | def name(cls):
    method enabled (line 105) | def enabled(cls):
    method configuration_schema (line 109) | def configuration_schema(cls):
    method __init__ (line 120) | def __init__(self, configuration):
    method _get_search_service (line 124) | def _get_search_service(self):
    method test_connection (line 135) | def test_connection(self):
    method run_query (line 143) | def run_query(self, query, user):

FILE: redash/query_runner/google_spreadsheets.py
  function _load_key (line 36) | def _load_key(filename):
  function _get_columns_and_column_names (line 41) | def _get_columns_and_column_names(row):
  function _value_eval_list (line 60) | def _value_eval_list(row_values, col_types):
  class WorksheetNotFoundError (line 87) | class WorksheetNotFoundError(Exception):
    method __init__ (line 88) | def __init__(self, worksheet_num, worksheet_count):
  class WorksheetNotFoundByTitleError (line 95) | class WorksheetNotFoundByTitleError(Exception):
    method __init__ (line 96) | def __init__(self, worksheet_title):
  function parse_query (line 101) | def parse_query(query):
  function parse_worksheet (line 118) | def parse_worksheet(worksheet):
  function parse_spreadsheet (line 135) | def parse_spreadsheet(spreadsheet, worksheet_num_or_title):
  function is_url_key (line 152) | def is_url_key(key):
  function parse_api_error (line 156) | def parse_api_error(error):
  class SpreadsheetWrapper (line 167) | class SpreadsheetWrapper:
    method __init__ (line 168) | def __init__(self, spreadsheet):
    method worksheets (line 171) | def worksheets(self):
    method get_worksheet_by_index (line 174) | def get_worksheet_by_index(self, index):
    method get_worksheet_by_title (line 177) | def get_worksheet_by_title(self, title):
  class TimeoutSession (line 184) | class TimeoutSession(Session):
    method request (line 185) | def request(self, *args, **kwargs):
  class GoogleSpreadsheet (line 190) | class GoogleSpreadsheet(BaseQueryRunner):
    method __init__ (line 193) | def __init__(self, configuration):
    method name (line 198) | def name(cls):
    method type (line 202) | def type(cls):
    method enabled (line 206) | def enabled(cls):
    method configuration_schema (line 210) | def configuration_schema(cls):
    method _get_spreadsheet_service (line 218) | def _get_spreadsheet_service(self):
    method test_connection (line 233) | def test_connection(self):
    method run_query (line 246) | def run_query(self, query, user):

FILE: redash/query_runner/graphite.py
  function _transform_result (line 17) | def _transform_result(response):
  class Graphite (line 40) | class Graphite(BaseQueryRunner):
    method configuration_schema (line 44) | def configuration_schema(cls):
    method __init__ (line 57) | def __init__(self, configuration):
    method test_connection (line 69) | def test_connection(self):
    method run_query (line 78) | def run_query(self, query, user):

FILE: redash/query_runner/hive_ds.py
  class Hive (line 48) | class Hive(BaseSQLQueryRunner):
    method configuration_schema (line 53) | def configuration_schema(cls):
    method type (line 67) | def type(cls):
    method enabled (line 71) | def enabled(cls):
    method _get_tables (line 74) | def _get_tables(self, schema):
    method _get_connection (line 103) | def _get_connection(self):
    method run_query (line 115) | def run_query(self, query, user):
  class HiveHttp (line 159) | class HiveHttp(Hive):
    method name (line 161) | def name(cls):
    method type (line 165) | def type(cls):
    method configuration_schema (line 169) | def configuration_schema(cls):
    method _get_connection (line 198) | def _get_connection(self):

FILE: redash/query_runner/ignite.py
  class Ignite (line 36) | class Ignite(BaseSQLQueryRunner):
    method configuration_schema (line 41) | def configuration_schema(cls):
    method name (line 60) | def name(cls):
    method type (line 64) | def type(cls):
    method enabled (line 68) | def enabled(cls):
    method _get_tables (line 71) | def _get_tables(self, schema):
    method normalise_column (line 100) | def normalise_column(self, col):
    method normalise_row (line 107) | def normalise_row(self, row):
    method server_to_connection (line 110) | def server_to_connection(self, s):
    method _parse_results (line 123) | def _parse_results(self, c):
    method run_query (line 130) | def run_query(self, query, user):

FILE: redash/query_runner/impala_ds.py
  class Impala (line 44) | class Impala(BaseSQLQueryRunner):
    method configuration_schema (line 48) | def configuration_schema(cls):
    method type (line 74) | def type(cls):
    method _get_tables (line 77) | def _get_tables(self, schema_dict):
    method run_query (line 95) | def run_query(self, query, user):

FILE: redash/query_runner/influx_db.py
  function _get_type (line 29) | def _get_type(value):
  function _transform_result (line 33) | def _transform_result(results):
  class InfluxDB (line 69) | class InfluxDB(BaseQueryRunner):
    method configuration_schema (line 74) | def configuration_schema(cls):
    method enabled (line 82) | def enabled(cls):
    method type (line 86) | def type(cls):
    method run_query (line 89) | def run_query(self, query, user):

FILE: redash/query_runner/influx_db_v2.py
  class InfluxDBv2 (line 39) | class InfluxDBv2(BaseQueryRunner):
    method _get_influx_kwargs (line 46) | def _get_influx_kwargs(self) -> Dict:
    method _create_cert_file (line 59) | def _create_cert_file(self, key: str) -> str:
    method _cleanup_cert_files (line 76) | def _cleanup_cert_files(self, influx_kwargs: Dict) -> None:
    method configuration_schema (line 86) | def configuration_schema(cls: Type[T]) -> Dict:
    method enabled (line 112) | def enabled(cls: Type[T]) -> bool:
    method test_connection (line 120) | def test_connection(self) -> None:
    method _get_type (line 144) | def _get_type(self, type_: str) -> str:
    method _get_data_from_tables (line 153) | def _get_data_from_tables(self, tables: Any) -> Dict:
    method run_query (line 178) | def run_query(self, query: str, user: str) -> Tuple[Optional[str], Opt...

FILE: redash/query_runner/jql.py
  class ResultSet (line 9) | class ResultSet:
    method __init__ (line 10) | def __init__(self):
    method add_row (line 14) | def add_row(self, row):
    method add_column (line 20) | def add_column(self, column, column_type=TYPE_STRING):
    method to_json (line 28) | def to_json(self):
    method merge (line 31) | def merge(self, set):
  function parse_issue (line 35) | def parse_issue(issue, field_mapping):  # noqa: C901
  function parse_issues (line 94) | def parse_issues(data, field_mapping):
  function parse_count (line 103) | def parse_count(data):
  class FieldMapping (line 111) | class FieldMapping:
    method __init__ (line 112) | def __init__(cls, query_field_mapping):
    method get_output_field_name (line 132) | def get_output_field_name(cls, field_name):
    method get_dict_members (line 138) | def get_dict_members(cls, field_name):
    method get_dict_output_field_name (line 145) | def get_dict_output_field_name(cls, field_name, member_name):
  class JiraJQL (line 152) | class JiraJQL(BaseHTTPQueryRunner):
    method name (line 161) | def name(cls):
    method __init__ (line 164) | def __init__(self, configuration):
    method run_query (line 168) | def run_query(self, query, user):

FILE: redash/query_runner/json_ds.py
  class QueryParseError (line 19) | class QueryParseError(Exception):
  function parse_query (line 23) | def parse_query(query):
  function _get_column_by_name (line 47) | def _get_column_by_name(columns, column_name):
  function _get_type (line 55) | def _get_type(value):
  function add_column (line 59) | def add_column(columns, column_name, column_type):
  function _apply_path_search (line 64) | def _apply_path_search(response, path, default=None):
  function _normalize_json (line 82) | def _normalize_json(data, path):
  function _sort_columns_with_fields (line 93) | def _sort_columns_with_fields(columns, fields):
  function parse_json (line 101) | def parse_json(data, fields):
  class JSON (line 133) | class JSON(BaseHTTPQueryRunner):
    method configuration_schema (line 138) | def configuration_schema(cls):
    method __init__ (line 150) | def __init__(self, configuration):
    method test_connection (line 154) | def test_connection(self):
    method run_query (line 157) | def run_query(self, query, user):
    method _run_json_query (line 168) | def _run_json_query(self, query):
    method _get_all_results (line 200) | def _get_all_results(self, url, method, result_path, pagination, **req...
    method _get_json_response (line 219) | def _get_json_response(self, url, method, **request_options):
  class RequestPagination (line 225) | class RequestPagination:
    method next (line 226) | def next(self, url, request_options, response):
    method from_config (line 235) | def from_config(configuration, pagination):
  class UrlPagination (line 247) | class UrlPagination(RequestPagination):
    method __init__ (line 248) | def __init__(self, pagination):
    method next (line 253) | def next(self, url, request_options, response):
  class TokenPagination (line 262) | class TokenPagination(RequestPagination):
    method __init__ (line 263) | def __init__(self, pagination):
    method next (line 268) | def next(self, url, request_options, response):

FILE: redash/query_runner/kylin.py
  class Kylin (line 59) | class Kylin(BaseQueryRunner):
    method configuration_schema (line 61) | def configuration_schema(cls):
    method run_query (line 79) | def run_query(self, query, user):
    method get_schema (line 106) | def get_schema(self, get_stats=False):
    method test_connection (line 123) | def test_connection(self):
    method get_columns (line 127) | def get_columns(self, colmetas):
    method get_rows (line 138) | def get_rows(self, columns, results):
    method get_table_schema (line 141) | def get_table_schema(self, table):

FILE: redash/query_runner/memsql_ds.py
  class MemSQL (line 47) | class MemSQL(BaseSQLQueryRunner):
    method configuration_schema (line 52) | def configuration_schema(cls):
    method type (line 66) | def type(cls):
    method enabled (line 70) | def enabled(cls):
    method _get_tables (line 73) | def _get_tables(self, schema):
    method run_query (line 100) | def run_query(self, query, user):

FILE: redash/query_runner/mongodb.py
  function parse_oids (line 48) | def parse_oids(oids):
  function datetime_parser (line 55) | def datetime_parser(dct):
  function parse_query_json (line 72) | def parse_query_json(query: str):
  function _get_column_by_name (line 77) | def _get_column_by_name(columns, column_name):
  function _parse_dict (line 85) | def _parse_dict(dic: dict, flatten: bool = False) -> dict:
  function parse_results (line 111) | def parse_results(results: list, flatten: bool = False) -> list:
  function _sorted_fields (line 134) | def _sorted_fields(fields):
  class MongoDB (line 145) | class MongoDB(BaseQueryRunner):
    method configuration_schema (line 149) | def configuration_schema(cls):
    method enabled (line 183) | def enabled(cls):
    method __init__ (line 186) | def __init__(self, configuration):
    method custom_json_encoder (line 201) | def custom_json_encoder(cls, dec, o):
    method _get_db (line 210) | def _get_db(self):
    method test_connection (line 228) | def test_connection(self):
    method _merge_property_names (line 235) | def _merge_property_names(self, columns, document):
    method _is_collection_a_view (line 240) | def _is_collection_a_view(self, db, collection_name):
    method _get_collection_fields (line 246) | def _get_collection_fields(self, db, collection_name):
    method get_schema (line 278) | def get_schema(self, get_stats=False):
    method run_query (line 293) | def run_query(self, query, user):  # noqa: C901

FILE: redash/query_runner/mssql.py
  class SqlServer (line 33) | class SqlServer(BaseSQLQueryRunner):
    method configuration_schema (line 42) | def configuration_schema(cls):
    method enabled (line 67) | def enabled(cls):
    method name (line 71) | def name(cls):
    method type (line 75) | def type(cls):
    method _get_tables (line 78) | def _get_tables(self, schema):
    method run_query (line 106) | def run_query(self, query, user):

FILE: redash/query_runner/mssql_odbc.py
  class SQLServerODBC (line 20) | class SQLServerODBC(BaseSQLQueryRunner):
    method configuration_schema (line 29) | def configuration_schema(cls):
    method enabled (line 70) | def enabled(cls):
    method name (line 74) | def name(cls):
    method type (line 78) | def type(cls):
    method supports_auto_limit (line 82) | def supports_auto_limit(self):
    method _get_tables (line 85) | def _get_tables(self, schema):
    method run_query (line 113) | def run_query(self, query, user):

FILE: redash/query_runner/mysql.py
  class Result (line 46) | class Result:
    method __init__ (line 47) | def __init__(self):
  class Mysql (line 51) | class Mysql(BaseSQLQueryRunner):
    method configuration_schema (line 55) | def configuration_schema(cls):
    method name (line 120) | def name(cls):
    method enabled (line 124) | def enabled(cls):
    method _connection (line 127) | def _connection(self):
    method _get_tables (line 149) | def _get_tables(self, schema):
    method run_query (line 209) | def run_query(self, query, user):
    method _run_query (line 229) | def _run_query(self, query, user, connection, r, ev):
    method _get_ssl_parameters (line 266) | def _get_ssl_parameters(self):
    method _cancel (line 281) | def _cancel(self, thread_id):
  class RDSMySQL (line 303) | class RDSMySQL(Mysql):
    method name (line 305) | def name(cls):
    method type (line 309) | def type(cls):
    method configuration_schema (line 313) | def configuration_schema(cls):
    method _get_ssl_parameters (line 330) | def _get_ssl_parameters(self):

FILE: redash/query_runner/nz.py
  class Netezza (line 70) | class Netezza(BaseSQLQueryRunner):
    method configuration_schema (line 74) | def configuration_schema(cls):
    method type (line 90) | def type(cls):
    method __init__ (line 93) | def __init__(self, configuration):
    method connection (line 98) | def connection(self):
    method get_schema (line 109) | def get_schema(self, get_stats=False):
    method enabled (line 131) | def enabled(cls):
    method type_map (line 135) | def type_map(self, typid, func):
    method run_query (line 151) | def run_query(self, query, user):

FILE: redash/query_runner/oracle.py
  class Oracle (line 40) | class Oracle(BaseSQLQueryRunner):
    method get_col_type (line 47) | def get_col_type(cls, col_type, scale):
    method enabled (line 58) | def enabled(cls):
    method configuration_schema (line 62) | def configuration_schema(cls):
    method type (line 82) | def type(cls):
    method _get_tables (line 85) | def _get_tables(self, schema):
    method _convert_number (line 114) | def _convert_number(cls, value):
    method output_handler (line 121) | def output_handler(cls, cursor, name, default_type, length, precision,...
    method run_query (line 137) | def run_query(self, query, user):

FILE: redash/query_runner/pg.py
  function _wait (line 58) | def _wait(conn, timeout=None):
  function full_table_name (line 74) | def full_table_name(schema, name):
  function build_schema (line 81) | def build_schema(query_result, schema):
  function _create_cert_file (line 115) | def _create_cert_file(configuration, key, ssl_config):
  function _cleanup_ssl_certs (line 125) | def _cleanup_ssl_certs(ssl_config):
  function _get_ssl_config (line 131) | def _get_ssl_config(configuration):
  function _parse_dsn (line 141) | def _parse_dsn(configuration):
  class PostgreSQL (line 150) | class PostgreSQL(BaseSQLQueryRunner):
    method configuration_schema (line 154) | def configuration_schema(cls):
    method type (line 193) | def type(cls):
    method custom_json_encoder (line 197) | def custom_json_encoder(cls, dec, o):
    method _get_definitions (line 208) | def _get_definitions(self, schema, query):
    method _get_tables (line 216) | def _get_tables(self, schema):
    method _get_connection (line 255) | def _get_connection(self):
    method run_query (line 271) | def run_query(self, query, user):
  class Redshift (line 306) | class Redshift(PostgreSQL):
    method type (line 308) | def type(cls):
    method name (line 312) | def name(cls):
    method _get_connection (line 315) | def _get_connection(self):
    method configuration_schema (line 334) | def configuration_schema(cls):
    method annotate_query (line 369) | def annotate_query(self, query, metadata):
    method _get_tables (line 383) | def _get_tables(self, schema):
  class RedshiftIAM (line 418) | class RedshiftIAM(Redshift):
    method type (line 420) | def type(cls):
    method name (line 424) | def name(cls):
    method enabled (line 428) | def enabled(cls):
    method _login_method_selection (line 431) | def _login_method_selection(self):
    method configuration_schema (line 443) | def configuration_schema(cls):
    method _get_connection (line 489) | def _get_connection(self):
  class CockroachDB (line 547) | class CockroachDB(PostgreSQL):
    method type (line 549) | def type(cls):

FILE: redash/query_runner/phoenix.py
  class Phoenix (line 52) | class Phoenix(BaseQueryRunner):
    method configuration_schema (line 56) | def configuration_schema(cls):
    method enabled (line 64) | def enabled(cls):
    method type (line 68) | def type(cls):
    method get_schema (line 71) | def get_schema(self, get_stats=False):
    method run_query (line 94) | def run_query(self, query, user):

FILE: redash/query_runner/pinot.py
  class Pinot (line 38) | class Pinot(BaseQueryRunner):
    method configuration_schema (line 44) | def configuration_schema(cls):
    method enabled (line 61) | def enabled(cls):
    method __init__ (line 64) | def __init__(self, configuration):
    method run_query (line 70) | def run_query(self, query, user):
    method get_schema (line 100) | def get_schema(self, get_stats=False):
    method get_schema_names (line 121) | def get_schema_names(self):
    method get_pinot_table_schema (line 124) | def get_pinot_table_schema(self, pinot_table_name):
    method get_table_names (line 127) | def get_table_names(self):
    method get_metadata_from_controller (line 130) | def get_metadata_from_controller(self, path):

FILE: redash/query_runner/presto.py
  class Presto (line 42) | class Presto(BaseQueryRunner):
    method configuration_schema (line 46) | def configuration_schema(cls):
    method enabled (line 71) | def enabled(cls):
    method type (line 75) | def type(cls):
    method get_schema (line 78) | def get_schema(self, get_stats=False):
    method run_query (line 101) | def run_query(self, query, user):

FILE: redash/query_runner/prometheus.py
  function get_instant_rows (line 19) | def get_instant_rows(metrics_data):
  function get_range_rows (line 33) | def get_range_rows(metrics_data):
  function convert_query_range (line 52) | def convert_query_range(payload):
  class Prometheus (line 75) | class Prometheus(BaseQueryRunner):
    method _get_datetime_now (line 78) | def _get_datetime_now(self):
    method _get_prometheus_kwargs (line 81) | def _get_prometheus_kwargs(self):
    method _create_cert_file (line 100) | def _create_cert_file(self, key):
    method _cleanup_cert_files (line 111) | def _cleanup_cert_files(self, promehteus_kwargs):
    method configuration_schema (line 122) | def configuration_schema(cls):
    method test_connection (line 142) | def test_connection(self):
    method get_schema (line 156) | def get_schema(self, get_stats=False):
    method run_query (line 180) | def run_query(self, query, user):

FILE: redash/query_runner/python.py
  class CustomPrint (line 41) | class CustomPrint:
    method __init__ (line 44) | def __init__(self):
    method write (line 48) | def write(self, text):
    method enable (line 54) | def enable(self):
    method disable (line 57) | def disable(self):
    method __call__ (line 60) | def __call__(self, *args):
    method _call_print (line 63) | def _call_print(self, *objects, **kwargs):
  class Python (line 67) | class Python(BaseQueryRunner):
    method configuration_schema (line 99) | def configuration_schema(cls):
    method enabled (line 113) | def enabled(cls):
    method __init__ (line 116) | def __init__(self, configuration):
    method custom_import (line 140) | def custom_import(self, name, globals=None, locals=None, fromlist=(), ...
    method custom_write (line 154) | def custom_write(obj):
    method custom_get_item (line 162) | def custom_get_item(obj, key):
    method custom_get_iter (line 166) | def custom_get_iter(obj):
    method custom_inplacevar (line 170) | def custom_inplacevar(op, x, y):
    method add_result_column (line 178) | def add_result_column(result, column_name, friendly_name, column_type):
    method add_result_row (line 196) | def add_result_row(result, values):
    method execute_query (line 209) | def execute_query(data_source_name_or_id, query, result_type=None):
    method get_source_schema (line 238) | def get_source_schema(data_source_name_or_id):
    method get_query_result (line 255) | def get_query_result(query_id):
    method dataframe_to_result (line 274) | def dataframe_to_result(self, result, df):
    method get_current_user (line 281) | def get_current_user(self):
    method test_connection (line 284) | def test_connection(self):
    method validate_result (line 287) | def validate_result(self, result):
    method run_query (line 306) | def run_query(self, query, user):

FILE: redash/query_runner/query_results.py
  class PermissionError (line 23) | class PermissionError(Exception):
  class CreateTableError (line 27) | class CreateTableError(Exception):
  function extract_query_params (line 31) | def extract_query_params(query):
  function extract_query_ids (line 35) | def extract_query_ids(query):
  function extract_cached_query_ids (line 40) | def extract_cached_query_ids(query):
  function _load_query (line 45) | def _load_query(user, query_id):
  function replace_query_parameters (line 59) | def replace_query_parameters(query_text, params):
  function get_query_results (line 66) | def get_query_results(user, query_id, bring_from_cache, params=None):
  function create_tables_from_query_ids (line 85) | def create_tables_from_query_ids(user, connection, query_ids, query_para...
  function fix_column_name (line 105) | def fix_column_name(name):
  function flatten (line 109) | def flatten(value):
  function create_table (line 120) | def create_table(connection, table_name, query_results):
  function prepare_parameterized_query (line 145) | def prepare_parameterized_query(query, query_params):
  class Results (line 156) | class Results(BaseQueryRunner):
    method configuration_schema (line 161) | def configuration_schema(cls):
    method name (line 165) | def name(cls):
    method run_query (line 168) | def run_query(self, query, user):

FILE: redash/query_runner/risingwave.py
  class RisingWave (line 5) | class RisingWave(PostgreSQL):
    method type (line 7) | def type(cls):
    method name (line 11) | def name(cls):
    method _get_tables (line 14) | def _get_tables(self, schema):

FILE: redash/query_runner/rockset.py
  function _get_type (line 13) | def _get_type(value):
  class RocksetAPI (line 27) | class RocksetAPI:
    method __init__ (line 28) | def __init__(self, api_key, api_server, vi_id):
    method _request (line 33) | def _request(self, endpoint, method="GET", body=None):
    method list_workspaces (line 46) | def list_workspaces(self):
    method list_collections (line 50) | def list_collections(self, workspace="commons"):
    method collection_columns (line 54) | def collection_columns(self, workspace, collection):
    method query (line 58) | def query(self, sql):
  class Rockset (line 65) | class Rockset(BaseSQLQueryRunner):
    method configuration_schema (line 69) | def configuration_schema(cls):
    method type (line 87) | def type(cls):
 
Condensed preview — 1155 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (6,248K chars).
[
  {
    "path": ".ci/Dockerfile.cypress",
    "chars": 348,
    "preview": "FROM cypress/browsers:node-24.14.0-chrome-145.0.7632.116-1-ff-148.0-edge-145.0.3800.70-1\n\nENV APP /usr/src/app\nWORKDIR $"
  },
  {
    "path": ".ci/compose.ci.yaml",
    "chars": 765,
    "preview": "services:\n  redash:\n    build: ../\n    command: manage version\n    depends_on:\n      - postgres\n      - redis\n    ports:"
  },
  {
    "path": ".ci/compose.cypress.yaml",
    "chars": 2054,
    "preview": "x-redash-service: &redash-service\n  build:\n    context: ../\n    args:\n      install_groups: \"main\"\n      code_coverage: "
  },
  {
    "path": ".ci/docker_build",
    "chars": 1191,
    "preview": "#!/bin/bash\n\n# This script only needs to run on the main Redash repo\n\nif [ \"${GITHUB_REPOSITORY}\" != \"getredash/redash\" "
  },
  {
    "path": ".ci/pack",
    "chars": 317,
    "preview": "#!/bin/bash\nNAME=redash\nVERSION=$(jq -r .version package.json)\nFULL_VERSION=$VERSION+b$CIRCLE_BUILD_NUM\nFILENAME=$NAME.$"
  },
  {
    "path": ".ci/update_version",
    "chars": 267,
    "preview": "#!/bin/bash\nVERSION=$(jq -r .version package.json)\nFULL_VERSION=${VERSION}+b${GITHUB_RUN_ID}.${GITHUB_RUN_NUMBER}\n\nsed -"
  },
  {
    "path": ".coveragerc",
    "chars": 109,
    "preview": "[run]\nbranch = True\nsource = redash\n\n[report]\nomit =\n    */settings.py\n    */python?.?/*\nshow_missing = True\n"
  },
  {
    "path": ".dockerignore",
    "chars": 161,
    "preview": "client/.tmp/\nnode_modules/\nviz-lib/node_modules/\n.tmp/\n.venv/\nvenv/\n.git/\n/.codeclimate.yml\n/.coverage\n/coverage.xml\n/.c"
  },
  {
    "path": ".editorconfig",
    "chars": 204,
    "preview": "root = true\n\n[*]\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.py]\nindent_style = spa"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/---bug_report.md",
    "chars": 1179,
    "preview": "---\nname: \"\\U0001F41B Bug report\"\nabout: Report reproducible software issues so we can improve\n---\n\n<!--\n\nWe use GitHub "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/--anything_else.md",
    "chars": 645,
    "preview": "---\nname: \"\\U0001F4A1Anything else\"\nabout: \"For help, support, features & ideas - please use Discussions \\U0001F46B \"\nla"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 686,
    "preview": "## What type of PR is this? \n<!-- Check all that apply, delete what doesn't apply. -->\n\n- [ ] Refactor\n- [ ] Feature\n- ["
  },
  {
    "path": ".github/config.yml",
    "chars": 221,
    "preview": "# https://github.com/behaviorbot/request-info?installation_id=189571\nrequestInfoLabelToAdd: needs-more-info\nrequestInfoR"
  },
  {
    "path": ".github/weekly-digest.yml",
    "chars": 222,
    "preview": "# Configuration for weekly-digest - https://github.com/apps/weekly-digest\npublishDay: mon\ncanPublishIssues: true\ncanPubl"
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 5900,
    "preview": "name: Tests\non:\n  push:\n    branches:\n      - master\n  pull_request:\n    branches:\n      - master\nenv:\n  NODE_VERSION: 2"
  },
  {
    "path": ".github/workflows/periodic-snapshot.yml",
    "chars": 3185,
    "preview": "name: Periodic Snapshot\n\non:\n  schedule:\n    - cron: '10 0 1 * *'  # 10 minutes after midnight on the first day of every"
  },
  {
    "path": ".github/workflows/preview-image.yml",
    "chars": 6301,
    "preview": "name: Preview Image\non:\n  push:\n    tags:\n      - '*-dev'\n  workflow_dispatch:\n    inputs:\n      dockerRepository:\n     "
  },
  {
    "path": ".github/workflows/restyled.yml",
    "chars": 1048,
    "preview": "name: Restyled\n\non:\n  pull_request:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress"
  },
  {
    "path": ".gitignore",
    "chars": 276,
    "preview": ".venv\nvenv/\n.cache\n.coverage.*\n.coveralls.yml\n.idea\n*.pyc\n.nyc_output\ncoverage\n.coverage\ncoverage.xml\nclient/dist\n.DS_St"
  },
  {
    "path": ".npmrc",
    "chars": 65,
    "preview": "engine-strict=true\nauto-install-peers=true\nshamefully-hoist=true\n"
  },
  {
    "path": ".nvmrc",
    "chars": 4,
    "preview": "v24\n"
  },
  {
    "path": ".pre-commit-config.yaml",
    "chars": 232,
    "preview": "repos:\n  - repo: https://github.com/psf/black\n    rev: 23.1.0\n    hooks:\n      - id: black\n        language_version: pyt"
  },
  {
    "path": ".restyled.yaml",
    "chars": 1407,
    "preview": "enabled: true\n\nauto: false\n\n# Open Restyle PRs?\npull_requests: true\n\n# Leave comments on the original PR linking to the "
  },
  {
    "path": "CHANGELOG.md",
    "chars": 118427,
    "preview": "# Change Log\n\n## 26.03.0\n\n* Fix regular expression warning ([#7650](https://github.com/getredash/redash/pull/7650))\n* Up"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 5829,
    "preview": "# Contributing Guide\n\nThank you for taking the time to contribute! :tada::+1:\n\nThe following is a set of guidelines for "
  },
  {
    "path": "Dockerfile",
    "chars": 3805,
    "preview": "FROM node:24-bookworm AS frontend-builder\n\nRUN npm install --global pnpm@10.30.3\n\n# Controls whether to build the fronte"
  },
  {
    "path": "LICENSE",
    "chars": 1320,
    "preview": "Copyright (c) 2013-2020, Arik Fraimovich.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with "
  },
  {
    "path": "LICENSE.borders",
    "chars": 195,
    "preview": "The Bahrain map data used in Redash was downloaded from\nhttps://cartographyvectors.com/map/857-bahrain-detailed-boundary"
  },
  {
    "path": "Makefile",
    "chars": 2128,
    "preview": ".PHONY: compose_build up test_db create_database clean down tests lint backend-unit-tests frontend-unit-tests test build"
  },
  {
    "path": "README.md",
    "chars": 4458,
    "preview": "<p align=\"center\">\n  <img title=\"Redash\" src='https://redash.io/assets/images/logo.png' width=\"200px\"/>\n</p>\n\n[![Documen"
  },
  {
    "path": "SECURITY.md",
    "chars": 429,
    "preview": "# Security Policy\n\n## Reporting a Vulnerability\n\nPlease email security@redash.io to report any security vulnerabilities."
  },
  {
    "path": "bin/docker-entrypoint",
    "chars": 3496,
    "preview": "#!/bin/bash\nset -e\n\nscheduler() {\n  echo \"Starting RQ scheduler...\"\n\n  exec /app/manage.py rq scheduler\n}\n\ndev_scheduler"
  },
  {
    "path": "bin/get_changes.py",
    "chars": 1128,
    "preview": "#!/bin/env python3\n\nimport re\nimport subprocess\nimport sys\n\n\ndef get_change_log(previous_sha):\n    args = [\n        \"git"
  },
  {
    "path": "bin/release_manager.py",
    "chars": 5062,
    "preview": "#!/usr/bin/env python3\nimport os\nimport re\nimport subprocess\nimport sys\nfrom urllib.parse import urlparse\n\nimport reques"
  },
  {
    "path": "bin/run",
    "chars": 273,
    "preview": "#!/usr/bin/env bash\n\n# Ideally I would use stdin with source, but in older bash versions this\n# wasn't supported properl"
  },
  {
    "path": "client/.babelrc",
    "chars": 584,
    "preview": "{\n  \"presets\": [\n    [\n      \"@babel/preset-env\",\n      {\n        \"exclude\": [\"@babel/plugin-transform-async-to-generato"
  },
  {
    "path": "client/.eslintignore",
    "chars": 40,
    "preview": "build/*.js\ndist\nconfig/*.js\nclient/dist\n"
  },
  {
    "path": "client/.eslintrc.js",
    "chars": 3056,
    "preview": "module.exports = {\n  root: true,\n  parser: \"@typescript-eslint/parser\",\n  extends: [\n    \"react-app\",\n    \"plugin:compat"
  },
  {
    "path": "client/.gitignore",
    "chars": 5,
    "preview": "dist\n"
  },
  {
    "path": "client/app/.eslintrc.js",
    "chars": 175,
    "preview": "module.exports = {\n  extends: [\"plugin:jest/recommended\"],\n  plugins: [\"jest\"],\n  env: {\n    \"jest/globals\": true,\n  },\n"
  },
  {
    "path": "client/app/__tests__/enzyme_setup.js",
    "chars": 123,
    "preview": "import { configure } from \"enzyme\";\nimport Adapter from \"enzyme-adapter-react-16\";\n\nconfigure({ adapter: new Adapter() }"
  },
  {
    "path": "client/app/__tests__/mocks.js",
    "chars": 105,
    "preview": "import MockDate from \"mockdate\";\n\nconst date = new Date(\"2000-01-01T02:00:00.000\");\n\nMockDate.set(date);\n"
  },
  {
    "path": "client/app/assets/css/login.css",
    "chars": 1029,
    "preview": "body {\n  padding-top: 0px !important;\n  background-color: #FFFFFF;\n}\n\n.logo-container {\n  background-color: #668899;\n  d"
  },
  {
    "path": "client/app/assets/images/illustrations/readme.md",
    "chars": 390,
    "preview": "The illustrations shared in this folder are covered by the CC-BY-SA-NC-ND License v4.0 (or newer). You are allowed to us"
  },
  {
    "path": "client/app/assets/less/STYLING-README.md",
    "chars": 304,
    "preview": "# Styling readme\n\nSome general rules before you add stuff.\n\n- Avoid using inline css\n- If possible, use classes that are"
  },
  {
    "path": "client/app/assets/less/ant.less",
    "chars": 9202,
    "preview": "@import \"~antd/lib/style/core/iconfont\";\n@import \"~antd/lib/style/core/motion\";\n@import \"~antd/lib/alert/style/index\";\n@"
  },
  {
    "path": "client/app/assets/less/inc/404.less",
    "chars": 1095,
    "preview": ".four-zero {\r\n\tbackground: @white;\r\n\tbox-shadow: 0 1px 11px rgba(0, 0, 0, 0.27);\r\n\tborder-radius: 2px;\r\n\tposition: absol"
  },
  {
    "path": "client/app/assets/less/inc/ace-editor.less",
    "chars": 512,
    "preview": ".ace_editor {\n  border: 1px solid fade(@redash-gray, 15%);\n  height: 100%;\n  margin-bottom: 10px;\n\n  &.ace_autocomplete "
  },
  {
    "path": "client/app/assets/less/inc/alert.less",
    "chars": 804,
    "preview": ".alert-page h3 {\r\n  flex-grow: 1;\r\n\r\n  input {\r\n    margin: -0.2em 0;\r\n    width: 100%;\r\n    min-width: 170px;\r\n  }\r\n}\r\n"
  },
  {
    "path": "client/app/assets/less/inc/ant-variables.less",
    "chars": 2695,
    "preview": "/* --------------------------------------------------------\n    Colors\n-------------------------------------------------"
  },
  {
    "path": "client/app/assets/less/inc/base.less",
    "chars": 3332,
    "preview": "*,\nbutton,\ninput,\ni,\na {\n  -webkit-font-smoothing: antialiased;\n}\n\n*,\n*:active,\n*:hover {\n  outline: none !important;\n  "
  },
  {
    "path": "client/app/assets/less/inc/bootstrap-overrides.less",
    "chars": 775,
    "preview": "/** Media - Overriding the Media object to 3.2 version in order to prevent issues like text overflow. **/\n.media {\n    m"
  },
  {
    "path": "client/app/assets/less/inc/breadcrumb.less",
    "chars": 747,
    "preview": ".breadcrumb {\r\n    border-bottom: 1px solid #E5E5E5;\r\n    border-radius: 0;\r\n    padding-top: 10px;\r\n    padding-right: "
  },
  {
    "path": "client/app/assets/less/inc/button.less",
    "chars": 2732,
    "preview": ".btn {\r\n    &:not(.btn-alt) {\r\n        border: 0;\r\n    }\r\n\r\n    &[class*=\"bg-\"]:not(.bg-white) {\r\n        color: #fff;\r\n"
  },
  {
    "path": "client/app/assets/less/inc/carousel.less",
    "chars": 681,
    "preview": ".carousel-caption {\r\n    left: 0;\r\n    right: 0;\r\n    bottom: 0;\r\n    background: rgba(0,0,0,0.6);\r\n    \r\n    h3 {\r\n    "
  },
  {
    "path": "client/app/assets/less/inc/chart.less",
    "chars": 4667,
    "preview": "/* --------------------------------------------------------\r\n    Chart Helper Classes\r\n---------------------------------"
  },
  {
    "path": "client/app/assets/less/inc/dropdown.less",
    "chars": 1740,
    "preview": "\n.dropdown-menu {\n    z-index: 1000000000;\n    box-shadow: @dropdown-shadow;\n    margin-top: 1px;\n    border-width: 0;\n "
  },
  {
    "path": "client/app/assets/less/inc/edit-in-place.less",
    "chars": 333,
    "preview": ".edit-in-place {\n  white-space: pre-line;\n  display: inline-block;\n\n  p {\n    margin-bottom: 0;\n  }\n\n  .editable {\n    d"
  },
  {
    "path": "client/app/assets/less/inc/flex.less",
    "chars": 1940,
    "preview": ".d-flex         { display: flex !important; }\n.d-inline-flex  { display: inline-flex !important; }\n\n.flex-row           "
  },
  {
    "path": "client/app/assets/less/inc/font.less",
    "chars": 862,
    "preview": "///* --------------------------------------------------------\n//    Roboto Light - 300\n//-------------------------------"
  },
  {
    "path": "client/app/assets/less/inc/form.less",
    "chars": 5375,
    "preview": "label {\n  font-weight: 500;\n}\n\ntextarea.v-resizable {\n  resize: vertical;\n}\n\n.form-group {\n  &.required {\n    .control-l"
  },
  {
    "path": "client/app/assets/less/inc/generics.less",
    "chars": 5373,
    "preview": "/* --------------------------------------------------------\r\n    Generate Margin Classes (0px - 25px)\r\n    margin, margi"
  },
  {
    "path": "client/app/assets/less/inc/header.less",
    "chars": 8139,
    "preview": "#header {\r\n    width: 100%;\r\n    z-index: 10;\r\n    top: 0;\r\n    left: 0;\r\n    background-color: #fff;\r\n    height: @head"
  },
  {
    "path": "client/app/assets/less/inc/ie-warning.less",
    "chars": 765,
    "preview": ".ie-warning {\n\tposition: fixed;\n\ttop: 0;\n\tleft: 0;\n\tz-index: 9999;\n\tbackground: @black;\n\twidth: 100%;\n\theight: 100%;\n\tte"
  },
  {
    "path": "client/app/assets/less/inc/jumbotron.less",
    "chars": 66,
    "preview": ".jumbotron {\r\n    padding-left: 60px;\r\n    padding-right: 60px;\r\n}"
  },
  {
    "path": "client/app/assets/less/inc/label.less",
    "chars": 614,
    "preview": ".label {\r\n    border-radius: 2px;\r\n    padding: 3px 6px 4px;\r\n    font-weight: 500;\r\n    font-size: 11px;\r\n}\r\n\r\n.badge {"
  },
  {
    "path": "client/app/assets/less/inc/less-plugins/for.less",
    "chars": 347,
    "preview": "\r\n.for(@i, @n) {.-each(@i)}\r\n.for(@n)     when (isnumber(@n)) {.for(1, @n)}\r\n.for(@i, @n) when not (@i = @n)  {\r\n    .fo"
  },
  {
    "path": "client/app/assets/less/inc/list-group.less",
    "chars": 1356,
    "preview": ".list-group {\n    margin-bottom: 0;\n\n    &.lg-alt .list-group-item {\n        border: 0;\n    }\n\n    &:not(.lg-alt) {\n    "
  },
  {
    "path": "client/app/assets/less/inc/list.less",
    "chars": 423,
    "preview": ".clist {\r\n    list-style: none;\r\n    \r\n    & > li {\r\n        &:before {\r\n            font-family: @font-icon;\r\n         "
  },
  {
    "path": "client/app/assets/less/inc/login.less",
    "chars": 2690,
    "preview": ".login-content {\r\n    overflow: hidden;\r\n    height: 100%;\r\n    background: @brand-bg;\r\n    padding: 0;\r\n    text-align:"
  },
  {
    "path": "client/app/assets/less/inc/media.less",
    "chars": 2235,
    "preview": "/* --------------------------------------------------------\r\n    Thumbnail\r\n--------------------------------------------"
  },
  {
    "path": "client/app/assets/less/inc/messages.less",
    "chars": 3107,
    "preview": "#messages-main {\r\n    position: relative;\r\n    margin: 0 auto;\r\n    .clearfix();\r\n    \r\n    .ms-menu {\r\n        position"
  },
  {
    "path": "client/app/assets/less/inc/misc.less",
    "chars": 5025,
    "preview": "/* --------------------------------------------------------\r\n    Actions\r\n----------------------------------------------"
  },
  {
    "path": "client/app/assets/less/inc/mixins.less",
    "chars": 2457,
    "preview": "/* --------------------------------------------------------\r\n    Font Face\r\n--------------------------------------------"
  },
  {
    "path": "client/app/assets/less/inc/modal.less",
    "chars": 957,
    "preview": ".modal-header {\n    padding: 23px 26px;\n}\n\n.modal-body {\n    padding: 0 26px 10px;\n}\n\n.modal-content {\n    box-shadow: 0"
  },
  {
    "path": "client/app/assets/less/inc/panel.less",
    "chars": 2010,
    "preview": ".panel {\r\n    box-shadow: none;\r\n    border: 0;\r\n}\r\n\r\n.panel-heading {\r\n    padding: 0;\r\n    >p {\r\n      &:last-child {\r"
  },
  {
    "path": "client/app/assets/less/inc/photos.less",
    "chars": 1174,
    "preview": ".photos {\r\n    &:not(.pmb-block) {\r\n        margin: 10px 5px 0;\r\n    }\r\n    \r\n    .p-item {\r\n        padding: 0 3px;\r\n  "
  },
  {
    "path": "client/app/assets/less/inc/popover.less",
    "chars": 360,
    "preview": ".popover {\r\n    box-shadow: fade(@redash-gray, 25%) 0px 0px 15px 0px;\r\n}\r\n\r\n.popover-title {\r\n    border-bottom: 0;\r\n   "
  },
  {
    "path": "client/app/assets/less/inc/pricing-table.less",
    "chars": 1646,
    "preview": ".pricing-table {\r\n    margin-top: 50px;\r\n}\r\n\r\n.pt-inner {\r\n    text-align: center;\r\n    \r\n    .pti-header {\r\n          p"
  },
  {
    "path": "client/app/assets/less/inc/print.less",
    "chars": 1011,
    "preview": "@media print {    \r\n    @page {\r\n        margin: 0;\r\n        padding: 0;\r\n        size: auto;\r\n    }\r\n    \r\n    body, #c"
  },
  {
    "path": "client/app/assets/less/inc/profile.less",
    "chars": 7162,
    "preview": "#profile-main {\r\n    min-height: 500px;\r\n    position: relative;\r\n}\r\n\r\n.pm-overview {\r\n    overflow: hidden !important;\r"
  },
  {
    "path": "client/app/assets/less/inc/progress-bar.less",
    "chars": 162,
    "preview": ".progress {\r\n    box-shadow: none;\r\n    border-radius: 0;\r\n    height: 5px;\r\n    margin-bottom: 0;\r\n    \r\n    .progress-"
  },
  {
    "path": "client/app/assets/less/inc/schema-browser.less",
    "chars": 1959,
    "preview": ".schema-container {\n  height: 100%;\n  z-index: 10;\n  background-color: white;\n\n  .schema-browser {\n    overflow: hidden;"
  },
  {
    "path": "client/app/assets/less/inc/sidebar.less",
    "chars": 6624,
    "preview": "#sidebar {\r\n    background-color: @sidebar;\r\n    position: fixed;\r\n    left: 0;\r\n    top: @header-height;\r\n    z-index: "
  },
  {
    "path": "client/app/assets/less/inc/table.less",
    "chars": 2198,
    "preview": ".table {\n  margin-bottom: 0;\n\n  th.sortable-column {\n    cursor: pointer;\n  }\n\n  &:not(.table-striped) > thead > tr > th"
  },
  {
    "path": "client/app/assets/less/inc/tile.less",
    "chars": 1968,
    "preview": ".tile {\r\n    background-color: #fff;\r\n    margin-bottom: @grid-gutter-width;\r\n    position: relative;\r\n    border-radius"
  },
  {
    "path": "client/app/assets/less/inc/tooltips.less",
    "chars": 90,
    "preview": ".tooltip-inner {\r\n    border-radius: 1px;\r\n    padding: 5px 10px;\r\n    font-size: 12px;\r\n}"
  },
  {
    "path": "client/app/assets/less/inc/variables.less",
    "chars": 11371,
    "preview": "/* --------------------------------------------------------\n    Paths\n--------------------------------------------------"
  },
  {
    "path": "client/app/assets/less/inc/visualizations/box.less",
    "chars": 593,
    "preview": ".box {\r\n  font: 10px sans-serif;\r\n  line, rect, circle {\r\n    fill: #fff;\r\n    stroke: #000;\r\n    stroke-width: 1.5px;\r\n"
  },
  {
    "path": "client/app/assets/less/inc/visualizations/map.less",
    "chars": 195,
    "preview": ".map-visualization-container {\n  height: 500px;\n\n  > div:first-child {\n    width: 100%;\n    height: 100%;\n    z-index: 0"
  },
  {
    "path": "client/app/assets/less/inc/visualizations/misc.less",
    "chars": 101,
    "preview": ".visualization-renderer {\n  display: block;\n\n  .pagination,\n  .ant-pagination {\n    margin: 0;\n  }\n}\n"
  },
  {
    "path": "client/app/assets/less/inc/visualizations/pivot-table.less",
    "chars": 126,
    "preview": ".pivot-table-visualization-container > table,\n.visualization-renderer > .visualization-renderer-wrapper {\n  overflow: au"
  },
  {
    "path": "client/app/assets/less/inc/well.less",
    "chars": 79,
    "preview": ".well {\r\n    border-radius: 0;\r\n    background: #fff;\r\n    box-shadow: none;\r\n}"
  },
  {
    "path": "client/app/assets/less/inc/widgets.less",
    "chars": 589,
    "preview": "/* --------------------------------------------------------\r\n    User Signups\r\n-----------------------------------------"
  },
  {
    "path": "client/app/assets/less/main.less",
    "chars": 1398,
    "preview": "/** LESS Plugins **/\n@import \"inc/less-plugins/for\";\n\n/** Load Main Bootstrap LESS files **/\n@import \"~bootstrap/less/bo"
  },
  {
    "path": "client/app/assets/less/redash/css-logo.less",
    "chars": 1551,
    "preview": "// based on https://github.com/outbrain/tech-companies-logos-in-css/pull/28\n\n@primary: #ff7964;\n@shadow: #ef6c58;\n@bar: "
  },
  {
    "path": "client/app/assets/less/redash/loading-indicator.less",
    "chars": 914,
    "preview": ".loading-indicator {\n  position: fixed;\n  top: 50%;\n  left: 50%;\n  margin: -50px 0 0 -50px; // center\n  width: 100px;\n  "
  },
  {
    "path": "client/app/assets/less/redash/query.less",
    "chars": 8165,
    "preview": "body.fixed-layout {\n  padding: 0;\n  overflow: hidden;\n\n  #application-root {\n    display: flex;\n    flex-direction: row;"
  },
  {
    "path": "client/app/assets/less/redash/redash-table.less",
    "chars": 1842,
    "preview": ".table {\n  margin-bottom: 0;\n\n  [class*=\"bg-\"] {\n    & > tr > th {\n      color: #fff;\n      border-bottom: 0;\n      back"
  },
  {
    "path": "client/app/assets/less/redash/tags-control.less",
    "chars": 297,
    "preview": ".tags-control {\n  display: flex;\n  flex-direction: row;\n  flex-wrap: wrap;\n  align-items: stretch;\n  justify-content: fl"
  },
  {
    "path": "client/app/assets/less/server.less",
    "chars": 1171,
    "preview": "/** LESS Plugins **/\n@import 'inc/less-plugins/for';\n\n/** Load Main Bootstrap LESS files **/\n@import '~bootstrap/less/bo"
  },
  {
    "path": "client/app/assets/robots.txt",
    "chars": 31,
    "preview": "# robotstxt.org\n\nUser-agent: *\n"
  },
  {
    "path": "client/app/components/AceEditorInput.jsx",
    "chars": 507,
    "preview": "import React, { forwardRef } from \"react\";\nimport AceEditor from \"react-ace\";\n\nimport \"./AceEditorInput.less\";\n\nfunction"
  },
  {
    "path": "client/app/components/AceEditorInput.less",
    "chars": 202,
    "preview": ".ace-editor-input {\n  // hide ghost cursor when not focused\n  .ace_hidden-cursors {\n    opacity: 0;\n  }\n\n  // allow Ant "
  },
  {
    "path": "client/app/components/ApplicationArea/ApplicationLayout/DesktopNavbar.jsx",
    "chars": 7105,
    "preview": "import React, { useMemo } from \"react\";\nimport { first, includes } from \"lodash\";\nimport Menu from \"antd/lib/menu\";\nimpo"
  },
  {
    "path": "client/app/components/ApplicationArea/ApplicationLayout/DesktopNavbar.less",
    "chars": 3008,
    "preview": "@backgroundColor: #001529;\n@dividerColor: rgba(255, 255, 255, 0.5);\n@textColor: rgba(255, 255, 255, 0.75);\n@brandColor: "
  },
  {
    "path": "client/app/components/ApplicationArea/ApplicationLayout/MobileNavbar.jsx",
    "chars": 3146,
    "preview": "import { first } from \"lodash\";\nimport React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Button from \"antd/"
  },
  {
    "path": "client/app/components/ApplicationArea/ApplicationLayout/MobileNavbar.less",
    "chars": 636,
    "preview": "@backgroundColor: #001529;\n@dividerColor: rgba(255, 255, 255, 0.5);\n@textColor: rgba(255, 255, 255, 0.75);\n\n.mobile-navb"
  },
  {
    "path": "client/app/components/ApplicationArea/ApplicationLayout/VersionInfo.jsx",
    "chars": 925,
    "preview": "import React from \"react\";\nimport Link from \"@/components/Link\";\nimport { clientConfig, currentUser } from \"@/services/a"
  },
  {
    "path": "client/app/components/ApplicationArea/ApplicationLayout/index.jsx",
    "chars": 1333,
    "preview": "import React, { useRef, useCallback } from \"react\";\nimport PropTypes from \"prop-types\";\nimport DynamicComponent from \"@/"
  },
  {
    "path": "client/app/components/ApplicationArea/ApplicationLayout/index.less",
    "chars": 1544,
    "preview": "@mobileBreakpoint: ~\"(max-width: 767px)\";\n\nbody #application-root {\n  @topMenuHeight: 49px;\n\n  display: flex;\n  flex-dir"
  },
  {
    "path": "client/app/components/ApplicationArea/ErrorMessage.jsx",
    "chars": 1976,
    "preview": "import { get, isObject } from \"lodash\";\nimport React from \"react\";\nimport PropTypes from \"prop-types\";\n\nimport \"./ErrorM"
  },
  {
    "path": "client/app/components/ApplicationArea/ErrorMessage.less",
    "chars": 279,
    "preview": ".error-message-container {\n  width: 100%;\n  padding: 0 15px;\n  display: flex;\n  flex-direction: column;\n  align-items: c"
  },
  {
    "path": "client/app/components/ApplicationArea/ErrorMessage.test.js",
    "chars": 1789,
    "preview": "import React from \"react\";\nimport { mount } from \"enzyme\";\nimport ErrorMessage from \"./ErrorMessage\";\n\nconst ErrorMessag"
  },
  {
    "path": "client/app/components/ApplicationArea/ErrorMessageDetails.jsx",
    "chars": 273,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\n\nexport function ErrorMessageDetails(props) {\n  return <h"
  },
  {
    "path": "client/app/components/ApplicationArea/Router.jsx",
    "chars": 4649,
    "preview": "import { isFunction, startsWith, trimStart, trimEnd } from \"lodash\";\nimport React, { useState, useEffect, useRef, useCon"
  },
  {
    "path": "client/app/components/ApplicationArea/handleNavigationIntent.js",
    "chars": 717,
    "preview": "import { isString } from \"lodash\";\nimport navigateTo from \"./navigateTo\";\n\nexport default function handleNavigationInten"
  },
  {
    "path": "client/app/components/ApplicationArea/index.jsx",
    "chars": 1801,
    "preview": "import React, { useState, useEffect } from \"react\";\nimport routes from \"@/services/routes\";\nimport Router from \"./Router"
  },
  {
    "path": "client/app/components/ApplicationArea/navigateTo.js",
    "chars": 701,
    "preview": "import location from \"@/services/location\";\nimport url from \"@/services/url\";\nimport { stripBase } from \"./Router\";\n\n// "
  },
  {
    "path": "client/app/components/ApplicationArea/routeWithApiKeySession.jsx",
    "chars": 1862,
    "preview": "import React, { useEffect, useState, useContext } from \"react\";\nimport PropTypes from \"prop-types\";\nimport { ErrorBounda"
  },
  {
    "path": "client/app/components/ApplicationArea/routeWithUserSession.tsx",
    "chars": 3443,
    "preview": "import React, { useEffect, useState } from \"react\";\nimport ErrorBoundary, { ErrorBoundaryContext } from \"@redash/viz/lib"
  },
  {
    "path": "client/app/components/BeaconConsent.jsx",
    "chars": 2525,
    "preview": "import React, { useState } from \"react\";\nimport Card from \"antd/lib/card\";\nimport Button from \"antd/lib/button\";\nimport "
  },
  {
    "path": "client/app/components/BigMessage.jsx",
    "chars": 934,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport { useUniqueId } from \"@/lib/hooks/useUniqueId\";\nim"
  },
  {
    "path": "client/app/components/CodeBlock.jsx",
    "chars": 1805,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Button from \"antd/lib/button\";\nimport Tooltip from"
  },
  {
    "path": "client/app/components/CodeBlock.less",
    "chars": 438,
    "preview": "@import (reference, less) \"~@/assets/less/ant\";\n\n.code-block {\n  background: rgba(0, 0, 0, 0.06);\n  border: 1px solid rg"
  },
  {
    "path": "client/app/components/Collapse.jsx",
    "chars": 692,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport cx from \"classnames\";\nimport AntCollapse from \"ant"
  },
  {
    "path": "client/app/components/CreateSourceDialog.jsx",
    "chars": 6932,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport { isEmpty, toUpper, includes, get, uniqueId } from"
  },
  {
    "path": "client/app/components/DateInput.jsx",
    "chars": 1090,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport DatePicker from \"antd/lib/date-picker\";\nimport { c"
  },
  {
    "path": "client/app/components/DateRangeInput.jsx",
    "chars": 1263,
    "preview": "import { isArray } from \"lodash\";\nimport React from \"react\";\nimport PropTypes from \"prop-types\";\nimport DatePicker from "
  },
  {
    "path": "client/app/components/DateTimeInput.jsx",
    "chars": 1239,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport DatePicker from \"antd/lib/date-picker\";\nimport { c"
  },
  {
    "path": "client/app/components/DateTimeRangeInput.jsx",
    "chars": 1447,
    "preview": "import { isArray } from \"lodash\";\nimport React from \"react\";\nimport PropTypes from \"prop-types\";\nimport DatePicker from "
  },
  {
    "path": "client/app/components/DialogWrapper.d.ts",
    "chars": 895,
    "preview": "import { ModalProps } from \"antd/lib/modal/Modal\";\n\nexport interface DialogProps<ROk, RCancel> {\n  props: ModalProps;\n  "
  },
  {
    "path": "client/app/components/DialogWrapper.jsx",
    "chars": 6170,
    "preview": "import { isFunction } from \"lodash\";\nimport React from \"react\";\nimport PropTypes from \"prop-types\";\nimport ReactDOM from"
  },
  {
    "path": "client/app/components/DynamicComponent.jsx",
    "chars": 1405,
    "preview": "import { isFunction, isString, isUndefined } from \"lodash\";\nimport React from \"react\";\nimport PropTypes from \"prop-types"
  },
  {
    "path": "client/app/components/EditInPlace.jsx",
    "chars": 2662,
    "preview": "import { trim } from \"lodash\";\nimport React from \"react\";\nimport PropTypes from \"prop-types\";\nimport cx from \"classnames"
  },
  {
    "path": "client/app/components/EditParameterSettingsDialog.jsx",
    "chars": 9909,
    "preview": "import { includes, words, capitalize, clone, isNull } from \"lodash\";\nimport React, { useState, useEffect } from \"react\";"
  },
  {
    "path": "client/app/components/EditParameterSettingsDialog.less",
    "chars": 50,
    "preview": ".input-error {\n    border-color: red !important;\n}"
  },
  {
    "path": "client/app/components/EditVisualizationButton/QueryControlDropdown.jsx",
    "chars": 3496,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Dropdown from \"antd/lib/dropdown\";\nimport Menu fro"
  },
  {
    "path": "client/app/components/EditVisualizationButton/QueryResultsLink.jsx",
    "chars": 1295,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Link from \"@/components/Link\";\n\nexport default fun"
  },
  {
    "path": "client/app/components/EditVisualizationButton/index.jsx",
    "chars": 750,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Button from \"antd/lib/button\";\nimport FormOutlined"
  },
  {
    "path": "client/app/components/EmailSettingsWarning.jsx",
    "chars": 1624,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport { clientConfig, currentUser } from \"@/services/aut"
  },
  {
    "path": "client/app/components/FavoritesControl.jsx",
    "chars": 1181,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport PlainButton from \"@/components/PlainButton\";\n\nexpo"
  },
  {
    "path": "client/app/components/Filters.jsx",
    "chars": 5191,
    "preview": "import { isArray, indexOf, get, map, includes, every, some, toNumber } from \"lodash\";\nimport moment from \"moment\";\nimpor"
  },
  {
    "path": "client/app/components/HelpTrigger.jsx",
    "chars": 9709,
    "preview": "import { startsWith, get, some, mapValues } from \"lodash\";\nimport React from \"react\";\nimport PropTypes from \"prop-types\""
  },
  {
    "path": "client/app/components/HelpTrigger.less",
    "chars": 1803,
    "preview": "@import (reference, less) \"~@/assets/less/ant\";\n\n@help-doc-bg: #f7f7f7; // according to https://github.com/getredash/web"
  },
  {
    "path": "client/app/components/InputWithCopy.jsx",
    "chars": 1414,
    "preview": "import React from \"react\";\nimport Input from \"antd/lib/input\";\nimport CopyOutlinedIcon from \"@ant-design/icons/CopyOutli"
  },
  {
    "path": "client/app/components/Link.tsx",
    "chars": 1653,
    "preview": "import React from \"react\";\nimport Button, { ButtonProps as AntdButtonProps } from \"antd/lib/button\";\n\nfunction DefaultLi"
  },
  {
    "path": "client/app/components/NoTaggedObjectsFound.jsx",
    "chars": 630,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport BigMessage from \"@/components/BigMessage\";\nimport "
  },
  {
    "path": "client/app/components/PageHeader/index.jsx",
    "chars": 456,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\n\nimport \"./index.less\";\n\nexport default function PageHead"
  },
  {
    "path": "client/app/components/PageHeader/index.less",
    "chars": 328,
    "preview": ".page-header-wrapper {\n  margin: 15px 0 10px 0;\n  display: flex;\n  flex-direction: row;\n  flex-wrap: nowrap;\n  align-ite"
  },
  {
    "path": "client/app/components/Paginator.jsx",
    "chars": 1093,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Pagination from \"antd/lib/pagination\";\n\nconst MIN_"
  },
  {
    "path": "client/app/components/ParameterApplyButton.jsx",
    "chars": 1218,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Button from \"antd/lib/button\";\nimport Badge from \""
  },
  {
    "path": "client/app/components/ParameterMappingInput.jsx",
    "chars": 19075,
    "preview": "/* eslint-disable react/no-multi-comp */\n\nimport { isString, extend, each, has, map, includes, findIndex, find, fromPair"
  },
  {
    "path": "client/app/components/ParameterMappingInput.less",
    "chars": 1327,
    "preview": "@import (reference, less) \"~@/assets/less/ant\"; // for ant @vars\n\n.parameters-mapping-list {\n  .keyword {\n    max-width:"
  },
  {
    "path": "client/app/components/ParameterValueInput.jsx",
    "chars": 6053,
    "preview": "import { isEqual, isEmpty, map } from \"lodash\";\nimport React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Se"
  },
  {
    "path": "client/app/components/ParameterValueInput.less",
    "chars": 504,
    "preview": "@import (reference, less) \"~@/assets/less/ant\"; // for ant @vars\n\n@input-dirty: #fffce1;\n\n.parameter-input {\n  display: "
  },
  {
    "path": "client/app/components/Parameters.jsx",
    "chars": 6830,
    "preview": "import { size, filter, forEach, extend, isEmpty } from \"lodash\";\nimport React from \"react\";\nimport PropTypes from \"prop-"
  },
  {
    "path": "client/app/components/Parameters.less",
    "chars": 2297,
    "preview": "@import (reference, less) \"~@/assets/less/ant\";\n\n.parameter-block {\n  display: inline-block;\n  background: white;\n  padd"
  },
  {
    "path": "client/app/components/PermissionsEditorDialog/index.jsx",
    "chars": 7031,
    "preview": "import React, { useState, useEffect, useCallback } from \"react\";\nimport { axios } from \"@/services/axios\";\nimport PropTy"
  },
  {
    "path": "client/app/components/PermissionsEditorDialog/index.less",
    "chars": 191,
    "preview": ".permissions-editor-dialog {\n  .ant-select-dropdown-menu-item-disabled {\n    // make sure .text-muted has the disabled c"
  },
  {
    "path": "client/app/components/PlainButton.less",
    "chars": 389,
    "preview": "@import (reference, less) \"~@/assets/less/ant\";\n\n.plain-button {\n  all: unset;\n  transition: all 0.3s cubic-bezier(0.645"
  },
  {
    "path": "client/app/components/PlainButton.tsx",
    "chars": 514,
    "preview": "import classNames from \"classnames\";\nimport React from \"react\";\n\nimport \"./PlainButton.less\";\n\nexport interface PlainBut"
  },
  {
    "path": "client/app/components/PreviewCard.jsx",
    "chars": 2427,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport classNames from \"classnames\";\nimport Link from \"@/"
  },
  {
    "path": "client/app/components/QueryBasedParameterInput.jsx",
    "chars": 2959,
    "preview": "import { find, isArray, get, first, map, intersection, isEqual, isEmpty } from \"lodash\";\nimport React from \"react\";\nimpo"
  },
  {
    "path": "client/app/components/QueryLink.jsx",
    "chars": 1205,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport { VisualizationType } from \"@redash/viz/lib\";\nimpo"
  },
  {
    "path": "client/app/components/QueryLink.less",
    "chars": 117,
    "preview": ".query-link {\n  .visualization-name {\n    font-size: 15px;\n    font-weight: 500;\n    color: rgba(0, 0, 0, 0.8);\n  }\n}"
  },
  {
    "path": "client/app/components/QuerySelector.jsx",
    "chars": 5301,
    "preview": "import { find } from \"lodash\";\nimport React, { useState, useEffect } from \"react\";\nimport PropTypes from \"prop-types\";\ni"
  },
  {
    "path": "client/app/components/Resizable/index.jsx",
    "chars": 5726,
    "preview": "import d3 from \"d3\";\nimport React, { useRef, useMemo, useCallback, useState, useEffect } from \"react\";\nimport PropTypes "
  },
  {
    "path": "client/app/components/Resizable/index.less",
    "chars": 1104,
    "preview": "@import (reference, less) \"~@/assets/less/inc/variables.less\";\n\n.resizable-component.react-resizable {\n  position: relat"
  },
  {
    "path": "client/app/components/SelectItemsDialog.jsx",
    "chars": 6250,
    "preview": "import { filter, find, isEmpty, size } from \"lodash\";\nimport React, { useState, useCallback, useEffect } from \"react\";\ni"
  },
  {
    "path": "client/app/components/SelectItemsDialog.less",
    "chars": 155,
    "preview": ".select-items-list {\n  &:hover,\n  &:focus,\n  &:focus-within {\n    color: #555;\n    background-color: #f5f5f5;\n    transi"
  },
  {
    "path": "client/app/components/SelectWithVirtualScroll.tsx",
    "chars": 1343,
    "preview": "import React, { useMemo } from \"react\";\nimport { maxBy } from \"lodash\";\nimport AntdSelect, { SelectProps, LabeledValue }"
  },
  {
    "path": "client/app/components/SettingsWrapper.jsx",
    "chars": 1262,
    "preview": "import React from \"react\";\nimport Menu from \"antd/lib/menu\";\nimport PageHeader from \"@/components/PageHeader\";\nimport Li"
  },
  {
    "path": "client/app/components/TagsList.less",
    "chars": 1024,
    "preview": "@import (reference, less) \"~@/assets/less/ant\";\n\n.tags-list {\n  .tags-list-title {\n    margin: 15px 5px 5px 5px;\n    dis"
  },
  {
    "path": "client/app/components/TagsList.tsx",
    "chars": 2920,
    "preview": "import { map, includes, difference } from \"lodash\";\nimport React, { useState, useCallback, useEffect } from \"react\";\nimp"
  },
  {
    "path": "client/app/components/TimeAgo.jsx",
    "chars": 1591,
    "preview": "import moment from \"moment\";\nimport { isNil } from \"lodash\";\nimport React, { useEffect, useMemo, useState } from \"react\""
  },
  {
    "path": "client/app/components/Timer.jsx",
    "chars": 905,
    "preview": "import React, { useMemo, useState, useEffect } from \"react\";\nimport moment from \"moment\";\nimport PropTypes from \"prop-ty"
  },
  {
    "path": "client/app/components/Tooltip.tsx",
    "chars": 433,
    "preview": "import React from \"react\";\nimport AntTooltip, { TooltipProps } from \"antd/lib/tooltip\";\nimport { isNil } from \"lodash\";\n"
  },
  {
    "path": "client/app/components/UserGroups.jsx",
    "chars": 792,
    "preview": "import { map } from \"lodash\";\nimport React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Tag from \"antd/lib/t"
  },
  {
    "path": "client/app/components/UserGroups.less",
    "chars": 85,
    "preview": ".user-groups {\n  margin: -5px 0 0 -5px;\n\n  .ant-tag {\n    margin: 5px 0 0 5px;\n  }\n}\n"
  },
  {
    "path": "client/app/components/admin/Layout.jsx",
    "chars": 1157,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Menu from \"antd/lib/menu\";\nimport PageHeader from "
  },
  {
    "path": "client/app/components/admin/RQStatus.jsx",
    "chars": 3930,
    "preview": "import { map } from \"lodash\";\nimport React from \"react\";\nimport PropTypes from \"prop-types\";\n\nimport Badge from \"antd/li"
  },
  {
    "path": "client/app/components/admin/StatusBlock.jsx",
    "chars": 2699,
    "preview": "/* eslint-disable react/prop-types */\n\nimport { toPairs } from \"lodash\";\nimport React from \"react\";\n\nimport List from \"a"
  },
  {
    "path": "client/app/components/admin/layout.less",
    "chars": 64,
    "preview": ".admin-page-layout {\n  .ant-table {\n    overflow-x: auto;\n  }\n}\n"
  },
  {
    "path": "client/app/components/cards-list/CardsList.less",
    "chars": 1239,
    "preview": "@import (reference, less) \"~@/assets/less/inc/variables\";\n\n.visual-card-list {\n  width: 100%;\n  margin: -5px 0 0 -5px; /"
  },
  {
    "path": "client/app/components/cards-list/CardsList.tsx",
    "chars": 2459,
    "preview": "import { includes, isEmpty } from \"lodash\";\nimport PropTypes from \"prop-types\";\nimport React, { useState } from \"react\";"
  },
  {
    "path": "client/app/components/dashboards/AddWidgetDialog.jsx",
    "chars": 5078,
    "preview": "import { map, includes, groupBy, first, find } from \"lodash\";\nimport React, { useState, useMemo, useCallback } from \"rea"
  },
  {
    "path": "client/app/components/dashboards/AutoHeightController.js",
    "chars": 2806,
    "preview": "import { includes, reduce, some } from \"lodash\";\n\n// TODO: Revisit this implementation when migrating widget component t"
  },
  {
    "path": "client/app/components/dashboards/CreateDashboardDialog.jsx",
    "chars": 2246,
    "preview": "import { trim } from \"lodash\";\nimport React, { useState } from \"react\";\nimport Modal from \"antd/lib/modal\";\nimport Input"
  },
  {
    "path": "client/app/components/dashboards/DashboardGrid.jsx",
    "chars": 8665,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport { chain, cloneDeep, find } from \"lodash\";\nimport c"
  },
  {
    "path": "client/app/components/dashboards/EditParameterMappingsDialog.jsx",
    "chars": 3537,
    "preview": "import { isMatch, map, find, sortBy } from \"lodash\";\nimport React from \"react\";\nimport PropTypes from \"prop-types\";\nimpo"
  },
  {
    "path": "client/app/components/dashboards/ExpandedWidgetDialog.jsx",
    "chars": 1271,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Button from \"antd/lib/button\";\nimport Modal from \""
  },
  {
    "path": "client/app/components/dashboards/TextboxDialog.jsx",
    "chars": 3357,
    "preview": "import { toString } from \"lodash\";\nimport { markdown } from \"markdown\";\nimport React, { useState, useEffect, useCallback"
  },
  {
    "path": "client/app/components/dashboards/TextboxDialog.less",
    "chars": 262,
    "preview": ".textbox-dialog {\n  small {\n    display: block;\n    margin-top: 4px;\n  }\n\n  .preview {\n    padding: 9px 9px 1px;\n    bac"
  },
  {
    "path": "client/app/components/dashboards/dashboard-grid.less",
    "chars": 3746,
    "preview": ".dashboard-wrapper {\n  flex-grow: 1;\n  margin-bottom: 70px;\n\n  .layout {\n    margin: -15px -15px 0;\n  }\n\n  .tile {\n    d"
  },
  {
    "path": "client/app/components/dashboards/dashboard-widget/RestrictedWidget.jsx",
    "chars": 565,
    "preview": "import React from \"react\";\nimport Widget from \"./Widget\";\n\nfunction RestrictedWidget(props) {\n  return (\n    <Widget {.."
  },
  {
    "path": "client/app/components/dashboards/dashboard-widget/TextboxWidget.jsx",
    "chars": 1279,
    "preview": "import React, { useState } from \"react\";\nimport PropTypes from \"prop-types\";\nimport { markdown } from \"markdown\";\nimport"
  },
  {
    "path": "client/app/components/dashboards/dashboard-widget/VisualizationWidget.jsx",
    "chars": 12451,
    "preview": "import React, { useState } from \"react\";\nimport PropTypes from \"prop-types\";\nimport { compact, isEmpty, invoke, map } fr"
  },
  {
    "path": "client/app/components/dashboards/dashboard-widget/Widget.jsx",
    "chars": 4037,
    "preview": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport cx from \"classnames\";\nimport { isEmpty } from \"lod"
  },
  {
    "path": "client/app/components/dashboards/dashboard-widget/Widget.less",
    "chars": 4446,
    "preview": "@import (reference, less) \"~@/assets/less/inc/variables\";\n\n.widget-wrapper {\n  .widget-actions {\n    display: flex;\n    "
  }
]

// ... and 955 more files (download for full content)

About this extraction

This page contains the full source code of the getredash/redash GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1155 files (5.7 MB), approximately 1.5M tokens, and a symbol index with 4438 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!