2020-03-17 08:10:30 -05:00
|
|
|
import angular from 'angular';
|
2021-04-21 02:38:00 -05:00
|
|
|
import { castArray, isEqual } from 'lodash';
|
2020-11-27 03:20:57 -06:00
|
|
|
import { DataQuery, LoadingState, TimeRange, UrlQueryMap, UrlQueryValue } from '@grafana/data';
|
2020-03-10 02:53:41 -05:00
|
|
|
|
2020-03-16 00:32:04 -05:00
|
|
|
import {
|
2020-06-25 00:38:55 -05:00
|
|
|
DashboardVariableModel,
|
2020-10-02 00:02:06 -05:00
|
|
|
initialVariableModelState,
|
2020-06-25 00:38:55 -05:00
|
|
|
OrgVariableModel,
|
2020-03-16 00:32:04 -05:00
|
|
|
QueryVariableModel,
|
2020-06-25 00:38:55 -05:00
|
|
|
UserVariableModel,
|
|
|
|
VariableHide,
|
2020-03-16 00:32:04 -05:00
|
|
|
VariableModel,
|
|
|
|
VariableOption,
|
|
|
|
VariableRefresh,
|
2020-04-01 11:13:38 -05:00
|
|
|
VariableWithMultiSupport,
|
2020-04-20 00:37:38 -05:00
|
|
|
VariableWithOptions,
|
2020-06-04 06:44:48 -05:00
|
|
|
} from '../types';
|
2020-10-02 00:02:06 -05:00
|
|
|
import { AppNotification, StoreState, ThunkResult } from '../../../types';
|
2020-03-10 02:53:41 -05:00
|
|
|
import { getVariable, getVariables } from './selectors';
|
|
|
|
import { variableAdapters } from '../adapters';
|
|
|
|
import { Graph } from '../../../core/utils/dag';
|
Routing NG: Replace Angular routing with react-router (#31463)
* Add router packages
* Get react app root work instead of Angular one
* Logger util
* Patch Angular routing ($routeProvider, $routeParamsProvider)
* Use react-router-dom history instead of separate dependency
* Add test routes
* Sidemenu - use Link instead of anchors
* Patch Angular $location service (stub)
* WIP: geting rid of $location provider from TimeSrv
* Intercept anchor clicks to use history under the hood
* Sync Redux location slice with history state
* Make login/logout work
* Debug routes for testing
* Make force login work
* Make sure query param change does not recreate page components
* Hide side menu in specified locations
* Make the dashboar route query parameters work, make panel edit menu work
* Enable more routes
* Fix side menu
* Handle view modes
* Disable playlist routes
* Make SafeDynamicImport work again
* Bring back router-debug
* Separate redux location sync from route rendering
* Refactor updateLocation to thunk and move force refresh(login) to it
* Fixing init dashboard issue
* Support switching between dashboards without an unmount of DashboardPage
* More fixes for init dashboard and panel edit
* More type fixes
* Moving angular location wrapper out of main LocationService, and fixing typescript issues
* Fixed last typescript errors
* LocationService: Move to runtime and remove getLocationService and export singleston const instead (#31523)
* Moving location service implementation to runtime and removing get function and making it a package const singleton
* Added test that used locationService directly
* removed unused import
* AngularApp: Moving angular dependencies and the app boot out of the main app into it's own file (#31525)
* Fixes angular panels by calling the monkey patch
* Moving angular stuff to to it's own files
* udpated
* Fixing clicking on divs and spans inside anchor
* Moving app notifications out of angular app and removing angular directive wrapper
* Moving search from angular to react and removing angular search wrapper
* Clean up, tried to remove the redux location wrapper but requires a big update for DashboardPage, so adding it back
* Moving AppWrapper to root to limit circular dependencies (app/core -> app/routing and back)
* Open and close search now works
* Hide sidemenu when in kiosk mode
* Restoring some keybindings like ESC key
* Removed kiosk events and simplified it, just handled through updating URL
* Fixing typescript errors
* Simplified GrafanaRouteComponentProps and renamed to ContainerProps
* renamed back
* Changed AlertRuleList to use GrafanaRouteComponentProps and location.search passed to it
* Removing the reloadOnSearch property, this is not needed now for react as react by default does not unmount components when only url match or query parmas change
* SafeDynamicImport causing unmount un every search update, not sure how to fix yet
* Fix signature for SafeDynamicImport so we do not create new route components on every route render
* Removing the redux location wrapper as it was causing errors, and making dashboard page work with RouteProps (location, match) etc
* Updating DashboardPage and SoloPanelPage to use match params and history location
* Fixed DashboardPage tests
* Fixing solo route tests
* LocationService: Rename getCurrentLocation to just getLocation
* do not intercept link clicks with target blank or self
* Experimental useUrlParams hook
* Update DataSourceSettingsPage to use router match params
* fix links with urls that have no starting / to work like before
* Fix forceLogin
* Add queryParams to GrafanaRouteComponentProps
* PanelEditor get rid of updateLocation and location state
* Improve grafana route query params typing
* Add getSearchObject to LocationService
* Use DashboardPAge queryParams instead of location.search parsing
* Fix DashboardPage typing
* Fix some tests weirdness
* Bring back KeyboardSrv
* Fixes typescript issues
* Team pages now use router match params
* Get rid of from GrafanaRouteComponent props
* Removed unnessary calls to getSearchObject when calling locationService.partial
* Updated DashboardPage tests after queryParams was added
* Fixing dashboard settings back
* GrafanaRoute: Adding tests and remove use of global locationService
* Fixing tests and typescript errors
* Bring back kiosk modes and add tests
* Fix TimeSrv tests
* Fix typecheck errors
* Fixing tests
* Updated SideMenu test to react-testing and wrapped component in Router, and fixed issue importing createMemoryHistory
* Get rid of routeChange event from TimeSrv from
* Fixed TopSectionItem test
* Trying to make basename work but failing
* Update TopSectionItem snapshot
* Fix TopSectionItem snapshot test
* Fix API keys creation
* Remove Angular dependencies from KeybindingSrv (#31617)
* Remove Angular dependency from KeybindingsSrv
* Fix tests and typecheck issues
* basename is starting to work
* Make dashboard save work
* KeybindingSrv: Remove as angular service and no usage angular scope
* So long bridge_srv, we won't miss you
* Update snapshots
* Dashboard: Refactoring ChangeTracker to use History api and no angular (#31653)
* Dashboard: Refactoring ChangeTracker to use History api and no angular
* Updated
* Removed logging
* fixed unit tests
* updated snapshots
* Mechanism for force reloading routes (#31683)
* e2e: Fixes various things in e2e scenarios after router migration (#31685)
* Explore: Update reading query params from router props and updating location via locationService (ReactRouter) (#31688)
* RoutingNG: Initial explore redux location to router location migration
* Updated explore Wrapper tests
* Fixing more tests
* remove loggin
* rename back to make naming consistent
* Fixing return to dashboard button
* fixing navigation to explore from dashboard
* updated routeProps
* Updated tests
* Make DashboardListPage work
* Fixing navigation after add new data source, and fixes explore e2e
* Fixing solo panel page
* PluginsPage now works
* RoutingNG: When parsing and rendering url search/query params preseve old logic of handling booleans and arrays (#31725)
* RoutingNG: When parsing and rendering url search/query params preserve old logic of handling booleans and arrays
* Fixed test
* Make snapshots list work
* fixed alert notification channel edit page
* Simplify LocationService, did not need special handling for login or forceLogin as target _self on link already handles that
* fixed UserAdminPage
* fixed edit orgs page
* Fixing LdapPage
* fixing dashboard import
* Fixed new folder page
* Fixed data source dashboards page
* fixing Folder permissions and folder settings page
* fixing snapshot list page nav model
* remove unused file
* Added placeholder page for playlist
* Moved browser compatability to index-template
* Restored 404/default page
* Fixed reset password page
* Fixed SignUpInvited page
* Fixing CreateTeam, Create user page, add panel widget
* Restore browwser file to make tests happy
* Fixed unit tests
* Removed unused import
* Replacing usage of updateLocation
* Fixed test
* Updating search filters to use history / location service for filters
* remove unused file
* AppRootPage fixed
* Fixing test and search issue
* Changes to support enterprise extensions
* remove console.log
* Removing more use of redux location
* Fixed signup page
* removed unused old angular controllers
* Fixing bugs
* one final bugfix
* Removed location from redux state
* Fixing ts issues and tests
* Fixing test issue
* fixing tests
* Fixing tests
* removed unused stuff
* Fixed search test
* Adding some doc comments
* Routing NG: Angular location provider patch (#31773)
* Patch Angulars $location provider
* Update public/app/angular/bridgeReactAngularRouting.ts
* Remove only test
* Update tests, disable loggers in test env
* Routing NG: remove $location provider usage (#31816)
* Remove dashboard_loaders
* Remove $location from Analytics service, track page views form GrafanaRoute
* Remove NotificationsEditCtrl
* Remove Angular dependencies from uploadDashboardDirective
* Update public/app/features/dashboard/containers/DashboardPage.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Update public/app/features/dashboard/containers/DashboardPage.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Remove unused test helpers (#31831)
* Playlist react (#31829)
* playlist list in react
* Playlist start
* Things started to work
* Updated
* Handle empty list
* Fix ts
* Fixes and kiosk mode stuff
* Removed unused events
* fixing ts issue
* Another ts issue
* Fixing tests
Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>
* fixed test
* Update public/app/AppWrapper.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Update public/app/AppWrapper.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Remove Angular dependency from DashboardLoaderSrv (#31863)
Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
Co-authored-by: Torkel Ödegaard <torkel@grafana.org>
Co-authored-by: Hugo Häggmark <hugo.haggmark@grafana.com>
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
2021-03-10 11:03:36 -06:00
|
|
|
import { notifyApp } from 'app/core/actions';
|
2020-04-01 11:13:38 -05:00
|
|
|
import {
|
|
|
|
addVariable,
|
2020-04-20 00:37:38 -05:00
|
|
|
changeVariableProp,
|
2020-04-01 11:13:38 -05:00
|
|
|
setCurrentVariableValue,
|
2020-10-02 00:02:06 -05:00
|
|
|
variableStateCompleted,
|
|
|
|
variableStateFailed,
|
|
|
|
variableStateFetching,
|
|
|
|
variableStateNotStarted,
|
2020-04-01 11:13:38 -05:00
|
|
|
} from './sharedReducer';
|
2020-11-10 23:19:09 -06:00
|
|
|
import {
|
|
|
|
ALL_VARIABLE_TEXT,
|
|
|
|
ALL_VARIABLE_VALUE,
|
|
|
|
toVariableIdentifier,
|
|
|
|
toVariablePayload,
|
|
|
|
VariableIdentifier,
|
|
|
|
} from './types';
|
2020-04-03 02:38:14 -05:00
|
|
|
import { contextSrv } from 'app/core/services/context_srv';
|
2020-10-01 12:51:23 -05:00
|
|
|
import { getTemplateSrv, TemplateSrv } from '../../templating/template_srv';
|
2020-04-01 11:13:38 -05:00
|
|
|
import { alignCurrentWithMulti } from '../shared/multiOptions';
|
2020-11-27 03:20:57 -06:00
|
|
|
import { hasLegacyVariableSupport, hasStandardVariableSupport, isMulti, isQuery } from '../guard';
|
2020-04-03 02:38:14 -05:00
|
|
|
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
|
|
|
import { DashboardModel } from 'app/features/dashboard/state';
|
2020-06-04 01:59:57 -05:00
|
|
|
import { createErrorNotification } from '../../../core/copy/appNotification';
|
|
|
|
import {
|
|
|
|
TransactionStatus,
|
|
|
|
variablesClearTransaction,
|
|
|
|
variablesCompleteTransaction,
|
|
|
|
variablesInitTransaction,
|
|
|
|
} from './transactionReducer';
|
|
|
|
import { getBackendSrv } from '../../../core/services/backend_srv';
|
|
|
|
import { cleanVariables } from './variablesReducer';
|
2021-03-15 02:52:44 -05:00
|
|
|
import { ensureStringValues, getCurrentText, getVariableRefresh } from '../utils';
|
2020-10-02 00:02:06 -05:00
|
|
|
import { store } from 'app/store/store';
|
2020-11-27 03:20:57 -06:00
|
|
|
import { getDatasourceSrv } from '../../plugins/datasource_srv';
|
2021-02-02 02:13:39 -06:00
|
|
|
import { cleanEditorState } from '../editor/reducer';
|
|
|
|
import { cleanPickerState } from '../pickers/OptionsPicker/reducer';
|
Routing NG: Replace Angular routing with react-router (#31463)
* Add router packages
* Get react app root work instead of Angular one
* Logger util
* Patch Angular routing ($routeProvider, $routeParamsProvider)
* Use react-router-dom history instead of separate dependency
* Add test routes
* Sidemenu - use Link instead of anchors
* Patch Angular $location service (stub)
* WIP: geting rid of $location provider from TimeSrv
* Intercept anchor clicks to use history under the hood
* Sync Redux location slice with history state
* Make login/logout work
* Debug routes for testing
* Make force login work
* Make sure query param change does not recreate page components
* Hide side menu in specified locations
* Make the dashboar route query parameters work, make panel edit menu work
* Enable more routes
* Fix side menu
* Handle view modes
* Disable playlist routes
* Make SafeDynamicImport work again
* Bring back router-debug
* Separate redux location sync from route rendering
* Refactor updateLocation to thunk and move force refresh(login) to it
* Fixing init dashboard issue
* Support switching between dashboards without an unmount of DashboardPage
* More fixes for init dashboard and panel edit
* More type fixes
* Moving angular location wrapper out of main LocationService, and fixing typescript issues
* Fixed last typescript errors
* LocationService: Move to runtime and remove getLocationService and export singleston const instead (#31523)
* Moving location service implementation to runtime and removing get function and making it a package const singleton
* Added test that used locationService directly
* removed unused import
* AngularApp: Moving angular dependencies and the app boot out of the main app into it's own file (#31525)
* Fixes angular panels by calling the monkey patch
* Moving angular stuff to to it's own files
* udpated
* Fixing clicking on divs and spans inside anchor
* Moving app notifications out of angular app and removing angular directive wrapper
* Moving search from angular to react and removing angular search wrapper
* Clean up, tried to remove the redux location wrapper but requires a big update for DashboardPage, so adding it back
* Moving AppWrapper to root to limit circular dependencies (app/core -> app/routing and back)
* Open and close search now works
* Hide sidemenu when in kiosk mode
* Restoring some keybindings like ESC key
* Removed kiosk events and simplified it, just handled through updating URL
* Fixing typescript errors
* Simplified GrafanaRouteComponentProps and renamed to ContainerProps
* renamed back
* Changed AlertRuleList to use GrafanaRouteComponentProps and location.search passed to it
* Removing the reloadOnSearch property, this is not needed now for react as react by default does not unmount components when only url match or query parmas change
* SafeDynamicImport causing unmount un every search update, not sure how to fix yet
* Fix signature for SafeDynamicImport so we do not create new route components on every route render
* Removing the redux location wrapper as it was causing errors, and making dashboard page work with RouteProps (location, match) etc
* Updating DashboardPage and SoloPanelPage to use match params and history location
* Fixed DashboardPage tests
* Fixing solo route tests
* LocationService: Rename getCurrentLocation to just getLocation
* do not intercept link clicks with target blank or self
* Experimental useUrlParams hook
* Update DataSourceSettingsPage to use router match params
* fix links with urls that have no starting / to work like before
* Fix forceLogin
* Add queryParams to GrafanaRouteComponentProps
* PanelEditor get rid of updateLocation and location state
* Improve grafana route query params typing
* Add getSearchObject to LocationService
* Use DashboardPAge queryParams instead of location.search parsing
* Fix DashboardPage typing
* Fix some tests weirdness
* Bring back KeyboardSrv
* Fixes typescript issues
* Team pages now use router match params
* Get rid of from GrafanaRouteComponent props
* Removed unnessary calls to getSearchObject when calling locationService.partial
* Updated DashboardPage tests after queryParams was added
* Fixing dashboard settings back
* GrafanaRoute: Adding tests and remove use of global locationService
* Fixing tests and typescript errors
* Bring back kiosk modes and add tests
* Fix TimeSrv tests
* Fix typecheck errors
* Fixing tests
* Updated SideMenu test to react-testing and wrapped component in Router, and fixed issue importing createMemoryHistory
* Get rid of routeChange event from TimeSrv from
* Fixed TopSectionItem test
* Trying to make basename work but failing
* Update TopSectionItem snapshot
* Fix TopSectionItem snapshot test
* Fix API keys creation
* Remove Angular dependencies from KeybindingSrv (#31617)
* Remove Angular dependency from KeybindingsSrv
* Fix tests and typecheck issues
* basename is starting to work
* Make dashboard save work
* KeybindingSrv: Remove as angular service and no usage angular scope
* So long bridge_srv, we won't miss you
* Update snapshots
* Dashboard: Refactoring ChangeTracker to use History api and no angular (#31653)
* Dashboard: Refactoring ChangeTracker to use History api and no angular
* Updated
* Removed logging
* fixed unit tests
* updated snapshots
* Mechanism for force reloading routes (#31683)
* e2e: Fixes various things in e2e scenarios after router migration (#31685)
* Explore: Update reading query params from router props and updating location via locationService (ReactRouter) (#31688)
* RoutingNG: Initial explore redux location to router location migration
* Updated explore Wrapper tests
* Fixing more tests
* remove loggin
* rename back to make naming consistent
* Fixing return to dashboard button
* fixing navigation to explore from dashboard
* updated routeProps
* Updated tests
* Make DashboardListPage work
* Fixing navigation after add new data source, and fixes explore e2e
* Fixing solo panel page
* PluginsPage now works
* RoutingNG: When parsing and rendering url search/query params preseve old logic of handling booleans and arrays (#31725)
* RoutingNG: When parsing and rendering url search/query params preserve old logic of handling booleans and arrays
* Fixed test
* Make snapshots list work
* fixed alert notification channel edit page
* Simplify LocationService, did not need special handling for login or forceLogin as target _self on link already handles that
* fixed UserAdminPage
* fixed edit orgs page
* Fixing LdapPage
* fixing dashboard import
* Fixed new folder page
* Fixed data source dashboards page
* fixing Folder permissions and folder settings page
* fixing snapshot list page nav model
* remove unused file
* Added placeholder page for playlist
* Moved browser compatability to index-template
* Restored 404/default page
* Fixed reset password page
* Fixed SignUpInvited page
* Fixing CreateTeam, Create user page, add panel widget
* Restore browwser file to make tests happy
* Fixed unit tests
* Removed unused import
* Replacing usage of updateLocation
* Fixed test
* Updating search filters to use history / location service for filters
* remove unused file
* AppRootPage fixed
* Fixing test and search issue
* Changes to support enterprise extensions
* remove console.log
* Removing more use of redux location
* Fixed signup page
* removed unused old angular controllers
* Fixing bugs
* one final bugfix
* Removed location from redux state
* Fixing ts issues and tests
* Fixing test issue
* fixing tests
* Fixing tests
* removed unused stuff
* Fixed search test
* Adding some doc comments
* Routing NG: Angular location provider patch (#31773)
* Patch Angulars $location provider
* Update public/app/angular/bridgeReactAngularRouting.ts
* Remove only test
* Update tests, disable loggers in test env
* Routing NG: remove $location provider usage (#31816)
* Remove dashboard_loaders
* Remove $location from Analytics service, track page views form GrafanaRoute
* Remove NotificationsEditCtrl
* Remove Angular dependencies from uploadDashboardDirective
* Update public/app/features/dashboard/containers/DashboardPage.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Update public/app/features/dashboard/containers/DashboardPage.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Remove unused test helpers (#31831)
* Playlist react (#31829)
* playlist list in react
* Playlist start
* Things started to work
* Updated
* Handle empty list
* Fix ts
* Fixes and kiosk mode stuff
* Removed unused events
* fixing ts issue
* Another ts issue
* Fixing tests
Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>
* fixed test
* Update public/app/AppWrapper.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Update public/app/AppWrapper.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Remove Angular dependency from DashboardLoaderSrv (#31863)
Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
Co-authored-by: Torkel Ödegaard <torkel@grafana.org>
Co-authored-by: Hugo Häggmark <hugo.haggmark@grafana.com>
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
2021-03-10 11:03:36 -06:00
|
|
|
import { locationService } from '@grafana/runtime';
|
2020-03-10 02:53:41 -05:00
|
|
|
|
|
|
|
// process flow queryVariable
|
|
|
|
// thunk => processVariables
|
|
|
|
// adapter => setValueFromUrl
|
|
|
|
// thunk => setOptionFromUrl
|
|
|
|
// adapter => updateOptions
|
|
|
|
// thunk => updateQueryVariableOptions
|
|
|
|
// action => updateVariableOptions
|
|
|
|
// action => updateVariableTags
|
|
|
|
// thunk => validateVariableSelectionState
|
|
|
|
// adapter => setValue
|
|
|
|
// thunk => setOptionAsCurrent
|
|
|
|
// action => setCurrentVariableValue
|
|
|
|
// thunk => variableUpdated
|
|
|
|
// adapter => updateOptions for dependent nodes
|
|
|
|
// adapter => setValue
|
|
|
|
// thunk => setOptionAsCurrent
|
|
|
|
// action => setCurrentVariableValue
|
|
|
|
// thunk => variableUpdated
|
|
|
|
// adapter => updateOptions for dependent nodes
|
|
|
|
// adapter => updateOptions
|
|
|
|
// thunk => updateQueryVariableOptions
|
|
|
|
// action => updateVariableOptions
|
|
|
|
// action => updateVariableTags
|
|
|
|
// thunk => validateVariableSelectionState
|
|
|
|
// adapter => setValue
|
|
|
|
// thunk => setOptionAsCurrent
|
|
|
|
// action => setCurrentVariableValue
|
|
|
|
// thunk => variableUpdated
|
|
|
|
// adapter => updateOptions for dependent nodes
|
|
|
|
|
|
|
|
export const initDashboardTemplating = (list: VariableModel[]): ThunkResult<void> => {
|
|
|
|
return (dispatch, getState) => {
|
|
|
|
let orderIndex = 0;
|
|
|
|
for (let index = 0; index < list.length; index++) {
|
|
|
|
const model = list[index];
|
2020-03-23 09:33:17 -05:00
|
|
|
if (!variableAdapters.getIfExists(model.type)) {
|
2020-03-10 02:53:41 -05:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
dispatch(addVariable(toVariablePayload(model, { global: false, index: orderIndex++, model })));
|
|
|
|
}
|
|
|
|
|
2020-10-01 12:51:23 -05:00
|
|
|
getTemplateSrv().updateTimeRange(getTimeSrv().timeRange());
|
2020-04-03 02:38:14 -05:00
|
|
|
|
2020-11-27 03:20:57 -06:00
|
|
|
const variables = getVariables(getState());
|
|
|
|
for (let index = 0; index < variables.length; index++) {
|
|
|
|
const variable = variables[index];
|
|
|
|
dispatch(variableStateNotStarted(toVariablePayload(variable)));
|
2020-03-10 02:53:41 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2020-07-28 09:05:29 -05:00
|
|
|
export const addSystemTemplateVariables = (dashboard: DashboardModel): ThunkResult<void> => {
|
2020-04-03 02:38:14 -05:00
|
|
|
return (dispatch, getState) => {
|
2020-06-25 00:38:55 -05:00
|
|
|
const dashboardModel: DashboardVariableModel = {
|
2020-10-02 00:02:06 -05:00
|
|
|
...initialVariableModelState,
|
2020-06-25 00:38:55 -05:00
|
|
|
id: '__dashboard',
|
|
|
|
name: '__dashboard',
|
|
|
|
type: 'system',
|
|
|
|
index: -3,
|
|
|
|
skipUrlSync: true,
|
|
|
|
hide: VariableHide.hideVariable,
|
|
|
|
current: {
|
|
|
|
value: {
|
|
|
|
name: dashboard.title,
|
|
|
|
uid: dashboard.uid,
|
|
|
|
toString: () => dashboard.title,
|
2020-04-03 02:38:14 -05:00
|
|
|
},
|
|
|
|
},
|
2020-06-25 00:38:55 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
dispatch(
|
|
|
|
addVariable(
|
|
|
|
toVariablePayload(dashboardModel, {
|
|
|
|
global: dashboardModel.global,
|
|
|
|
index: dashboardModel.index,
|
|
|
|
model: dashboardModel,
|
|
|
|
})
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
const orgModel: OrgVariableModel = {
|
2020-10-02 00:02:06 -05:00
|
|
|
...initialVariableModelState,
|
2020-06-25 00:38:55 -05:00
|
|
|
id: '__org',
|
|
|
|
name: '__org',
|
|
|
|
type: 'system',
|
|
|
|
index: -2,
|
|
|
|
skipUrlSync: true,
|
|
|
|
hide: VariableHide.hideVariable,
|
|
|
|
current: {
|
|
|
|
value: {
|
|
|
|
name: contextSrv.user.orgName,
|
|
|
|
id: contextSrv.user.orgId,
|
|
|
|
toString: () => contextSrv.user.orgId.toString(),
|
2020-04-03 02:38:14 -05:00
|
|
|
},
|
|
|
|
},
|
2020-06-25 00:38:55 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
dispatch(
|
|
|
|
addVariable(toVariablePayload(orgModel, { global: orgModel.global, index: orgModel.index, model: orgModel }))
|
|
|
|
);
|
|
|
|
|
|
|
|
const userModel: UserVariableModel = {
|
2020-10-02 00:02:06 -05:00
|
|
|
...initialVariableModelState,
|
2020-06-25 00:38:55 -05:00
|
|
|
id: '__user',
|
|
|
|
name: '__user',
|
|
|
|
type: 'system',
|
|
|
|
index: -1,
|
|
|
|
skipUrlSync: true,
|
|
|
|
hide: VariableHide.hideVariable,
|
|
|
|
current: {
|
|
|
|
value: {
|
|
|
|
login: contextSrv.user.login,
|
|
|
|
id: contextSrv.user.id,
|
2020-11-05 08:26:08 -06:00
|
|
|
email: contextSrv.user.email,
|
2020-06-25 00:38:55 -05:00
|
|
|
toString: () => contextSrv.user.id.toString(),
|
2020-06-02 01:47:54 -05:00
|
|
|
},
|
|
|
|
},
|
2020-06-25 00:38:55 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
dispatch(
|
|
|
|
addVariable(toVariablePayload(userModel, { global: userModel.global, index: userModel.index, model: userModel }))
|
|
|
|
);
|
2020-04-03 02:38:14 -05:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2020-04-01 11:13:38 -05:00
|
|
|
export const changeVariableMultiValue = (identifier: VariableIdentifier, multi: boolean): ThunkResult<void> => {
|
|
|
|
return (dispatch, getState) => {
|
2020-06-04 06:44:48 -05:00
|
|
|
const variable = getVariable<VariableWithMultiSupport>(identifier.id, getState());
|
2020-04-01 11:13:38 -05:00
|
|
|
const current = alignCurrentWithMulti(variable.current, multi);
|
|
|
|
|
|
|
|
dispatch(changeVariableProp(toVariablePayload(identifier, { propName: 'multi', propValue: multi })));
|
|
|
|
dispatch(changeVariableProp(toVariablePayload(identifier, { propName: 'current', propValue: current })));
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2020-03-10 02:53:41 -05:00
|
|
|
export const processVariableDependencies = async (variable: VariableModel, state: StoreState) => {
|
2020-10-02 00:02:06 -05:00
|
|
|
const dependencies: VariableModel[] = [];
|
2020-03-10 02:53:41 -05:00
|
|
|
|
|
|
|
for (const otherVariable of getVariables(state)) {
|
|
|
|
if (variable === otherVariable) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-03-23 09:33:17 -05:00
|
|
|
if (variableAdapters.getIfExists(variable.type)) {
|
2020-03-10 02:53:41 -05:00
|
|
|
if (variableAdapters.get(variable.type).dependsOn(variable, otherVariable)) {
|
2020-10-02 00:02:06 -05:00
|
|
|
dependencies.push(otherVariable);
|
2020-03-10 02:53:41 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-02 00:02:06 -05:00
|
|
|
if (!isWaitingForDependencies(dependencies, state)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-01-20 00:59:48 -06:00
|
|
|
await new Promise<void>((resolve) => {
|
2020-10-02 00:02:06 -05:00
|
|
|
const unsubscribe = store.subscribe(() => {
|
|
|
|
if (!isWaitingForDependencies(dependencies, store.getState())) {
|
|
|
|
unsubscribe();
|
|
|
|
resolve();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const isWaitingForDependencies = (dependencies: VariableModel[], state: StoreState): boolean => {
|
|
|
|
if (dependencies.length === 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const variables = getVariables(state);
|
2021-01-20 00:59:48 -06:00
|
|
|
const notCompletedDependencies = dependencies.filter((d) =>
|
|
|
|
variables.some((v) => v.id === d.id && (v.state === LoadingState.NotStarted || v.state === LoadingState.Loading))
|
2020-10-02 00:02:06 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
return notCompletedDependencies.length > 0;
|
2020-03-10 02:53:41 -05:00
|
|
|
};
|
|
|
|
|
2020-04-03 02:38:14 -05:00
|
|
|
export const processVariable = (
|
|
|
|
identifier: VariableIdentifier,
|
|
|
|
queryParams: UrlQueryMap
|
|
|
|
): ThunkResult<Promise<void>> => {
|
2020-03-10 02:53:41 -05:00
|
|
|
return async (dispatch, getState) => {
|
2020-06-04 06:44:48 -05:00
|
|
|
const variable = getVariable(identifier.id, getState());
|
2020-03-10 02:53:41 -05:00
|
|
|
await processVariableDependencies(variable, getState());
|
|
|
|
|
|
|
|
const urlValue = queryParams['var-' + variable.name];
|
|
|
|
if (urlValue !== void 0) {
|
2021-03-15 02:52:44 -05:00
|
|
|
const stringUrlValue = ensureStringValues(urlValue);
|
|
|
|
await variableAdapters.get(variable.type).setValueFromUrl(variable, stringUrlValue);
|
2020-03-10 02:53:41 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (variable.hasOwnProperty('refresh')) {
|
|
|
|
const refreshableVariable = variable as QueryVariableModel;
|
|
|
|
if (
|
|
|
|
refreshableVariable.refresh === VariableRefresh.onDashboardLoad ||
|
|
|
|
refreshableVariable.refresh === VariableRefresh.onTimeRangeChanged
|
|
|
|
) {
|
2020-10-02 00:02:06 -05:00
|
|
|
await dispatch(updateOptions(toVariableIdentifier(refreshableVariable)));
|
2020-03-10 02:53:41 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-01 11:17:39 -05:00
|
|
|
// for variables that aren't updated via URL or refresh, let's simulate the same state changes
|
2020-10-14 10:07:42 -05:00
|
|
|
dispatch(completeVariableLoading(identifier));
|
2020-03-10 02:53:41 -05:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2020-04-03 02:38:14 -05:00
|
|
|
export const processVariables = (): ThunkResult<Promise<void>> => {
|
2020-03-10 02:53:41 -05:00
|
|
|
return async (dispatch, getState) => {
|
Routing NG: Replace Angular routing with react-router (#31463)
* Add router packages
* Get react app root work instead of Angular one
* Logger util
* Patch Angular routing ($routeProvider, $routeParamsProvider)
* Use react-router-dom history instead of separate dependency
* Add test routes
* Sidemenu - use Link instead of anchors
* Patch Angular $location service (stub)
* WIP: geting rid of $location provider from TimeSrv
* Intercept anchor clicks to use history under the hood
* Sync Redux location slice with history state
* Make login/logout work
* Debug routes for testing
* Make force login work
* Make sure query param change does not recreate page components
* Hide side menu in specified locations
* Make the dashboar route query parameters work, make panel edit menu work
* Enable more routes
* Fix side menu
* Handle view modes
* Disable playlist routes
* Make SafeDynamicImport work again
* Bring back router-debug
* Separate redux location sync from route rendering
* Refactor updateLocation to thunk and move force refresh(login) to it
* Fixing init dashboard issue
* Support switching between dashboards without an unmount of DashboardPage
* More fixes for init dashboard and panel edit
* More type fixes
* Moving angular location wrapper out of main LocationService, and fixing typescript issues
* Fixed last typescript errors
* LocationService: Move to runtime and remove getLocationService and export singleston const instead (#31523)
* Moving location service implementation to runtime and removing get function and making it a package const singleton
* Added test that used locationService directly
* removed unused import
* AngularApp: Moving angular dependencies and the app boot out of the main app into it's own file (#31525)
* Fixes angular panels by calling the monkey patch
* Moving angular stuff to to it's own files
* udpated
* Fixing clicking on divs and spans inside anchor
* Moving app notifications out of angular app and removing angular directive wrapper
* Moving search from angular to react and removing angular search wrapper
* Clean up, tried to remove the redux location wrapper but requires a big update for DashboardPage, so adding it back
* Moving AppWrapper to root to limit circular dependencies (app/core -> app/routing and back)
* Open and close search now works
* Hide sidemenu when in kiosk mode
* Restoring some keybindings like ESC key
* Removed kiosk events and simplified it, just handled through updating URL
* Fixing typescript errors
* Simplified GrafanaRouteComponentProps and renamed to ContainerProps
* renamed back
* Changed AlertRuleList to use GrafanaRouteComponentProps and location.search passed to it
* Removing the reloadOnSearch property, this is not needed now for react as react by default does not unmount components when only url match or query parmas change
* SafeDynamicImport causing unmount un every search update, not sure how to fix yet
* Fix signature for SafeDynamicImport so we do not create new route components on every route render
* Removing the redux location wrapper as it was causing errors, and making dashboard page work with RouteProps (location, match) etc
* Updating DashboardPage and SoloPanelPage to use match params and history location
* Fixed DashboardPage tests
* Fixing solo route tests
* LocationService: Rename getCurrentLocation to just getLocation
* do not intercept link clicks with target blank or self
* Experimental useUrlParams hook
* Update DataSourceSettingsPage to use router match params
* fix links with urls that have no starting / to work like before
* Fix forceLogin
* Add queryParams to GrafanaRouteComponentProps
* PanelEditor get rid of updateLocation and location state
* Improve grafana route query params typing
* Add getSearchObject to LocationService
* Use DashboardPAge queryParams instead of location.search parsing
* Fix DashboardPage typing
* Fix some tests weirdness
* Bring back KeyboardSrv
* Fixes typescript issues
* Team pages now use router match params
* Get rid of from GrafanaRouteComponent props
* Removed unnessary calls to getSearchObject when calling locationService.partial
* Updated DashboardPage tests after queryParams was added
* Fixing dashboard settings back
* GrafanaRoute: Adding tests and remove use of global locationService
* Fixing tests and typescript errors
* Bring back kiosk modes and add tests
* Fix TimeSrv tests
* Fix typecheck errors
* Fixing tests
* Updated SideMenu test to react-testing and wrapped component in Router, and fixed issue importing createMemoryHistory
* Get rid of routeChange event from TimeSrv from
* Fixed TopSectionItem test
* Trying to make basename work but failing
* Update TopSectionItem snapshot
* Fix TopSectionItem snapshot test
* Fix API keys creation
* Remove Angular dependencies from KeybindingSrv (#31617)
* Remove Angular dependency from KeybindingsSrv
* Fix tests and typecheck issues
* basename is starting to work
* Make dashboard save work
* KeybindingSrv: Remove as angular service and no usage angular scope
* So long bridge_srv, we won't miss you
* Update snapshots
* Dashboard: Refactoring ChangeTracker to use History api and no angular (#31653)
* Dashboard: Refactoring ChangeTracker to use History api and no angular
* Updated
* Removed logging
* fixed unit tests
* updated snapshots
* Mechanism for force reloading routes (#31683)
* e2e: Fixes various things in e2e scenarios after router migration (#31685)
* Explore: Update reading query params from router props and updating location via locationService (ReactRouter) (#31688)
* RoutingNG: Initial explore redux location to router location migration
* Updated explore Wrapper tests
* Fixing more tests
* remove loggin
* rename back to make naming consistent
* Fixing return to dashboard button
* fixing navigation to explore from dashboard
* updated routeProps
* Updated tests
* Make DashboardListPage work
* Fixing navigation after add new data source, and fixes explore e2e
* Fixing solo panel page
* PluginsPage now works
* RoutingNG: When parsing and rendering url search/query params preseve old logic of handling booleans and arrays (#31725)
* RoutingNG: When parsing and rendering url search/query params preserve old logic of handling booleans and arrays
* Fixed test
* Make snapshots list work
* fixed alert notification channel edit page
* Simplify LocationService, did not need special handling for login or forceLogin as target _self on link already handles that
* fixed UserAdminPage
* fixed edit orgs page
* Fixing LdapPage
* fixing dashboard import
* Fixed new folder page
* Fixed data source dashboards page
* fixing Folder permissions and folder settings page
* fixing snapshot list page nav model
* remove unused file
* Added placeholder page for playlist
* Moved browser compatability to index-template
* Restored 404/default page
* Fixed reset password page
* Fixed SignUpInvited page
* Fixing CreateTeam, Create user page, add panel widget
* Restore browwser file to make tests happy
* Fixed unit tests
* Removed unused import
* Replacing usage of updateLocation
* Fixed test
* Updating search filters to use history / location service for filters
* remove unused file
* AppRootPage fixed
* Fixing test and search issue
* Changes to support enterprise extensions
* remove console.log
* Removing more use of redux location
* Fixed signup page
* removed unused old angular controllers
* Fixing bugs
* one final bugfix
* Removed location from redux state
* Fixing ts issues and tests
* Fixing test issue
* fixing tests
* Fixing tests
* removed unused stuff
* Fixed search test
* Adding some doc comments
* Routing NG: Angular location provider patch (#31773)
* Patch Angulars $location provider
* Update public/app/angular/bridgeReactAngularRouting.ts
* Remove only test
* Update tests, disable loggers in test env
* Routing NG: remove $location provider usage (#31816)
* Remove dashboard_loaders
* Remove $location from Analytics service, track page views form GrafanaRoute
* Remove NotificationsEditCtrl
* Remove Angular dependencies from uploadDashboardDirective
* Update public/app/features/dashboard/containers/DashboardPage.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Update public/app/features/dashboard/containers/DashboardPage.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Remove unused test helpers (#31831)
* Playlist react (#31829)
* playlist list in react
* Playlist start
* Things started to work
* Updated
* Handle empty list
* Fix ts
* Fixes and kiosk mode stuff
* Removed unused events
* fixing ts issue
* Another ts issue
* Fixing tests
Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>
* fixed test
* Update public/app/AppWrapper.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Update public/app/AppWrapper.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Remove Angular dependency from DashboardLoaderSrv (#31863)
Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
Co-authored-by: Torkel Ödegaard <torkel@grafana.org>
Co-authored-by: Hugo Häggmark <hugo.haggmark@grafana.com>
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
2021-03-10 11:03:36 -06:00
|
|
|
const queryParams = locationService.getSearchObject();
|
2020-03-10 02:53:41 -05:00
|
|
|
const promises = getVariables(getState()).map(
|
|
|
|
async (variable: VariableModel) => await dispatch(processVariable(toVariableIdentifier(variable), queryParams))
|
|
|
|
);
|
|
|
|
|
|
|
|
await Promise.all(promises);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2020-04-03 02:38:14 -05:00
|
|
|
export const setOptionFromUrl = (
|
|
|
|
identifier: VariableIdentifier,
|
|
|
|
urlValue: UrlQueryValue
|
|
|
|
): ThunkResult<Promise<void>> => {
|
2020-03-10 02:53:41 -05:00
|
|
|
return async (dispatch, getState) => {
|
2021-03-15 02:52:44 -05:00
|
|
|
const stringUrlValue = ensureStringValues(urlValue);
|
2020-06-04 06:44:48 -05:00
|
|
|
const variable = getVariable(identifier.id, getState());
|
2020-11-04 01:56:02 -06:00
|
|
|
if (getVariableRefresh(variable) !== VariableRefresh.never) {
|
2020-03-10 02:53:41 -05:00
|
|
|
// updates options
|
2020-10-02 00:02:06 -05:00
|
|
|
await dispatch(updateOptions(toVariableIdentifier(variable)));
|
|
|
|
}
|
|
|
|
|
2020-03-10 02:53:41 -05:00
|
|
|
// get variable from state
|
2020-06-04 06:44:48 -05:00
|
|
|
const variableFromState = getVariable<VariableWithOptions>(variable.id, getState());
|
2020-03-10 02:53:41 -05:00
|
|
|
if (!variableFromState) {
|
|
|
|
throw new Error(`Couldn't find variable with name: ${variable.name}`);
|
|
|
|
}
|
2021-04-01 11:17:39 -05:00
|
|
|
// Simple case. Value in URL matches existing options text or value.
|
2021-01-20 00:59:48 -06:00
|
|
|
let option = variableFromState.options.find((op) => {
|
2021-03-15 02:52:44 -05:00
|
|
|
return op.text === stringUrlValue || op.value === stringUrlValue;
|
2020-03-10 02:53:41 -05:00
|
|
|
});
|
|
|
|
|
2020-11-10 23:19:09 -06:00
|
|
|
if (!option && isMulti(variableFromState)) {
|
2021-03-15 02:52:44 -05:00
|
|
|
if (variableFromState.allValue && stringUrlValue === variableFromState.allValue) {
|
2020-11-10 23:19:09 -06:00
|
|
|
option = { text: ALL_VARIABLE_TEXT, value: ALL_VARIABLE_VALUE, selected: false };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-10 02:53:41 -05:00
|
|
|
if (!option) {
|
2021-03-15 02:52:44 -05:00
|
|
|
let defaultText = stringUrlValue;
|
|
|
|
const defaultValue = stringUrlValue;
|
2020-03-10 02:53:41 -05:00
|
|
|
|
2021-03-15 02:52:44 -05:00
|
|
|
if (Array.isArray(stringUrlValue)) {
|
2020-03-10 02:53:41 -05:00
|
|
|
// Multiple values in the url. We construct text as a list of texts from all matched options.
|
2021-03-15 02:52:44 -05:00
|
|
|
defaultText = stringUrlValue.reduce((acc: string[], item: string) => {
|
2021-01-20 00:59:48 -06:00
|
|
|
const foundOption = variableFromState.options.find((o) => o.value === item);
|
2020-03-10 02:53:41 -05:00
|
|
|
if (!foundOption) {
|
|
|
|
// @ts-ignore according to strict null errors this can never happen
|
|
|
|
// TODO: investigate this further or refactor code
|
|
|
|
return [].concat(acc, [item]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// @ts-ignore according to strict null errors this can never happen
|
|
|
|
// TODO: investigate this further or refactor code
|
|
|
|
return [].concat(acc, [foundOption.text]);
|
|
|
|
}, []);
|
|
|
|
}
|
|
|
|
|
2021-04-01 11:17:39 -05:00
|
|
|
// It is possible that we did not match the value to any existing option. In that case the URL value will be
|
2020-03-10 02:53:41 -05:00
|
|
|
// used anyway for both text and value.
|
|
|
|
option = { text: defaultText, value: defaultValue, selected: false };
|
|
|
|
}
|
|
|
|
|
2020-04-01 11:13:38 -05:00
|
|
|
if (isMulti(variableFromState)) {
|
2021-04-01 11:17:39 -05:00
|
|
|
// In case variable is multiple choice, we cast to array to preserve the same behavior as when selecting
|
2020-03-10 02:53:41 -05:00
|
|
|
// the option directly, which will return even single value in an array.
|
2020-04-01 11:13:38 -05:00
|
|
|
option = alignCurrentWithMulti(
|
|
|
|
{ text: castArray(option.text), value: castArray(option.value), selected: false },
|
|
|
|
variableFromState.multi
|
|
|
|
);
|
2020-03-10 02:53:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
await variableAdapters.get(variable.type).setValue(variableFromState, option);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
export const selectOptionsForCurrentValue = (variable: VariableWithOptions): VariableOption[] => {
|
|
|
|
let i, y, value, option;
|
|
|
|
const selected: VariableOption[] = [];
|
|
|
|
|
|
|
|
for (i = 0; i < variable.options.length; i++) {
|
|
|
|
option = { ...variable.options[i] };
|
|
|
|
option.selected = false;
|
|
|
|
if (Array.isArray(variable.current.value)) {
|
|
|
|
for (y = 0; y < variable.current.value.length; y++) {
|
|
|
|
value = variable.current.value[y];
|
|
|
|
if (option.value === value) {
|
|
|
|
option.selected = true;
|
|
|
|
selected.push(option);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (option.value === variable.current.value) {
|
|
|
|
option.selected = true;
|
|
|
|
selected.push(option);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return selected;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const validateVariableSelectionState = (
|
|
|
|
identifier: VariableIdentifier,
|
|
|
|
defaultValue?: string
|
2020-04-03 02:38:14 -05:00
|
|
|
): ThunkResult<Promise<void>> => {
|
|
|
|
return (dispatch, getState) => {
|
2020-06-04 06:44:48 -05:00
|
|
|
const variableInState = getVariable<VariableWithOptions>(identifier.id, getState());
|
2020-03-10 02:53:41 -05:00
|
|
|
const current = variableInState.current || (({} as unknown) as VariableOption);
|
|
|
|
const setValue = variableAdapters.get(variableInState.type).setValue;
|
|
|
|
|
|
|
|
if (Array.isArray(current.value)) {
|
|
|
|
const selected = selectOptionsForCurrentValue(variableInState);
|
|
|
|
|
|
|
|
// if none pick first
|
|
|
|
if (selected.length === 0) {
|
|
|
|
const option = variableInState.options[0];
|
|
|
|
return setValue(variableInState, option);
|
|
|
|
}
|
|
|
|
|
|
|
|
const option: VariableOption = {
|
2021-01-20 00:59:48 -06:00
|
|
|
value: selected.map((v) => v.value) as string[],
|
|
|
|
text: selected.map((v) => v.text) as string[],
|
2020-03-10 02:53:41 -05:00
|
|
|
selected: true,
|
|
|
|
};
|
|
|
|
return setValue(variableInState, option);
|
|
|
|
}
|
|
|
|
|
|
|
|
let option: VariableOption | undefined | null = null;
|
|
|
|
|
|
|
|
// 1. find the current value
|
2020-08-24 02:29:21 -05:00
|
|
|
const text = getCurrentText(variableInState);
|
2021-01-20 00:59:48 -06:00
|
|
|
option = variableInState.options?.find((v) => v.text === text);
|
2020-03-10 02:53:41 -05:00
|
|
|
if (option) {
|
|
|
|
return setValue(variableInState, option);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 2. find the default value
|
|
|
|
if (defaultValue) {
|
2021-01-20 00:59:48 -06:00
|
|
|
option = variableInState.options?.find((v) => v.text === defaultValue);
|
2020-03-10 02:53:41 -05:00
|
|
|
if (option) {
|
|
|
|
return setValue(variableInState, option);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 3. use the first value
|
|
|
|
if (variableInState.options) {
|
|
|
|
const option = variableInState.options[0];
|
2020-05-05 08:47:48 -05:00
|
|
|
if (option) {
|
|
|
|
return setValue(variableInState, option);
|
|
|
|
}
|
2020-03-10 02:53:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// 4... give up
|
|
|
|
return Promise.resolve();
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
export const setOptionAsCurrent = (
|
|
|
|
identifier: VariableIdentifier,
|
|
|
|
current: VariableOption,
|
|
|
|
emitChanges: boolean
|
2020-04-03 02:38:14 -05:00
|
|
|
): ThunkResult<Promise<void>> => {
|
2021-01-20 00:59:48 -06:00
|
|
|
return async (dispatch) => {
|
2020-03-10 02:53:41 -05:00
|
|
|
dispatch(setCurrentVariableValue(toVariablePayload(identifier, { option: current })));
|
2020-12-09 04:18:58 -06:00
|
|
|
return await dispatch(variableUpdated(identifier, emitChanges));
|
2020-03-10 02:53:41 -05:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
const createGraph = (variables: VariableModel[]) => {
|
|
|
|
const g = new Graph();
|
|
|
|
|
2021-01-20 00:59:48 -06:00
|
|
|
variables.forEach((v) => {
|
2020-03-10 02:53:41 -05:00
|
|
|
g.createNode(v.name);
|
|
|
|
});
|
|
|
|
|
2021-01-20 00:59:48 -06:00
|
|
|
variables.forEach((v1) => {
|
|
|
|
variables.forEach((v2) => {
|
2020-03-10 02:53:41 -05:00
|
|
|
if (v1 === v2) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (variableAdapters.get(v1.type).dependsOn(v1, v2)) {
|
|
|
|
g.link(v1.name, v2.name);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
return g;
|
|
|
|
};
|
|
|
|
|
2020-04-03 02:38:14 -05:00
|
|
|
export const variableUpdated = (
|
|
|
|
identifier: VariableIdentifier,
|
|
|
|
emitChangeEvents: boolean
|
|
|
|
): ThunkResult<Promise<void>> => {
|
2020-12-09 04:18:58 -06:00
|
|
|
return async (dispatch, getState) => {
|
2020-10-02 00:02:06 -05:00
|
|
|
const variableInState = getVariable(identifier.id, getState());
|
|
|
|
|
|
|
|
// if we're initializing variables ignore cascading update because we are in a boot up scenario
|
|
|
|
if (getState().templating.transaction.status === TransactionStatus.Fetching) {
|
2020-11-04 01:56:02 -06:00
|
|
|
if (getVariableRefresh(variableInState) === VariableRefresh.never) {
|
|
|
|
// for variable types with updates that go the setValueFromUrl path in the update let's make sure their state is set to Done.
|
2020-12-09 04:18:58 -06:00
|
|
|
await dispatch(upgradeLegacyQueries(toVariableIdentifier(variableInState)));
|
2020-11-04 01:56:02 -06:00
|
|
|
dispatch(completeVariableLoading(identifier));
|
|
|
|
}
|
2020-03-10 02:53:41 -05:00
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
const variables = getVariables(getState());
|
|
|
|
const g = createGraph(variables);
|
|
|
|
|
2020-10-02 00:02:06 -05:00
|
|
|
const node = g.getNode(variableInState.name);
|
2020-03-10 02:53:41 -05:00
|
|
|
let promises: Array<Promise<any>> = [];
|
|
|
|
if (node) {
|
2021-01-20 00:59:48 -06:00
|
|
|
promises = node.getOptimizedInputEdges().map((e) => {
|
2021-04-15 07:21:06 -05:00
|
|
|
const variable = variables.find((v) => v.name === e.inputNode?.name);
|
2020-03-10 02:53:41 -05:00
|
|
|
if (!variable) {
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
2020-10-02 00:02:06 -05:00
|
|
|
|
|
|
|
return dispatch(updateOptions(toVariableIdentifier(variable)));
|
2020-03-10 02:53:41 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return Promise.all(promises).then(() => {
|
|
|
|
if (emitChangeEvents) {
|
|
|
|
const dashboard = getState().dashboard.getModel();
|
|
|
|
dashboard?.processRepeats();
|
Routing NG: Replace Angular routing with react-router (#31463)
* Add router packages
* Get react app root work instead of Angular one
* Logger util
* Patch Angular routing ($routeProvider, $routeParamsProvider)
* Use react-router-dom history instead of separate dependency
* Add test routes
* Sidemenu - use Link instead of anchors
* Patch Angular $location service (stub)
* WIP: geting rid of $location provider from TimeSrv
* Intercept anchor clicks to use history under the hood
* Sync Redux location slice with history state
* Make login/logout work
* Debug routes for testing
* Make force login work
* Make sure query param change does not recreate page components
* Hide side menu in specified locations
* Make the dashboar route query parameters work, make panel edit menu work
* Enable more routes
* Fix side menu
* Handle view modes
* Disable playlist routes
* Make SafeDynamicImport work again
* Bring back router-debug
* Separate redux location sync from route rendering
* Refactor updateLocation to thunk and move force refresh(login) to it
* Fixing init dashboard issue
* Support switching between dashboards without an unmount of DashboardPage
* More fixes for init dashboard and panel edit
* More type fixes
* Moving angular location wrapper out of main LocationService, and fixing typescript issues
* Fixed last typescript errors
* LocationService: Move to runtime and remove getLocationService and export singleston const instead (#31523)
* Moving location service implementation to runtime and removing get function and making it a package const singleton
* Added test that used locationService directly
* removed unused import
* AngularApp: Moving angular dependencies and the app boot out of the main app into it's own file (#31525)
* Fixes angular panels by calling the monkey patch
* Moving angular stuff to to it's own files
* udpated
* Fixing clicking on divs and spans inside anchor
* Moving app notifications out of angular app and removing angular directive wrapper
* Moving search from angular to react and removing angular search wrapper
* Clean up, tried to remove the redux location wrapper but requires a big update for DashboardPage, so adding it back
* Moving AppWrapper to root to limit circular dependencies (app/core -> app/routing and back)
* Open and close search now works
* Hide sidemenu when in kiosk mode
* Restoring some keybindings like ESC key
* Removed kiosk events and simplified it, just handled through updating URL
* Fixing typescript errors
* Simplified GrafanaRouteComponentProps and renamed to ContainerProps
* renamed back
* Changed AlertRuleList to use GrafanaRouteComponentProps and location.search passed to it
* Removing the reloadOnSearch property, this is not needed now for react as react by default does not unmount components when only url match or query parmas change
* SafeDynamicImport causing unmount un every search update, not sure how to fix yet
* Fix signature for SafeDynamicImport so we do not create new route components on every route render
* Removing the redux location wrapper as it was causing errors, and making dashboard page work with RouteProps (location, match) etc
* Updating DashboardPage and SoloPanelPage to use match params and history location
* Fixed DashboardPage tests
* Fixing solo route tests
* LocationService: Rename getCurrentLocation to just getLocation
* do not intercept link clicks with target blank or self
* Experimental useUrlParams hook
* Update DataSourceSettingsPage to use router match params
* fix links with urls that have no starting / to work like before
* Fix forceLogin
* Add queryParams to GrafanaRouteComponentProps
* PanelEditor get rid of updateLocation and location state
* Improve grafana route query params typing
* Add getSearchObject to LocationService
* Use DashboardPAge queryParams instead of location.search parsing
* Fix DashboardPage typing
* Fix some tests weirdness
* Bring back KeyboardSrv
* Fixes typescript issues
* Team pages now use router match params
* Get rid of from GrafanaRouteComponent props
* Removed unnessary calls to getSearchObject when calling locationService.partial
* Updated DashboardPage tests after queryParams was added
* Fixing dashboard settings back
* GrafanaRoute: Adding tests and remove use of global locationService
* Fixing tests and typescript errors
* Bring back kiosk modes and add tests
* Fix TimeSrv tests
* Fix typecheck errors
* Fixing tests
* Updated SideMenu test to react-testing and wrapped component in Router, and fixed issue importing createMemoryHistory
* Get rid of routeChange event from TimeSrv from
* Fixed TopSectionItem test
* Trying to make basename work but failing
* Update TopSectionItem snapshot
* Fix TopSectionItem snapshot test
* Fix API keys creation
* Remove Angular dependencies from KeybindingSrv (#31617)
* Remove Angular dependency from KeybindingsSrv
* Fix tests and typecheck issues
* basename is starting to work
* Make dashboard save work
* KeybindingSrv: Remove as angular service and no usage angular scope
* So long bridge_srv, we won't miss you
* Update snapshots
* Dashboard: Refactoring ChangeTracker to use History api and no angular (#31653)
* Dashboard: Refactoring ChangeTracker to use History api and no angular
* Updated
* Removed logging
* fixed unit tests
* updated snapshots
* Mechanism for force reloading routes (#31683)
* e2e: Fixes various things in e2e scenarios after router migration (#31685)
* Explore: Update reading query params from router props and updating location via locationService (ReactRouter) (#31688)
* RoutingNG: Initial explore redux location to router location migration
* Updated explore Wrapper tests
* Fixing more tests
* remove loggin
* rename back to make naming consistent
* Fixing return to dashboard button
* fixing navigation to explore from dashboard
* updated routeProps
* Updated tests
* Make DashboardListPage work
* Fixing navigation after add new data source, and fixes explore e2e
* Fixing solo panel page
* PluginsPage now works
* RoutingNG: When parsing and rendering url search/query params preseve old logic of handling booleans and arrays (#31725)
* RoutingNG: When parsing and rendering url search/query params preserve old logic of handling booleans and arrays
* Fixed test
* Make snapshots list work
* fixed alert notification channel edit page
* Simplify LocationService, did not need special handling for login or forceLogin as target _self on link already handles that
* fixed UserAdminPage
* fixed edit orgs page
* Fixing LdapPage
* fixing dashboard import
* Fixed new folder page
* Fixed data source dashboards page
* fixing Folder permissions and folder settings page
* fixing snapshot list page nav model
* remove unused file
* Added placeholder page for playlist
* Moved browser compatability to index-template
* Restored 404/default page
* Fixed reset password page
* Fixed SignUpInvited page
* Fixing CreateTeam, Create user page, add panel widget
* Restore browwser file to make tests happy
* Fixed unit tests
* Removed unused import
* Replacing usage of updateLocation
* Fixed test
* Updating search filters to use history / location service for filters
* remove unused file
* AppRootPage fixed
* Fixing test and search issue
* Changes to support enterprise extensions
* remove console.log
* Removing more use of redux location
* Fixed signup page
* removed unused old angular controllers
* Fixing bugs
* one final bugfix
* Removed location from redux state
* Fixing ts issues and tests
* Fixing test issue
* fixing tests
* Fixing tests
* removed unused stuff
* Fixed search test
* Adding some doc comments
* Routing NG: Angular location provider patch (#31773)
* Patch Angulars $location provider
* Update public/app/angular/bridgeReactAngularRouting.ts
* Remove only test
* Update tests, disable loggers in test env
* Routing NG: remove $location provider usage (#31816)
* Remove dashboard_loaders
* Remove $location from Analytics service, track page views form GrafanaRoute
* Remove NotificationsEditCtrl
* Remove Angular dependencies from uploadDashboardDirective
* Update public/app/features/dashboard/containers/DashboardPage.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Update public/app/features/dashboard/containers/DashboardPage.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Remove unused test helpers (#31831)
* Playlist react (#31829)
* playlist list in react
* Playlist start
* Things started to work
* Updated
* Handle empty list
* Fix ts
* Fixes and kiosk mode stuff
* Removed unused events
* fixing ts issue
* Another ts issue
* Fixing tests
Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>
* fixed test
* Update public/app/AppWrapper.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Update public/app/AppWrapper.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Remove Angular dependency from DashboardLoaderSrv (#31863)
Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
Co-authored-by: Torkel Ödegaard <torkel@grafana.org>
Co-authored-by: Hugo Häggmark <hugo.haggmark@grafana.com>
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
2021-03-10 11:03:36 -06:00
|
|
|
locationService.partial(getQueryWithVariables(getState));
|
2020-03-10 02:53:41 -05:00
|
|
|
dashboard?.startRefresh();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2020-03-17 08:10:30 -05:00
|
|
|
export interface OnTimeRangeUpdatedDependencies {
|
2020-10-01 12:51:23 -05:00
|
|
|
templateSrv: TemplateSrv;
|
2020-03-17 08:10:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
export const onTimeRangeUpdated = (
|
|
|
|
timeRange: TimeRange,
|
2020-10-02 00:02:06 -05:00
|
|
|
dependencies: OnTimeRangeUpdatedDependencies = { templateSrv: getTemplateSrv() }
|
2020-04-03 02:38:14 -05:00
|
|
|
): ThunkResult<Promise<void>> => async (dispatch, getState) => {
|
2020-03-17 08:10:30 -05:00
|
|
|
dependencies.templateSrv.updateTimeRange(timeRange);
|
2021-01-20 00:59:48 -06:00
|
|
|
const variablesThatNeedRefresh = getVariables(getState()).filter((variable) => {
|
2020-03-17 08:10:30 -05:00
|
|
|
if (variable.hasOwnProperty('refresh') && variable.hasOwnProperty('options')) {
|
|
|
|
const variableWithRefresh = (variable as unknown) as QueryVariableModel;
|
|
|
|
return variableWithRefresh.refresh === VariableRefresh.onTimeRangeChanged;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2021-02-17 23:21:35 -06:00
|
|
|
}) as VariableWithOptions[];
|
2020-03-17 08:10:30 -05:00
|
|
|
|
2020-10-02 00:02:06 -05:00
|
|
|
const promises = variablesThatNeedRefresh.map((variable: VariableWithOptions) =>
|
|
|
|
dispatch(timeRangeUpdated(toVariableIdentifier(variable)))
|
|
|
|
);
|
2020-03-17 08:10:30 -05:00
|
|
|
|
|
|
|
try {
|
|
|
|
await Promise.all(promises);
|
|
|
|
const dashboard = getState().dashboard.getModel();
|
|
|
|
dashboard?.startRefresh();
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
2020-10-02 00:02:06 -05:00
|
|
|
dispatch(notifyApp(createVariableErrorNotification('Template variable service failed', error)));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const timeRangeUpdated = (identifier: VariableIdentifier): ThunkResult<Promise<void>> => async (dispatch, getState) => {
|
|
|
|
const variableInState = getVariable<VariableWithOptions>(identifier.id);
|
|
|
|
const previousOptions = variableInState.options.slice();
|
|
|
|
|
|
|
|
await dispatch(updateOptions(toVariableIdentifier(variableInState), true));
|
|
|
|
|
|
|
|
const updatedVariable = getVariable<VariableWithOptions>(identifier.id, getState());
|
|
|
|
const updatedOptions = updatedVariable.options;
|
|
|
|
|
|
|
|
if (angular.toJson(previousOptions) !== angular.toJson(updatedOptions)) {
|
|
|
|
const dashboard = getState().dashboard.getModel();
|
|
|
|
dashboard?.templateVariableValueUpdated();
|
2020-03-17 08:10:30 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-06-04 06:44:48 -05:00
|
|
|
export const templateVarsChangedInUrl = (vars: UrlQueryMap): ThunkResult<void> => async (dispatch, getState) => {
|
|
|
|
const update: Array<Promise<any>> = [];
|
|
|
|
for (const variable of getVariables(getState())) {
|
|
|
|
const key = `var-${variable.name}`;
|
|
|
|
if (vars.hasOwnProperty(key)) {
|
|
|
|
if (isVariableUrlValueDifferentFromCurrent(variable, vars[key])) {
|
|
|
|
const promise = variableAdapters.get(variable.type).setValueFromUrl(variable, vars[key]);
|
|
|
|
update.push(promise);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (update.length) {
|
|
|
|
await Promise.all(update);
|
|
|
|
const dashboard = getState().dashboard.getModel();
|
|
|
|
dashboard?.templateVariableValueUpdated();
|
|
|
|
dashboard?.startRefresh();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const isVariableUrlValueDifferentFromCurrent = (variable: VariableModel, urlValue: any): boolean => {
|
2021-03-15 02:52:44 -05:00
|
|
|
const stringUrlValue = ensureStringValues(urlValue);
|
2020-06-04 06:44:48 -05:00
|
|
|
// lodash isEqual handles array of value equality checks as well
|
2021-03-15 02:52:44 -05:00
|
|
|
return !isEqual(variableAdapters.get(variable.type).getValueForUrl(variable), stringUrlValue);
|
2020-06-04 06:44:48 -05:00
|
|
|
};
|
|
|
|
|
2020-03-10 02:53:41 -05:00
|
|
|
const getQueryWithVariables = (getState: () => StoreState): UrlQueryMap => {
|
Routing NG: Replace Angular routing with react-router (#31463)
* Add router packages
* Get react app root work instead of Angular one
* Logger util
* Patch Angular routing ($routeProvider, $routeParamsProvider)
* Use react-router-dom history instead of separate dependency
* Add test routes
* Sidemenu - use Link instead of anchors
* Patch Angular $location service (stub)
* WIP: geting rid of $location provider from TimeSrv
* Intercept anchor clicks to use history under the hood
* Sync Redux location slice with history state
* Make login/logout work
* Debug routes for testing
* Make force login work
* Make sure query param change does not recreate page components
* Hide side menu in specified locations
* Make the dashboar route query parameters work, make panel edit menu work
* Enable more routes
* Fix side menu
* Handle view modes
* Disable playlist routes
* Make SafeDynamicImport work again
* Bring back router-debug
* Separate redux location sync from route rendering
* Refactor updateLocation to thunk and move force refresh(login) to it
* Fixing init dashboard issue
* Support switching between dashboards without an unmount of DashboardPage
* More fixes for init dashboard and panel edit
* More type fixes
* Moving angular location wrapper out of main LocationService, and fixing typescript issues
* Fixed last typescript errors
* LocationService: Move to runtime and remove getLocationService and export singleston const instead (#31523)
* Moving location service implementation to runtime and removing get function and making it a package const singleton
* Added test that used locationService directly
* removed unused import
* AngularApp: Moving angular dependencies and the app boot out of the main app into it's own file (#31525)
* Fixes angular panels by calling the monkey patch
* Moving angular stuff to to it's own files
* udpated
* Fixing clicking on divs and spans inside anchor
* Moving app notifications out of angular app and removing angular directive wrapper
* Moving search from angular to react and removing angular search wrapper
* Clean up, tried to remove the redux location wrapper but requires a big update for DashboardPage, so adding it back
* Moving AppWrapper to root to limit circular dependencies (app/core -> app/routing and back)
* Open and close search now works
* Hide sidemenu when in kiosk mode
* Restoring some keybindings like ESC key
* Removed kiosk events and simplified it, just handled through updating URL
* Fixing typescript errors
* Simplified GrafanaRouteComponentProps and renamed to ContainerProps
* renamed back
* Changed AlertRuleList to use GrafanaRouteComponentProps and location.search passed to it
* Removing the reloadOnSearch property, this is not needed now for react as react by default does not unmount components when only url match or query parmas change
* SafeDynamicImport causing unmount un every search update, not sure how to fix yet
* Fix signature for SafeDynamicImport so we do not create new route components on every route render
* Removing the redux location wrapper as it was causing errors, and making dashboard page work with RouteProps (location, match) etc
* Updating DashboardPage and SoloPanelPage to use match params and history location
* Fixed DashboardPage tests
* Fixing solo route tests
* LocationService: Rename getCurrentLocation to just getLocation
* do not intercept link clicks with target blank or self
* Experimental useUrlParams hook
* Update DataSourceSettingsPage to use router match params
* fix links with urls that have no starting / to work like before
* Fix forceLogin
* Add queryParams to GrafanaRouteComponentProps
* PanelEditor get rid of updateLocation and location state
* Improve grafana route query params typing
* Add getSearchObject to LocationService
* Use DashboardPAge queryParams instead of location.search parsing
* Fix DashboardPage typing
* Fix some tests weirdness
* Bring back KeyboardSrv
* Fixes typescript issues
* Team pages now use router match params
* Get rid of from GrafanaRouteComponent props
* Removed unnessary calls to getSearchObject when calling locationService.partial
* Updated DashboardPage tests after queryParams was added
* Fixing dashboard settings back
* GrafanaRoute: Adding tests and remove use of global locationService
* Fixing tests and typescript errors
* Bring back kiosk modes and add tests
* Fix TimeSrv tests
* Fix typecheck errors
* Fixing tests
* Updated SideMenu test to react-testing and wrapped component in Router, and fixed issue importing createMemoryHistory
* Get rid of routeChange event from TimeSrv from
* Fixed TopSectionItem test
* Trying to make basename work but failing
* Update TopSectionItem snapshot
* Fix TopSectionItem snapshot test
* Fix API keys creation
* Remove Angular dependencies from KeybindingSrv (#31617)
* Remove Angular dependency from KeybindingsSrv
* Fix tests and typecheck issues
* basename is starting to work
* Make dashboard save work
* KeybindingSrv: Remove as angular service and no usage angular scope
* So long bridge_srv, we won't miss you
* Update snapshots
* Dashboard: Refactoring ChangeTracker to use History api and no angular (#31653)
* Dashboard: Refactoring ChangeTracker to use History api and no angular
* Updated
* Removed logging
* fixed unit tests
* updated snapshots
* Mechanism for force reloading routes (#31683)
* e2e: Fixes various things in e2e scenarios after router migration (#31685)
* Explore: Update reading query params from router props and updating location via locationService (ReactRouter) (#31688)
* RoutingNG: Initial explore redux location to router location migration
* Updated explore Wrapper tests
* Fixing more tests
* remove loggin
* rename back to make naming consistent
* Fixing return to dashboard button
* fixing navigation to explore from dashboard
* updated routeProps
* Updated tests
* Make DashboardListPage work
* Fixing navigation after add new data source, and fixes explore e2e
* Fixing solo panel page
* PluginsPage now works
* RoutingNG: When parsing and rendering url search/query params preseve old logic of handling booleans and arrays (#31725)
* RoutingNG: When parsing and rendering url search/query params preserve old logic of handling booleans and arrays
* Fixed test
* Make snapshots list work
* fixed alert notification channel edit page
* Simplify LocationService, did not need special handling for login or forceLogin as target _self on link already handles that
* fixed UserAdminPage
* fixed edit orgs page
* Fixing LdapPage
* fixing dashboard import
* Fixed new folder page
* Fixed data source dashboards page
* fixing Folder permissions and folder settings page
* fixing snapshot list page nav model
* remove unused file
* Added placeholder page for playlist
* Moved browser compatability to index-template
* Restored 404/default page
* Fixed reset password page
* Fixed SignUpInvited page
* Fixing CreateTeam, Create user page, add panel widget
* Restore browwser file to make tests happy
* Fixed unit tests
* Removed unused import
* Replacing usage of updateLocation
* Fixed test
* Updating search filters to use history / location service for filters
* remove unused file
* AppRootPage fixed
* Fixing test and search issue
* Changes to support enterprise extensions
* remove console.log
* Removing more use of redux location
* Fixed signup page
* removed unused old angular controllers
* Fixing bugs
* one final bugfix
* Removed location from redux state
* Fixing ts issues and tests
* Fixing test issue
* fixing tests
* Fixing tests
* removed unused stuff
* Fixed search test
* Adding some doc comments
* Routing NG: Angular location provider patch (#31773)
* Patch Angulars $location provider
* Update public/app/angular/bridgeReactAngularRouting.ts
* Remove only test
* Update tests, disable loggers in test env
* Routing NG: remove $location provider usage (#31816)
* Remove dashboard_loaders
* Remove $location from Analytics service, track page views form GrafanaRoute
* Remove NotificationsEditCtrl
* Remove Angular dependencies from uploadDashboardDirective
* Update public/app/features/dashboard/containers/DashboardPage.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Update public/app/features/dashboard/containers/DashboardPage.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Remove unused test helpers (#31831)
* Playlist react (#31829)
* playlist list in react
* Playlist start
* Things started to work
* Updated
* Handle empty list
* Fix ts
* Fixes and kiosk mode stuff
* Removed unused events
* fixing ts issue
* Another ts issue
* Fixing tests
Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>
* fixed test
* Update public/app/AppWrapper.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Update public/app/AppWrapper.tsx
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
* Remove Angular dependency from DashboardLoaderSrv (#31863)
Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
Co-authored-by: Torkel Ödegaard <torkel@grafana.org>
Co-authored-by: Hugo Häggmark <hugo.haggmark@grafana.com>
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
2021-03-10 11:03:36 -06:00
|
|
|
const queryParams = locationService.getSearchObject();
|
2020-03-10 02:53:41 -05:00
|
|
|
|
|
|
|
const queryParamsNew = Object.keys(queryParams)
|
2021-01-20 00:59:48 -06:00
|
|
|
.filter((key) => key.indexOf('var-') === -1)
|
2020-03-10 02:53:41 -05:00
|
|
|
.reduce((obj, key) => {
|
|
|
|
obj[key] = queryParams[key];
|
|
|
|
return obj;
|
|
|
|
}, {} as UrlQueryMap);
|
|
|
|
|
|
|
|
for (const variable of getVariables(getState())) {
|
|
|
|
if (variable.skipUrlSync) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const adapter = variableAdapters.get(variable.type);
|
|
|
|
queryParamsNew['var-' + variable.name] = adapter.getValueForUrl(variable);
|
|
|
|
}
|
|
|
|
|
|
|
|
return queryParamsNew;
|
|
|
|
};
|
2020-06-04 01:59:57 -05:00
|
|
|
|
2020-06-04 06:44:48 -05:00
|
|
|
export const initVariablesTransaction = (dashboardUid: string, dashboard: DashboardModel): ThunkResult<void> => async (
|
|
|
|
dispatch,
|
|
|
|
getState
|
|
|
|
) => {
|
2020-06-04 01:59:57 -05:00
|
|
|
try {
|
|
|
|
const transactionState = getState().templating.transaction;
|
|
|
|
if (transactionState.status === TransactionStatus.Fetching) {
|
|
|
|
// previous dashboard is still fetching variables, cancel all requests
|
|
|
|
dispatch(cancelVariables());
|
|
|
|
}
|
|
|
|
|
2020-07-28 09:05:29 -05:00
|
|
|
// Start init transaction
|
2020-06-04 01:59:57 -05:00
|
|
|
dispatch(variablesInitTransaction({ uid: dashboardUid }));
|
2020-07-28 09:05:29 -05:00
|
|
|
// Add system variables like __dashboard and __user
|
|
|
|
dispatch(addSystemTemplateVariables(dashboard));
|
|
|
|
// Load all variables into redux store
|
2020-06-04 06:44:48 -05:00
|
|
|
dispatch(initDashboardTemplating(dashboard.templating.list));
|
2020-07-28 09:05:29 -05:00
|
|
|
// Process all variable updates
|
2020-06-04 06:44:48 -05:00
|
|
|
await dispatch(processVariables());
|
2020-07-28 09:05:29 -05:00
|
|
|
// Mark update as complete
|
2020-06-04 01:59:57 -05:00
|
|
|
dispatch(variablesCompleteTransaction({ uid: dashboardUid }));
|
|
|
|
} catch (err) {
|
2020-10-02 00:02:06 -05:00
|
|
|
dispatch(notifyApp(createVariableErrorNotification('Templating init failed', err)));
|
2020-07-10 09:07:04 -05:00
|
|
|
console.error(err);
|
2020-06-04 01:59:57 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-01-20 00:59:48 -06:00
|
|
|
export const cleanUpVariables = (): ThunkResult<void> => (dispatch) => {
|
2020-06-04 01:59:57 -05:00
|
|
|
dispatch(cleanVariables());
|
2021-02-02 02:13:39 -06:00
|
|
|
dispatch(cleanEditorState());
|
|
|
|
dispatch(cleanPickerState());
|
2020-06-04 01:59:57 -05:00
|
|
|
dispatch(variablesClearTransaction());
|
|
|
|
};
|
|
|
|
|
|
|
|
type CancelVariablesDependencies = { getBackendSrv: typeof getBackendSrv };
|
|
|
|
export const cancelVariables = (
|
|
|
|
dependencies: CancelVariablesDependencies = { getBackendSrv: getBackendSrv }
|
2021-01-20 00:59:48 -06:00
|
|
|
): ThunkResult<void> => (dispatch) => {
|
2020-06-04 01:59:57 -05:00
|
|
|
dependencies.getBackendSrv().cancelAllInFlightRequests();
|
|
|
|
dispatch(cleanUpVariables());
|
|
|
|
};
|
2020-10-02 00:02:06 -05:00
|
|
|
|
|
|
|
export const updateOptions = (identifier: VariableIdentifier, rethrow = false): ThunkResult<Promise<void>> => async (
|
|
|
|
dispatch,
|
|
|
|
getState
|
|
|
|
) => {
|
|
|
|
const variableInState = getVariable(identifier.id, getState());
|
|
|
|
try {
|
|
|
|
dispatch(variableStateFetching(toVariablePayload(variableInState)));
|
2020-12-09 04:18:58 -06:00
|
|
|
await dispatch(upgradeLegacyQueries(toVariableIdentifier(variableInState)));
|
2020-10-02 00:02:06 -05:00
|
|
|
await variableAdapters.get(variableInState.type).updateOptions(variableInState);
|
2020-10-14 10:07:42 -05:00
|
|
|
dispatch(completeVariableLoading(identifier));
|
2020-10-02 00:02:06 -05:00
|
|
|
} catch (error) {
|
|
|
|
dispatch(variableStateFailed(toVariablePayload(variableInState, { error })));
|
|
|
|
|
|
|
|
if (!rethrow) {
|
|
|
|
console.error(error);
|
|
|
|
dispatch(notifyApp(createVariableErrorNotification('Error updating options:', error, identifier)));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rethrow) {
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
export const createVariableErrorNotification = (
|
|
|
|
message: string,
|
|
|
|
error: any,
|
|
|
|
identifier?: VariableIdentifier
|
|
|
|
): AppNotification =>
|
|
|
|
createErrorNotification(
|
|
|
|
`${identifier ? `Templating [${identifier.id}]` : 'Templating'}`,
|
|
|
|
`${message} ${error.message}`
|
|
|
|
);
|
2020-10-14 10:07:42 -05:00
|
|
|
|
|
|
|
export const completeVariableLoading = (identifier: VariableIdentifier): ThunkResult<void> => (dispatch, getState) => {
|
|
|
|
const variableInState = getVariable(identifier.id, getState());
|
|
|
|
|
|
|
|
if (variableInState.state !== LoadingState.Done) {
|
|
|
|
dispatch(variableStateCompleted(toVariablePayload(variableInState)));
|
|
|
|
}
|
|
|
|
};
|
2020-11-27 03:20:57 -06:00
|
|
|
|
|
|
|
export function upgradeLegacyQueries(
|
|
|
|
identifier: VariableIdentifier,
|
|
|
|
getDatasourceSrvFunc: typeof getDatasourceSrv = getDatasourceSrv
|
|
|
|
): ThunkResult<void> {
|
2021-01-20 00:59:48 -06:00
|
|
|
return async function (dispatch, getState) {
|
2020-11-27 03:20:57 -06:00
|
|
|
const variable = getVariable<QueryVariableModel>(identifier.id, getState());
|
|
|
|
|
|
|
|
if (!isQuery(variable)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-12-09 04:18:58 -06:00
|
|
|
try {
|
|
|
|
const datasource = await getDatasourceSrvFunc().get(variable.datasource ?? '');
|
2020-11-27 03:20:57 -06:00
|
|
|
|
2020-12-09 04:18:58 -06:00
|
|
|
if (hasLegacyVariableSupport(datasource)) {
|
|
|
|
return;
|
|
|
|
}
|
2020-11-27 03:20:57 -06:00
|
|
|
|
2020-12-09 04:18:58 -06:00
|
|
|
if (!hasStandardVariableSupport(datasource)) {
|
|
|
|
return;
|
|
|
|
}
|
2020-11-27 03:20:57 -06:00
|
|
|
|
2020-12-09 04:18:58 -06:00
|
|
|
if (isDataQueryType(variable.query)) {
|
|
|
|
return;
|
|
|
|
}
|
2020-11-27 03:20:57 -06:00
|
|
|
|
2020-12-09 04:18:58 -06:00
|
|
|
const query = {
|
|
|
|
refId: `${datasource.name}-${identifier.id}-Variable-Query`,
|
|
|
|
query: variable.query,
|
|
|
|
};
|
2020-11-27 03:20:57 -06:00
|
|
|
|
2020-12-09 04:18:58 -06:00
|
|
|
dispatch(changeVariableProp(toVariablePayload(identifier, { propName: 'query', propValue: query })));
|
|
|
|
} catch (err) {
|
|
|
|
dispatch(notifyApp(createVariableErrorNotification('Failed to upgrade legacy queries', err)));
|
|
|
|
console.error(err);
|
|
|
|
}
|
2020-11-27 03:20:57 -06:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function isDataQueryType(query: any): query is DataQuery {
|
|
|
|
if (!query) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return query.hasOwnProperty('refId') && typeof query.refId === 'string';
|
|
|
|
}
|