Просмотр исходного кода

Now handles all dashbord routes

Torkel Ödegaard 6 лет назад
Родитель
Сommit
ae768193e3

+ 3 - 1
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,
       };
     }
   }

+ 4 - 0
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);
       }

+ 6 - 2
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<Props, State> {
       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,

+ 6 - 6
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) {

+ 80 - 20
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<void> {
-  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<void> {
+  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;
+}

+ 1 - 0
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]);

+ 19 - 6
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: '<react-container />',
       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: '<react-container />',
       pageClass: 'page-dashboard',
+      routeInfo: DashboardRouteInfo.Normal,
       reloadOnSearch: false,
       resolve: {
         component: () => DashboardPage,
@@ -48,6 +54,7 @@ export function setupAngularRoutes($routeProvider, $locationProvider) {
       template: '<react-container />',
       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: '<react-container />',
       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,
       resolve: {
         component: () => DashboardPage,
@@ -63,6 +80,7 @@ export function setupAngularRoutes($routeProvider, $locationProvider) {
     .when('/d-solo/:uid/:slug', {
       template: '<react-container />',
       pageClass: 'dashboard-solo',
+      routeInfo: DashboardRouteInfo.Normal,
       resolve: {
         component: () => SoloPanelPage,
       },
@@ -70,16 +88,11 @@ export function setupAngularRoutes($routeProvider, $locationProvider) {
     .when('/dashboard-solo/:type/:slug', {
       template: '<react-container />',
       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,

+ 8 - 1
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',

+ 5 - 0
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[];