From ae768193e3b78532ff7b2c2dbdbac2e7ff1fff05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 4 Feb 2019 13:49:14 +0100 Subject: [PATCH] Now handles all dashbord routes --- public/app/core/reducers/location.ts | 4 +- public/app/core/services/bridge_srv.ts | 4 + .../dashboard/containers/DashboardPage.tsx | 8 +- .../services/DashboardViewStateSrv.ts | 12 +-- .../features/dashboard/state/initDashboard.ts | 100 ++++++++++++++---- public/app/routes/ReactContainer.tsx | 1 + public/app/routes/routes.ts | 25 +++-- public/app/types/dashboard.ts | 9 +- public/app/types/location.ts | 5 + 9 files changed, 132 insertions(+), 36 deletions(-) diff --git a/public/app/core/reducers/location.ts b/public/app/core/reducers/location.ts index 6b39710dcca..c038ab53c9f 100644 --- a/public/app/core/reducers/location.ts +++ b/public/app/core/reducers/location.ts @@ -8,12 +8,13 @@ export const initialState: LocationState = { path: '', query: {}, routeParams: {}, + replace: false, }; export const locationReducer = (state = initialState, action: Action): LocationState => { switch (action.type) { case CoreActionTypes.UpdateLocation: { - const { path, routeParams } = action.payload; + const { path, routeParams, replace } = action.payload; let query = action.payload.query || state.query; if (action.payload.partial) { @@ -26,6 +27,7 @@ export const locationReducer = (state = initialState, action: Action): LocationS path: path || state.path, query: { ...query }, routeParams: routeParams || state.routeParams, + replace: replace === true, }; } } diff --git a/public/app/core/services/bridge_srv.ts b/public/app/core/services/bridge_srv.ts index 37f71946364..8bb828310cf 100644 --- a/public/app/core/services/bridge_srv.ts +++ b/public/app/core/services/bridge_srv.ts @@ -46,6 +46,10 @@ export class BridgeSrv { if (angularUrl !== url) { this.$timeout(() => { 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); } diff --git a/public/app/features/dashboard/containers/DashboardPage.tsx b/public/app/features/dashboard/containers/DashboardPage.tsx index e01998f65a9..3fbac681498 100644 --- a/public/app/features/dashboard/containers/DashboardPage.tsx +++ b/public/app/features/dashboard/containers/DashboardPage.tsx @@ -22,9 +22,8 @@ import { updateLocation } from 'app/core/actions'; import { notifyApp } from 'app/core/actions'; // Types -import { StoreState } from 'app/types'; +import { StoreState, DashboardLoadingState, DashboardRouteInfo } from 'app/types'; import { DashboardModel, PanelModel } from 'app/features/dashboard/state'; -import { DashboardLoadingState } from 'app/types/dashboard'; interface Props { urlUid?: string; @@ -32,8 +31,10 @@ interface Props { urlType?: string; editview?: string; urlPanelId?: string; + urlFolderId?: string; $scope: any; $injector: any; + routeInfo: DashboardRouteInfo; urlEdit: boolean; urlFullscreen: boolean; loadingState: DashboardLoadingState; @@ -66,6 +67,8 @@ export class DashboardPage extends PureComponent { urlSlug: this.props.urlSlug, urlUid: this.props.urlUid, 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, editview: state.location.query.editview, urlPanelId: state.location.query.panelId, + urlFolderId: state.location.query.folderId, urlFullscreen: state.location.query.fullscreen === true, urlEdit: state.location.query.edit === true, loadingState: state.dashboard.loadingState, diff --git a/public/app/features/dashboard/services/DashboardViewStateSrv.ts b/public/app/features/dashboard/services/DashboardViewStateSrv.ts index f5a68d6f647..aa64a2e93cf 100644 --- a/public/app/features/dashboard/services/DashboardViewStateSrv.ts +++ b/public/app/features/dashboard/services/DashboardViewStateSrv.ts @@ -23,10 +23,10 @@ export class DashboardViewStateSrv { self.dashboard = $scope.dashboard; $scope.onAppEvent('$routeUpdate', () => { - const urlState = self.getQueryStringState(); - if (self.needsSync(urlState)) { - self.update(urlState, true); - } + // const urlState = self.getQueryStringState(); + // if (self.needsSync(urlState)) { + // self.update(urlState, true); + // } }); $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 // don't want url changes like adding orgId to add browser history - $location.replace(); - this.update(this.getQueryStringState()); + // $location.replace(); + // this.update(this.getQueryStringState()); } needsSync(urlState) { diff --git a/public/app/features/dashboard/state/initDashboard.ts b/public/app/features/dashboard/state/initDashboard.ts index a39a7fce285..d497ef92d1f 100644 --- a/public/app/features/dashboard/state/initDashboard.ts +++ b/public/app/features/dashboard/state/initDashboard.ts @@ -15,7 +15,7 @@ import { setDashboardLoadingState, ThunkResult, setDashboardModel } from './acti import { removePanel } from '../utils/panel'; // Types -import { DashboardLoadingState } from 'app/types/dashboard'; +import { DashboardLoadingState, DashboardRouteInfo } from 'app/types'; import { DashboardModel } from './DashboardModel'; export interface InitDashboardArgs { @@ -24,6 +24,8 @@ export interface InitDashboardArgs { urlUid?: string; urlSlug?: string; urlType?: string; + urlFolderId: string; + routeInfo: string; } 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 { - return async dispatch => { - // handle old urls with no uid - if (!urlUid && urlSlug && !urlType) { - redirectToNewUrl(urlSlug, dispatch); - return; - } - +export function initDashboard({ + $injector, + $scope, + urlUid, + urlSlug, + urlType, + urlFolderId, + routeInfo, +}: InitDashboardArgs): ThunkResult { + return async (dispatch, getState) => { let dashDTO = null; // set fetching state dispatch(setDashboardLoadingState(DashboardLoadingState.Fetching)); try { - // if no uid or slug, load home dashboard - if (!urlUid && !urlSlug) { - dashDTO = await getBackendSrv().get('/api/dashboards/home'); - - if (dashDTO.redirectUri) { - const newUrl = locationUtil.stripBaseFromUrl(dashDTO.redirectUri); - dispatch(updateLocation({ path: newUrl })); + switch (routeInfo) { + // handle old urls with no uid + case DashboardRouteInfo.Old: { + redirectToNewUrl(urlSlug, dispatch); 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.canShare = 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) { dispatch(setDashboardLoadingState(DashboardLoadingState.Error)); @@ -136,3 +169,30 @@ export function initDashboard({ $injector, $scope, urlUid, urlSlug, urlType }: I 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; +} diff --git a/public/app/routes/ReactContainer.tsx b/public/app/routes/ReactContainer.tsx index 2cad3d828bf..a56c8878fb1 100644 --- a/public/app/routes/ReactContainer.tsx +++ b/public/app/routes/ReactContainer.tsx @@ -44,6 +44,7 @@ export function reactContainer( $injector: $injector, $rootScope: $rootScope, $scope: scope, + routeInfo: $route.current.$$route.routeInfo, }; ReactDOM.render(WrapInProvider(store, component, props), elem[0]); diff --git a/public/app/routes/routes.ts b/public/app/routes/routes.ts index abe347d689a..ecd934cdccf 100644 --- a/public/app/routes/routes.ts +++ b/public/app/routes/routes.ts @@ -2,6 +2,7 @@ import './dashboard_loaders'; import './ReactContainer'; import { applyRouteRegistrationHandlers } from './registry'; +// Pages import ServerStats from 'app/features/admin/ServerStats'; import AlertRuleList from 'app/features/alerting/AlertRuleList'; 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 config from 'app/core/config'; +// Types +import { DashboardRouteInfo } from 'app/types'; + /** @ngInject */ export function setupAngularRoutes($routeProvider, $locationProvider) { $locationProvider.html5Mode(true); @@ -31,6 +35,7 @@ export function setupAngularRoutes($routeProvider, $locationProvider) { .when('/', { template: '', pageClass: 'page-dashboard', + routeInfo: DashboardRouteInfo.Home, reloadOnSearch: false, resolve: { component: () => DashboardPage, @@ -39,6 +44,7 @@ export function setupAngularRoutes($routeProvider, $locationProvider) { .when('/d/:uid/:slug', { template: '', pageClass: 'page-dashboard', + routeInfo: DashboardRouteInfo.Normal, reloadOnSearch: false, resolve: { component: () => DashboardPage, @@ -48,6 +54,7 @@ export function setupAngularRoutes($routeProvider, $locationProvider) { template: '', pageClass: 'page-dashboard', reloadOnSearch: false, + routeInfo: DashboardRouteInfo.Normal, resolve: { component: () => DashboardPage, }, @@ -55,6 +62,16 @@ export function setupAngularRoutes($routeProvider, $locationProvider) { .when('/dashboard/:type/:slug', { template: '', pageClass: 'page-dashboard', + routeInfo: DashboardRouteInfo.Old, + reloadOnSearch: false, + resolve: { + component: () => DashboardPage, + }, + }) + .when('/dashboard/new', { + template: '', + pageClass: 'page-dashboard', + routeInfo: DashboardRouteInfo.New, reloadOnSearch: false, resolve: { component: () => DashboardPage, @@ -63,6 +80,7 @@ export function setupAngularRoutes($routeProvider, $locationProvider) { .when('/d-solo/:uid/:slug', { template: '', pageClass: 'dashboard-solo', + routeInfo: DashboardRouteInfo.Normal, resolve: { component: () => SoloPanelPage, }, @@ -70,16 +88,11 @@ export function setupAngularRoutes($routeProvider, $locationProvider) { .when('/dashboard-solo/:type/:slug', { template: '', pageClass: 'dashboard-solo', + routeInfo: DashboardRouteInfo.Old, resolve: { component: () => SoloPanelPage, }, }) - .when('/dashboard/new', { - templateUrl: 'public/app/partials/dashboard.html', - controller: 'NewDashboardCtrl', - reloadOnSearch: false, - pageClass: 'page-dashboard', - }) .when('/dashboard/import', { templateUrl: 'public/app/features/manage-dashboards/partials/dashboard_import.html', controller: DashboardImportCtrl, diff --git a/public/app/types/dashboard.ts b/public/app/types/dashboard.ts index 9b1e750e859..9b8f539aeb2 100644 --- a/public/app/types/dashboard.ts +++ b/public/app/types/dashboard.ts @@ -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 { NotStarted = 'Not started', - Fetching = 'Fetching', + Fetching = 'Fetching', Initializing = 'Initializing', Error = 'Error', Done = 'Done', diff --git a/public/app/types/location.ts b/public/app/types/location.ts index 7dcf57f7e02..a47ef05d2be 100644 --- a/public/app/types/location.ts +++ b/public/app/types/location.ts @@ -3,6 +3,10 @@ export interface LocationUpdate { query?: UrlQueryMap; routeParams?: UrlQueryMap; partial?: boolean; + /* + * If true this will replace url state (ie cause no new browser history) + */ + replace?: boolean; } export interface LocationState { @@ -10,6 +14,7 @@ export interface LocationState { path: string; query: UrlQueryMap; routeParams: UrlQueryMap; + replace: boolean; } export type UrlQueryValue = string | number | boolean | string[] | number[] | boolean[];