diff --git a/packages/grafana-runtime/src/services/LocationSrv.ts b/packages/grafana-runtime/src/services/LocationSrv.ts new file mode 100644 index 00000000000..5e397d77e35 --- /dev/null +++ b/packages/grafana-runtime/src/services/LocationSrv.ts @@ -0,0 +1,36 @@ +export interface LocationUpdate { + path?: string; + query?: UrlQueryMap; + + /** + * Add the query argument to the existing URL + */ + partial?: boolean; + + /** + * Do not change this unless you are the angular router + */ + routeParams?: UrlQueryMap; + + /* + * If true this will replace url state (ie cause no new browser history) + */ + replace?: boolean; +} + +export type UrlQueryValue = string | number | boolean | string[] | number[] | boolean[]; +export type UrlQueryMap = { [s: string]: UrlQueryValue }; + +export interface LocationSrv { + update(options: LocationUpdate): void; +} + +let singletonInstance: LocationSrv; + +export function setLocationSrv(instance: LocationSrv) { + singletonInstance = instance; +} + +export function getLocationSrv(): LocationSrv { + return singletonInstance; +} diff --git a/packages/grafana-runtime/src/services/index.ts b/packages/grafana-runtime/src/services/index.ts index 08517c0650b..c92ac500c6a 100644 --- a/packages/grafana-runtime/src/services/index.ts +++ b/packages/grafana-runtime/src/services/index.ts @@ -1,3 +1,4 @@ export * from './backendSrv'; export * from './AngularLoader'; export * from './dataSourceSrv'; +export * from './LocationSrv'; diff --git a/public/app/core/actions/location.ts b/public/app/core/actions/location.ts index 34ab43da7d2..567934e12cb 100644 --- a/public/app/core/actions/location.ts +++ b/public/app/core/actions/location.ts @@ -1,4 +1,4 @@ -import { LocationUpdate } from 'app/types'; +import { LocationUpdate } from '@grafana/runtime'; import { actionCreatorFactory } from 'app/core/redux'; export const updateLocation = actionCreatorFactory('UPDATE_LOCATION').create(); diff --git a/public/app/core/utils/url.ts b/public/app/core/utils/url.ts index b0994eb0103..878904bc7a6 100644 --- a/public/app/core/utils/url.ts +++ b/public/app/core/utils/url.ts @@ -2,7 +2,7 @@ * @preserve jquery-param (c) 2015 KNOWLEDGECODE | MIT */ -import { UrlQueryMap } from 'app/types'; +import { UrlQueryMap } from '@grafana/runtime'; export function renderUrl(path: string, query: UrlQueryMap | undefined): string { if (query && Object.keys(query).length > 0) { @@ -11,7 +11,7 @@ export function renderUrl(path: string, query: UrlQueryMap | undefined): string return path; } -export function encodeURIComponentAsAngularJS(val, pctEncodeSpaces) { +export function encodeURIComponentAsAngularJS(val: string, pctEncodeSpaces?: boolean) { return encodeURIComponent(val) .replace(/%40/gi, '@') .replace(/%3A/gi, ':') @@ -21,15 +21,15 @@ export function encodeURIComponentAsAngularJS(val, pctEncodeSpaces) { .replace(/%20/g, pctEncodeSpaces ? '%20' : '+'); } -export function toUrlParams(a) { +export function toUrlParams(a: any) { const s = []; const rbracket = /\[\]$/; - const isArray = obj => { + const isArray = (obj: any) => { return Object.prototype.toString.call(obj) === '[object Array]'; }; - const add = (k, v) => { + const add = (k: string, v: any) => { v = typeof v === 'function' ? v() : v === null ? '' : v === undefined ? '' : v; if (typeof v !== 'boolean') { s[s.length] = encodeURIComponentAsAngularJS(k, true) + '=' + encodeURIComponentAsAngularJS(v, true); @@ -38,7 +38,7 @@ export function toUrlParams(a) { } }; - const buildParams = (prefix, obj) => { + const buildParams = (prefix: string, obj: any) => { let i, len, key; if (prefix) { diff --git a/public/app/features/dashboard/components/AddPanelWidget/AddPanelWidget.tsx b/public/app/features/dashboard/components/AddPanelWidget/AddPanelWidget.tsx index a4a1adffc7d..c6764ffd9ef 100644 --- a/public/app/features/dashboard/components/AddPanelWidget/AddPanelWidget.tsx +++ b/public/app/features/dashboard/components/AddPanelWidget/AddPanelWidget.tsx @@ -14,7 +14,7 @@ import { updateLocation } from 'app/core/actions'; import { PanelModel } from '../../state'; import { DashboardModel } from '../../state'; import { LS_PANEL_COPY_KEY } from 'app/core/constants'; -import { LocationUpdate } from 'app/types'; +import { LocationUpdate } from '@grafana/runtime'; export interface Props { panel: PanelModel; diff --git a/public/app/features/dashboard/state/DashboardModel.ts b/public/app/features/dashboard/state/DashboardModel.ts index d5301e98cea..88e92cd09df 100644 --- a/public/app/features/dashboard/state/DashboardModel.ts +++ b/public/app/features/dashboard/state/DashboardModel.ts @@ -13,8 +13,9 @@ import sortByKeys from 'app/core/utils/sort_by_keys'; // Types import { PanelModel, GridPos } from './PanelModel'; import { DashboardMigrator } from './DashboardMigrator'; -import { TimeRange } from '@grafana/ui/src'; -import { UrlQueryValue, KIOSK_MODE_TV, DashboardMeta } from 'app/types'; +import { TimeRange } from '@grafana/ui'; +import { UrlQueryValue } from '@grafana/runtime'; +import { KIOSK_MODE_TV, DashboardMeta } from 'app/types'; import { toUtc, DateTimeInput, dateTime, isDateTime } from '@grafana/ui/src/utils/moment_wrapper'; export interface CloneOptions { diff --git a/public/app/features/datasources/settings/DataSourceSettingsPage.tsx b/public/app/features/datasources/settings/DataSourceSettingsPage.tsx index 30d4d6ea38c..a34031c487f 100644 --- a/public/app/features/datasources/settings/DataSourceSettingsPage.tsx +++ b/public/app/features/datasources/settings/DataSourceSettingsPage.tsx @@ -22,7 +22,8 @@ import { getNavModel } from 'app/core/selectors/navModel'; import { getRouteParamsId } from 'app/core/selectors/location'; // Types -import { StoreState, UrlQueryMap } from 'app/types/'; +import { StoreState } from 'app/types/'; +import { UrlQueryMap } from '@grafana/runtime'; import { NavModel, DataSourceSettings, DataSourcePluginMeta } from '@grafana/ui'; import { getDataSourceLoadingNav } from '../state/navModel'; import PluginStateinfo from 'app/features/plugins/PluginStateInfo'; diff --git a/public/app/features/datasources/state/actions.ts b/public/app/features/datasources/state/actions.ts index 9fb003bc0c4..3df2c445443 100644 --- a/public/app/features/datasources/state/actions.ts +++ b/public/app/features/datasources/state/actions.ts @@ -6,7 +6,8 @@ import { LayoutMode } from 'app/core/components/LayoutSelector/LayoutSelector'; import { updateLocation, updateNavIndex, UpdateNavIndexAction } from 'app/core/actions'; import { buildNavModel } from './navModel'; import { DataSourceSettings, DataSourcePluginMeta } from '@grafana/ui'; -import { StoreState, LocationUpdate } from 'app/types'; +import { StoreState } from 'app/types'; +import { LocationUpdate } from '@grafana/runtime'; import { actionCreatorFactory } from 'app/core/redux'; import { ActionOf, noPayloadActionCreatorFactory } from 'app/core/redux/actionCreatorFactory'; import { getPluginSettings } from 'app/features/plugins/PluginSettingsCache'; diff --git a/public/app/features/explore/state/reducers.ts b/public/app/features/explore/state/reducers.ts index 67775b9626b..eed4be614ac 100644 --- a/public/app/features/explore/state/reducers.ts +++ b/public/app/features/explore/state/reducers.ts @@ -55,7 +55,7 @@ import { toggleLogLevelAction, } from './actionTypes'; import { updateLocation } from 'app/core/actions/location'; -import { LocationUpdate } from 'app/types'; +import { LocationUpdate } from '@grafana/runtime'; import TableModel from 'app/core/table_model'; import { isLive } from '@grafana/ui/src/components/RefreshPicker/RefreshPicker'; diff --git a/public/app/features/plugins/AppRootPage.tsx b/public/app/features/plugins/AppRootPage.tsx index 8c337670890..ec6c6c00e17 100644 --- a/public/app/features/plugins/AppRootPage.tsx +++ b/public/app/features/plugins/AppRootPage.tsx @@ -4,7 +4,8 @@ import { hot } from 'react-hot-loader'; import { connect } from 'react-redux'; // Types -import { StoreState, UrlQueryMap } from 'app/types'; +import { StoreState } from 'app/types'; +import { UrlQueryMap } from '@grafana/runtime'; import Page from 'app/core/components/Page/Page'; import { getPluginSettings } from './PluginSettingsCache'; diff --git a/public/app/features/plugins/PluginPage.tsx b/public/app/features/plugins/PluginPage.tsx index 9da5b097f2a..a2ca435f9c9 100644 --- a/public/app/features/plugins/PluginPage.tsx +++ b/public/app/features/plugins/PluginPage.tsx @@ -5,7 +5,8 @@ import { connect } from 'react-redux'; import find from 'lodash/find'; // Types -import { StoreState, UrlQueryMap } from 'app/types'; +import { UrlQueryMap } from '@grafana/runtime'; +import { StoreState } from 'app/types'; import { NavModel, NavModelItem, diff --git a/public/app/routes/GrafanaCtrl.ts b/public/app/routes/GrafanaCtrl.ts index 0550fb09628..53e0431a093 100644 --- a/public/app/routes/GrafanaCtrl.ts +++ b/public/app/routes/GrafanaCtrl.ts @@ -16,6 +16,9 @@ import { KeybindingSrv, setKeybindingSrv } from 'app/core/services/keybindingSrv import { AngularLoader, setAngularLoader } from 'app/core/services/AngularLoader'; import { configureStore } from 'app/store/configureStore'; +import { LocationUpdate, setLocationSrv } from '@grafana/runtime'; +import { updateLocation } from 'app/core/actions'; + // Types import { KioskUrlValue } from 'app/types'; @@ -40,7 +43,12 @@ export class GrafanaCtrl { setDataSourceSrv(datasourceSrv); setTimeSrv(timeSrv); setKeybindingSrv(keybindingSrv); - configureStore(); + const store = configureStore(); + setLocationSrv({ + update: (opt: LocationUpdate) => { + store.dispatch(updateLocation(opt)); + }, + }); $scope.init = () => { $scope.contextSrv = contextSrv; diff --git a/public/app/store/configureStore.ts b/public/app/store/configureStore.ts index 63d8eaaf718..31c1d3964d7 100644 --- a/public/app/store/configureStore.ts +++ b/public/app/store/configureStore.ts @@ -89,6 +89,8 @@ export function configureStore() { ? applyMiddleware(toggleLogActionsMiddleware, thunk, epicMiddleware, logger) : applyMiddleware(thunk, epicMiddleware); - setStore(createStore(rootReducer, {}, composeEnhancers(storeEnhancers))); + const store = createStore(rootReducer, {}, composeEnhancers(storeEnhancers)); + setStore(store); epicMiddleware.run(rootEpic); + return store; } diff --git a/public/app/types/location.ts b/public/app/types/location.ts index 4730f9d6ed7..13a4e88ab79 100644 --- a/public/app/types/location.ts +++ b/public/app/types/location.ts @@ -1,13 +1,4 @@ -export interface LocationUpdate { - path?: string; - query?: UrlQueryMap; - routeParams?: UrlQueryMap; - partial?: boolean; - /* - * If true this will replace url state (ie cause no new browser history) - */ - replace?: boolean; -} +import { UrlQueryMap } from '@grafana/runtime'; export interface LocationState { url: string; @@ -17,6 +8,3 @@ export interface LocationState { replace: boolean; lastUpdated: number; } - -export type UrlQueryValue = string | number | boolean | string[] | number[] | boolean[]; -export type UrlQueryMap = { [s: string]: UrlQueryValue };