mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Now handles all dashbord routes
This commit is contained in:
@@ -8,12 +8,13 @@ export const initialState: LocationState = {
|
|||||||
path: '',
|
path: '',
|
||||||
query: {},
|
query: {},
|
||||||
routeParams: {},
|
routeParams: {},
|
||||||
|
replace: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const locationReducer = (state = initialState, action: Action): LocationState => {
|
export const locationReducer = (state = initialState, action: Action): LocationState => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case CoreActionTypes.UpdateLocation: {
|
case CoreActionTypes.UpdateLocation: {
|
||||||
const { path, routeParams } = action.payload;
|
const { path, routeParams, replace } = action.payload;
|
||||||
let query = action.payload.query || state.query;
|
let query = action.payload.query || state.query;
|
||||||
|
|
||||||
if (action.payload.partial) {
|
if (action.payload.partial) {
|
||||||
@@ -26,6 +27,7 @@ export const locationReducer = (state = initialState, action: Action): LocationS
|
|||||||
path: path || state.path,
|
path: path || state.path,
|
||||||
query: { ...query },
|
query: { ...query },
|
||||||
routeParams: routeParams || state.routeParams,
|
routeParams: routeParams || state.routeParams,
|
||||||
|
replace: replace === true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ export class BridgeSrv {
|
|||||||
if (angularUrl !== url) {
|
if (angularUrl !== url) {
|
||||||
this.$timeout(() => {
|
this.$timeout(() => {
|
||||||
this.$location.url(url);
|
this.$location.url(url);
|
||||||
|
// some state changes should not trigger new browser history
|
||||||
|
if (state.location.replace) {
|
||||||
|
this.$location.replace();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
console.log('store updating angular $location.url', url);
|
console.log('store updating angular $location.url', url);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,9 +22,8 @@ import { updateLocation } from 'app/core/actions';
|
|||||||
import { notifyApp } from 'app/core/actions';
|
import { notifyApp } from 'app/core/actions';
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { StoreState } from 'app/types';
|
import { StoreState, DashboardLoadingState, DashboardRouteInfo } from 'app/types';
|
||||||
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
||||||
import { DashboardLoadingState } from 'app/types/dashboard';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
urlUid?: string;
|
urlUid?: string;
|
||||||
@@ -32,8 +31,10 @@ interface Props {
|
|||||||
urlType?: string;
|
urlType?: string;
|
||||||
editview?: string;
|
editview?: string;
|
||||||
urlPanelId?: string;
|
urlPanelId?: string;
|
||||||
|
urlFolderId?: string;
|
||||||
$scope: any;
|
$scope: any;
|
||||||
$injector: any;
|
$injector: any;
|
||||||
|
routeInfo: DashboardRouteInfo;
|
||||||
urlEdit: boolean;
|
urlEdit: boolean;
|
||||||
urlFullscreen: boolean;
|
urlFullscreen: boolean;
|
||||||
loadingState: DashboardLoadingState;
|
loadingState: DashboardLoadingState;
|
||||||
@@ -66,6 +67,8 @@ export class DashboardPage extends PureComponent<Props, State> {
|
|||||||
urlSlug: this.props.urlSlug,
|
urlSlug: this.props.urlSlug,
|
||||||
urlUid: this.props.urlUid,
|
urlUid: this.props.urlUid,
|
||||||
urlType: this.props.urlType,
|
urlType: this.props.urlType,
|
||||||
|
urlFolderId: this.props.urlFolderId,
|
||||||
|
routeInfo: this.props.routeInfo,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,6 +211,7 @@ const mapStateToProps = (state: StoreState) => ({
|
|||||||
urlType: state.location.routeParams.type,
|
urlType: state.location.routeParams.type,
|
||||||
editview: state.location.query.editview,
|
editview: state.location.query.editview,
|
||||||
urlPanelId: state.location.query.panelId,
|
urlPanelId: state.location.query.panelId,
|
||||||
|
urlFolderId: state.location.query.folderId,
|
||||||
urlFullscreen: state.location.query.fullscreen === true,
|
urlFullscreen: state.location.query.fullscreen === true,
|
||||||
urlEdit: state.location.query.edit === true,
|
urlEdit: state.location.query.edit === true,
|
||||||
loadingState: state.dashboard.loadingState,
|
loadingState: state.dashboard.loadingState,
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ export class DashboardViewStateSrv {
|
|||||||
self.dashboard = $scope.dashboard;
|
self.dashboard = $scope.dashboard;
|
||||||
|
|
||||||
$scope.onAppEvent('$routeUpdate', () => {
|
$scope.onAppEvent('$routeUpdate', () => {
|
||||||
const urlState = self.getQueryStringState();
|
// const urlState = self.getQueryStringState();
|
||||||
if (self.needsSync(urlState)) {
|
// if (self.needsSync(urlState)) {
|
||||||
self.update(urlState, true);
|
// self.update(urlState, true);
|
||||||
}
|
// }
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.onAppEvent('panel-change-view', (evt, payload) => {
|
$scope.onAppEvent('panel-change-view', (evt, payload) => {
|
||||||
@@ -35,8 +35,8 @@ export class DashboardViewStateSrv {
|
|||||||
|
|
||||||
// this marks changes to location during this digest cycle as not to add history item
|
// this marks changes to location during this digest cycle as not to add history item
|
||||||
// don't want url changes like adding orgId to add browser history
|
// don't want url changes like adding orgId to add browser history
|
||||||
$location.replace();
|
// $location.replace();
|
||||||
this.update(this.getQueryStringState());
|
// this.update(this.getQueryStringState());
|
||||||
}
|
}
|
||||||
|
|
||||||
needsSync(urlState) {
|
needsSync(urlState) {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { setDashboardLoadingState, ThunkResult, setDashboardModel } from './acti
|
|||||||
import { removePanel } from '../utils/panel';
|
import { removePanel } from '../utils/panel';
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { DashboardLoadingState } from 'app/types/dashboard';
|
import { DashboardLoadingState, DashboardRouteInfo } from 'app/types';
|
||||||
import { DashboardModel } from './DashboardModel';
|
import { DashboardModel } from './DashboardModel';
|
||||||
|
|
||||||
export interface InitDashboardArgs {
|
export interface InitDashboardArgs {
|
||||||
@@ -24,6 +24,8 @@ export interface InitDashboardArgs {
|
|||||||
urlUid?: string;
|
urlUid?: string;
|
||||||
urlSlug?: string;
|
urlSlug?: string;
|
||||||
urlType?: string;
|
urlType?: string;
|
||||||
|
urlFolderId: string;
|
||||||
|
routeInfo: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function redirectToNewUrl(slug: string, dispatch: any) {
|
async function redirectToNewUrl(slug: string, dispatch: any) {
|
||||||
@@ -35,36 +37,67 @@ async function redirectToNewUrl(slug: string, dispatch: any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initDashboard({ $injector, $scope, urlUid, urlSlug, urlType }: InitDashboardArgs): ThunkResult<void> {
|
export function initDashboard({
|
||||||
return async dispatch => {
|
$injector,
|
||||||
// handle old urls with no uid
|
$scope,
|
||||||
if (!urlUid && urlSlug && !urlType) {
|
urlUid,
|
||||||
redirectToNewUrl(urlSlug, dispatch);
|
urlSlug,
|
||||||
return;
|
urlType,
|
||||||
}
|
urlFolderId,
|
||||||
|
routeInfo,
|
||||||
|
}: InitDashboardArgs): ThunkResult<void> {
|
||||||
|
return async (dispatch, getState) => {
|
||||||
let dashDTO = null;
|
let dashDTO = null;
|
||||||
|
|
||||||
// set fetching state
|
// set fetching state
|
||||||
dispatch(setDashboardLoadingState(DashboardLoadingState.Fetching));
|
dispatch(setDashboardLoadingState(DashboardLoadingState.Fetching));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// if no uid or slug, load home dashboard
|
switch (routeInfo) {
|
||||||
if (!urlUid && !urlSlug) {
|
// handle old urls with no uid
|
||||||
dashDTO = await getBackendSrv().get('/api/dashboards/home');
|
case DashboardRouteInfo.Old: {
|
||||||
|
redirectToNewUrl(urlSlug, dispatch);
|
||||||
if (dashDTO.redirectUri) {
|
|
||||||
const newUrl = locationUtil.stripBaseFromUrl(dashDTO.redirectUri);
|
|
||||||
dispatch(updateLocation({ path: newUrl }));
|
|
||||||
return;
|
return;
|
||||||
} else {
|
}
|
||||||
|
case DashboardRouteInfo.Home: {
|
||||||
|
// load home dash
|
||||||
|
dashDTO = await getBackendSrv().get('/api/dashboards/home');
|
||||||
|
|
||||||
|
// if user specified a custom home dashboard redirect to that
|
||||||
|
if (dashDTO.redirectUri) {
|
||||||
|
const newUrl = locationUtil.stripBaseFromUrl(dashDTO.redirectUri);
|
||||||
|
dispatch(updateLocation({ path: newUrl, replace: true }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable some actions on the default home dashboard
|
||||||
dashDTO.meta.canSave = false;
|
dashDTO.meta.canSave = false;
|
||||||
dashDTO.meta.canShare = false;
|
dashDTO.meta.canShare = false;
|
||||||
dashDTO.meta.canStar = false;
|
dashDTO.meta.canStar = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DashboardRouteInfo.Normal: {
|
||||||
|
const loaderSrv = $injector.get('dashboardLoaderSrv');
|
||||||
|
dashDTO = await loaderSrv.loadDashboard(urlType, urlSlug, urlUid);
|
||||||
|
|
||||||
|
// check if the current url is correct (might be old slug)
|
||||||
|
const dashboardUrl = locationUtil.stripBaseFromUrl(dashDTO.meta.url);
|
||||||
|
const currentPath = getState().location.path;
|
||||||
|
console.log('loading dashboard: currentPath', currentPath);
|
||||||
|
console.log('loading dashboard: dashboardUrl', dashboardUrl);
|
||||||
|
|
||||||
|
if (dashboardUrl !== currentPath) {
|
||||||
|
// replace url to not create additional history items and then return so that initDashboard below isn't executed multiple times.
|
||||||
|
dispatch(updateLocation({path: dashboardUrl, partial: true, replace: true}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DashboardRouteInfo.New: {
|
||||||
|
dashDTO = getNewDashboardModelData(urlFolderId);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
const loaderSrv = $injector.get('dashboardLoaderSrv');
|
|
||||||
dashDTO = await loaderSrv.loadDashboard(urlType, urlSlug, urlUid);
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
dispatch(setDashboardLoadingState(DashboardLoadingState.Error));
|
dispatch(setDashboardLoadingState(DashboardLoadingState.Error));
|
||||||
@@ -136,3 +169,30 @@ export function initDashboard({ $injector, $scope, urlUid, urlSlug, urlType }: I
|
|||||||
dispatch(setDashboardModel(dashboard));
|
dispatch(setDashboardModel(dashboard));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getNewDashboardModelData(urlFolderId?: string): any {
|
||||||
|
const data = {
|
||||||
|
meta: {
|
||||||
|
canStar: false,
|
||||||
|
canShare: false,
|
||||||
|
isNew: true,
|
||||||
|
folderId: 0,
|
||||||
|
},
|
||||||
|
dashboard: {
|
||||||
|
title: 'New dashboard',
|
||||||
|
panels: [
|
||||||
|
{
|
||||||
|
type: 'add-panel',
|
||||||
|
gridPos: { x: 0, y: 0, w: 12, h: 9 },
|
||||||
|
title: 'Panel Title',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (urlFolderId) {
|
||||||
|
data.meta.folderId = parseInt(urlFolderId, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ export function reactContainer(
|
|||||||
$injector: $injector,
|
$injector: $injector,
|
||||||
$rootScope: $rootScope,
|
$rootScope: $rootScope,
|
||||||
$scope: scope,
|
$scope: scope,
|
||||||
|
routeInfo: $route.current.$$route.routeInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
ReactDOM.render(WrapInProvider(store, component, props), elem[0]);
|
ReactDOM.render(WrapInProvider(store, component, props), elem[0]);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import './dashboard_loaders';
|
|||||||
import './ReactContainer';
|
import './ReactContainer';
|
||||||
import { applyRouteRegistrationHandlers } from './registry';
|
import { applyRouteRegistrationHandlers } from './registry';
|
||||||
|
|
||||||
|
// Pages
|
||||||
import ServerStats from 'app/features/admin/ServerStats';
|
import ServerStats from 'app/features/admin/ServerStats';
|
||||||
import AlertRuleList from 'app/features/alerting/AlertRuleList';
|
import AlertRuleList from 'app/features/alerting/AlertRuleList';
|
||||||
import TeamPages from 'app/features/teams/TeamPages';
|
import TeamPages from 'app/features/teams/TeamPages';
|
||||||
@@ -23,6 +24,9 @@ import SoloPanelPage from '../features/dashboard/containers/SoloPanelPage';
|
|||||||
import DashboardPage from '../features/dashboard/containers/DashboardPage';
|
import DashboardPage from '../features/dashboard/containers/DashboardPage';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
|
|
||||||
|
// Types
|
||||||
|
import { DashboardRouteInfo } from 'app/types';
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
export function setupAngularRoutes($routeProvider, $locationProvider) {
|
export function setupAngularRoutes($routeProvider, $locationProvider) {
|
||||||
$locationProvider.html5Mode(true);
|
$locationProvider.html5Mode(true);
|
||||||
@@ -31,6 +35,7 @@ export function setupAngularRoutes($routeProvider, $locationProvider) {
|
|||||||
.when('/', {
|
.when('/', {
|
||||||
template: '<react-container />',
|
template: '<react-container />',
|
||||||
pageClass: 'page-dashboard',
|
pageClass: 'page-dashboard',
|
||||||
|
routeInfo: DashboardRouteInfo.Home,
|
||||||
reloadOnSearch: false,
|
reloadOnSearch: false,
|
||||||
resolve: {
|
resolve: {
|
||||||
component: () => DashboardPage,
|
component: () => DashboardPage,
|
||||||
@@ -39,6 +44,7 @@ export function setupAngularRoutes($routeProvider, $locationProvider) {
|
|||||||
.when('/d/:uid/:slug', {
|
.when('/d/:uid/:slug', {
|
||||||
template: '<react-container />',
|
template: '<react-container />',
|
||||||
pageClass: 'page-dashboard',
|
pageClass: 'page-dashboard',
|
||||||
|
routeInfo: DashboardRouteInfo.Normal,
|
||||||
reloadOnSearch: false,
|
reloadOnSearch: false,
|
||||||
resolve: {
|
resolve: {
|
||||||
component: () => DashboardPage,
|
component: () => DashboardPage,
|
||||||
@@ -48,6 +54,7 @@ export function setupAngularRoutes($routeProvider, $locationProvider) {
|
|||||||
template: '<react-container />',
|
template: '<react-container />',
|
||||||
pageClass: 'page-dashboard',
|
pageClass: 'page-dashboard',
|
||||||
reloadOnSearch: false,
|
reloadOnSearch: false,
|
||||||
|
routeInfo: DashboardRouteInfo.Normal,
|
||||||
resolve: {
|
resolve: {
|
||||||
component: () => DashboardPage,
|
component: () => DashboardPage,
|
||||||
},
|
},
|
||||||
@@ -55,6 +62,16 @@ export function setupAngularRoutes($routeProvider, $locationProvider) {
|
|||||||
.when('/dashboard/:type/:slug', {
|
.when('/dashboard/:type/:slug', {
|
||||||
template: '<react-container />',
|
template: '<react-container />',
|
||||||
pageClass: 'page-dashboard',
|
pageClass: 'page-dashboard',
|
||||||
|
routeInfo: DashboardRouteInfo.Old,
|
||||||
|
reloadOnSearch: false,
|
||||||
|
resolve: {
|
||||||
|
component: () => DashboardPage,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.when('/dashboard/new', {
|
||||||
|
template: '<react-container />',
|
||||||
|
pageClass: 'page-dashboard',
|
||||||
|
routeInfo: DashboardRouteInfo.New,
|
||||||
reloadOnSearch: false,
|
reloadOnSearch: false,
|
||||||
resolve: {
|
resolve: {
|
||||||
component: () => DashboardPage,
|
component: () => DashboardPage,
|
||||||
@@ -63,6 +80,7 @@ export function setupAngularRoutes($routeProvider, $locationProvider) {
|
|||||||
.when('/d-solo/:uid/:slug', {
|
.when('/d-solo/:uid/:slug', {
|
||||||
template: '<react-container />',
|
template: '<react-container />',
|
||||||
pageClass: 'dashboard-solo',
|
pageClass: 'dashboard-solo',
|
||||||
|
routeInfo: DashboardRouteInfo.Normal,
|
||||||
resolve: {
|
resolve: {
|
||||||
component: () => SoloPanelPage,
|
component: () => SoloPanelPage,
|
||||||
},
|
},
|
||||||
@@ -70,16 +88,11 @@ export function setupAngularRoutes($routeProvider, $locationProvider) {
|
|||||||
.when('/dashboard-solo/:type/:slug', {
|
.when('/dashboard-solo/:type/:slug', {
|
||||||
template: '<react-container />',
|
template: '<react-container />',
|
||||||
pageClass: 'dashboard-solo',
|
pageClass: 'dashboard-solo',
|
||||||
|
routeInfo: DashboardRouteInfo.Old,
|
||||||
resolve: {
|
resolve: {
|
||||||
component: () => SoloPanelPage,
|
component: () => SoloPanelPage,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.when('/dashboard/new', {
|
|
||||||
templateUrl: 'public/app/partials/dashboard.html',
|
|
||||||
controller: 'NewDashboardCtrl',
|
|
||||||
reloadOnSearch: false,
|
|
||||||
pageClass: 'page-dashboard',
|
|
||||||
})
|
|
||||||
.when('/dashboard/import', {
|
.when('/dashboard/import', {
|
||||||
templateUrl: 'public/app/features/manage-dashboards/partials/dashboard_import.html',
|
templateUrl: 'public/app/features/manage-dashboards/partials/dashboard_import.html',
|
||||||
controller: DashboardImportCtrl,
|
controller: DashboardImportCtrl,
|
||||||
|
|||||||
@@ -7,9 +7,16 @@ export interface MutableDashboard {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum DashboardRouteInfo {
|
||||||
|
Old = 'old-dashboard',
|
||||||
|
Home = 'home-dashboard',
|
||||||
|
New = 'new-dashboard',
|
||||||
|
Normal = 'normal-dashboard',
|
||||||
|
}
|
||||||
|
|
||||||
export enum DashboardLoadingState {
|
export enum DashboardLoadingState {
|
||||||
NotStarted = 'Not started',
|
NotStarted = 'Not started',
|
||||||
Fetching = 'Fetching',
|
Fetching = 'Fetching',
|
||||||
Initializing = 'Initializing',
|
Initializing = 'Initializing',
|
||||||
Error = 'Error',
|
Error = 'Error',
|
||||||
Done = 'Done',
|
Done = 'Done',
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ export interface LocationUpdate {
|
|||||||
query?: UrlQueryMap;
|
query?: UrlQueryMap;
|
||||||
routeParams?: UrlQueryMap;
|
routeParams?: UrlQueryMap;
|
||||||
partial?: boolean;
|
partial?: boolean;
|
||||||
|
/*
|
||||||
|
* If true this will replace url state (ie cause no new browser history)
|
||||||
|
*/
|
||||||
|
replace?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LocationState {
|
export interface LocationState {
|
||||||
@@ -10,6 +14,7 @@ export interface LocationState {
|
|||||||
path: string;
|
path: string;
|
||||||
query: UrlQueryMap;
|
query: UrlQueryMap;
|
||||||
routeParams: UrlQueryMap;
|
routeParams: UrlQueryMap;
|
||||||
|
replace: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UrlQueryValue = string | number | boolean | string[] | number[] | boolean[];
|
export type UrlQueryValue = string | number | boolean | string[] | number[] | boolean[];
|
||||||
|
|||||||
Reference in New Issue
Block a user