浏览代码

Fixed lots of loading flow issues and updated solo route page

Torkel Ödegaard 6 年之前
父节点
当前提交
d978a66ef6

+ 1 - 1
public/app/core/utils/location_util.ts

@@ -1,6 +1,6 @@
 import config from 'app/core/config';
 
-export const stripBaseFromUrl = url => {
+export const stripBaseFromUrl = (url: string): string => {
   const appSubUrl = config.appSubUrl;
   const stripExtraChars = appSubUrl.endsWith('/') ? 1 : 0;
   const urlWithoutBase =

+ 89 - 71
public/app/features/dashboard/components/DashNav/DashNav.tsx

@@ -5,6 +5,7 @@ import { connect } from 'react-redux';
 // Utils & Services
 import { AngularComponent, getAngularLoader } from 'app/core/services/AngularLoader';
 import { appEvents } from 'app/core/app_events';
+import { PlaylistSrv } from 'app/features/playlist/playlist_srv';
 
 // Components
 import { DashNavButton } from './DashNavButton';
@@ -116,12 +117,13 @@ export class DashNav extends PureComponent<Props> {
   };
 
   render() {
-    const { dashboard, isFullscreen, editview } = this.props;
+    const { dashboard, isFullscreen, editview, $injector } = this.props;
     const { canStar, canSave, canShare, folderTitle, showSettings, isStarred } = dashboard.meta;
     const { snapshot } = dashboard;
 
     const haveFolder = dashboard.meta.folderId > 0;
     const snapshotUrl = snapshot && snapshot.originalUrl;
+    const playlistSrv: PlaylistSrv = $injector.get('playlistSrv');
 
     return (
       <div className="navbar">
@@ -135,87 +137,103 @@ export class DashNav extends PureComponent<Props> {
         </div>
 
         <div className="navbar__spacer" />
-        {/*
-        <div class="navbar-buttons navbar-buttons--playlist" ng-if="ctrl.playlistSrv.isPlaying">
-          <a class="navbar-button navbar-button--tight" ng-click="ctrl.playlistSrv.prev()"><i class="fa fa-step-backward"></i></a>
-          <a class="navbar-button navbar-button--tight" ng-click="ctrl.playlistSrv.stop()"><i class="fa fa-stop"></i></a>
-          <a class="navbar-button navbar-button--tight" ng-click="ctrl.playlistSrv.next()"><i class="fa fa-step-forward"></i></a>
-        </div>
-        */}
 
-        <div className="navbar-buttons navbar-buttons--actions">
-          {canSave && (
+        {playlistSrv.isPlaying && (
+          <div className="navbar-buttons navbar-buttons--playlist">
             <DashNavButton
-              tooltip="Add panel"
-              classSuffix="add-panel"
-              icon="gicon gicon-add-panel"
-              onClick={this.onAddPanel}
+              tooltip="Jump to previous dashboard"
+              classSuffix="tight"
+              icon="fa fa-step-backward"
+              onClick={() => playlistSrv.prev()}
             />
-          )}
-
-          {canStar && (
             <DashNavButton
-              tooltip="Mark as favorite"
-              classSuffix="star"
-              icon={`${isStarred ? 'fa fa-star' : 'fa fa-star-o'}`}
-              onClick={this.onStarDashboard}
+              tooltip="Stop playlist"
+              classSuffix="tight"
+              icon="fa fa-stop"
+              onClick={() => playlistSrv.stop()}
             />
-          )}
-
-          {canShare && (
             <DashNavButton
-              tooltip="Share dashboard"
-              classSuffix="share"
-              icon="fa fa-share-square-o"
-              onClick={this.onOpenShare}
+              tooltip="Jump forward"
+              classSuffix="tight"
+              icon="fa fa-forward"
+              onClick={() => playlistSrv.next()}
             />
-          )}
+          </div>
+        )}
 
+        <div className="navbar-buttons navbar-buttons--actions">
           {canSave && (
-            <DashNavButton tooltip="Save dashboard" classSuffix="save" icon="fa fa-save" onClick={this.onSave} />
-          )}
-
-          {snapshotUrl && (
             <DashNavButton
-              tooltip="Open original dashboard"
-              classSuffix="snapshot-origin"
-              icon="fa fa-link"
-              href={snapshotUrl}
-            />
-          )}
-
-          {showSettings && (
-            <DashNavButton
-              tooltip="Dashboard settings"
-              classSuffix="settings"
-              icon="fa fa-cog"
-              onClick={this.onOpenSettings}
-            />
-          )}
-        </div>
-
-        <div className="navbar-buttons navbar-buttons--tv">
-          <DashNavButton
-            tooltip="Cycke view mode"
-            classSuffix="tv"
-            icon="fa fa-desktop"
-            onClick={this.onToggleTVMode}
-          />
-        </div>
-
-        <div className="gf-timepicker-nav" ref={element => (this.timePickerEl = element)} />
-
-        {(isFullscreen || editview) && (
-          <div className="navbar-buttons navbar-buttons--close">
-            <DashNavButton
-              tooltip="Back to dashboard"
-              classSuffix="primary"
-              icon="fa fa-reply"
-              onClick={this.onClose}
+              tooltip="Add panel"
+              classSuffix="add-panel"
+              icon="gicon gicon-add-panel"
+              onClick={this.onAddPanel}
             />
-          </div>
-        )}
-      </div>
+            )}
+
+            {canStar && (
+              <DashNavButton
+                tooltip="Mark as favorite"
+                classSuffix="star"
+                icon={`${isStarred ? 'fa fa-star' : 'fa fa-star-o'}`}
+                onClick={this.onStarDashboard}
+              />
+              )}
+
+              {canShare && (
+                <DashNavButton
+                  tooltip="Share dashboard"
+                  classSuffix="share"
+                  icon="fa fa-share-square-o"
+                  onClick={this.onOpenShare}
+                />
+                )}
+
+                {canSave && (
+                  <DashNavButton tooltip="Save dashboard" classSuffix="save" icon="fa fa-save" onClick={this.onSave} />
+                  )}
+
+                  {snapshotUrl && (
+                    <DashNavButton
+                      tooltip="Open original dashboard"
+                      classSuffix="snapshot-origin"
+                      icon="fa fa-link"
+                      href={snapshotUrl}
+                    />
+                    )}
+
+                    {showSettings && (
+                      <DashNavButton
+                        tooltip="Dashboard settings"
+                        classSuffix="settings"
+                        icon="fa fa-cog"
+                        onClick={this.onOpenSettings}
+                      />
+                      )}
+                    </div>
+
+                    <div className="navbar-buttons navbar-buttons--tv">
+                      <DashNavButton
+                        tooltip="Cycke view mode"
+                        classSuffix="tv"
+                        icon="fa fa-desktop"
+                        onClick={this.onToggleTVMode}
+                      />
+                    </div>
+
+                    <div className="gf-timepicker-nav" ref={element => (this.timePickerEl = element)} />
+
+                    {(isFullscreen || editview) && (
+                      <div className="navbar-buttons navbar-buttons--close">
+                        <DashNavButton
+                          tooltip="Back to dashboard"
+                          classSuffix="primary"
+                          icon="fa fa-reply"
+                          onClick={this.onClose}
+                        />
+                      </div>
+                    )}
+                  </div>
     );
   }
 }

+ 1 - 0
public/app/features/dashboard/containers/DashboardPage.tsx

@@ -69,6 +69,7 @@ export class DashboardPage extends PureComponent<Props, State> {
       urlType: this.props.urlType,
       urlFolderId: this.props.urlFolderId,
       routeInfo: this.props.routeInfo,
+      fixUrl: true,
     });
   }
 

+ 37 - 55
public/app/features/dashboard/containers/SoloPanelPage.tsx

@@ -3,98 +3,78 @@ import React, { Component } from 'react';
 import { hot } from 'react-hot-loader';
 import { connect } from 'react-redux';
 
-// Utils & Services
-import appEvents from 'app/core/app_events';
-import locationUtil from 'app/core/utils/location_util';
-import { getBackendSrv } from 'app/core/services/backend_srv';
-
 // Components
 import { DashboardPanel } from '../dashgrid/DashboardPanel';
 
 // Redux
-import { updateLocation } from 'app/core/actions';
+import { initDashboard } from '../state/initDashboard';
 
 // Types
-import { StoreState } from 'app/types';
+import { StoreState, DashboardRouteInfo } from 'app/types';
 import { PanelModel, DashboardModel } from 'app/features/dashboard/state';
 
 interface Props {
-  panelId: string;
+  urlPanelId: string;
   urlUid?: string;
   urlSlug?: string;
   urlType?: string;
   $scope: any;
   $injector: any;
-  updateLocation: typeof updateLocation;
+  routeInfo: DashboardRouteInfo;
+  initDashboard: typeof initDashboard;
+  dashboard: DashboardModel | null;
 }
 
 interface State {
   panel: PanelModel | null;
-  dashboard: DashboardModel | null;
   notFound: boolean;
 }
 
 export class SoloPanelPage extends Component<Props, State> {
-
   state: State = {
     panel: null,
-    dashboard: null,
     notFound: false,
   };
 
   componentDidMount() {
-    const { $injector, $scope, urlUid, urlType, urlSlug } = this.props;
-
-    // handle old urls with no uid
-    if (!urlUid && !(urlType === 'script' || urlType === 'snapshot')) {
-      this.redirectToNewUrl();
-      return;
-    }
-
-    const dashboardLoaderSrv = $injector.get('dashboardLoaderSrv');
-
-    // subscribe to event to know when dashboard controller is done with inititalization
-    appEvents.on('dashboard-initialized', this.onDashoardInitialized);
-
-    dashboardLoaderSrv.loadDashboard(urlType, urlSlug, urlUid).then(result => {
-      result.meta.soloMode = true;
-      $scope.initDashboard(result, $scope);
+    const { $injector, $scope, urlUid, urlType, urlSlug, routeInfo } = this.props;
+
+    this.props.initDashboard({
+      $injector: $injector,
+      $scope: $scope,
+      urlSlug: urlSlug,
+      urlUid: urlUid,
+      urlType: urlType,
+      routeInfo: routeInfo,
+      fixUrl: false,
     });
   }
 
-  redirectToNewUrl() {
-    getBackendSrv().getDashboardBySlug(this.props.urlSlug).then(res => {
-      if (res) {
-        const url = locationUtil.stripBaseFromUrl(res.meta.url.replace('/d/', '/d-solo/'));
-        this.props.updateLocation(url);
-      }
-    });
-  }
-
-  onDashoardInitialized = () => {
-    const { $scope, panelId } = this.props;
+  componentDidUpdate(prevProps: Props) {
+    const { urlPanelId, dashboard } = this.props;
 
-    const dashboard: DashboardModel = $scope.dashboard;
-    const panel = dashboard.getPanelById(parseInt(panelId, 10));
-
-    if (!panel) {
-      this.setState({ notFound: true });
+    if (!dashboard) {
       return;
     }
 
-    this.setState({ dashboard, panel });
-  };
+    // we just got the dashboard!
+    if (!prevProps.dashboard) {
+      const panel = dashboard.getPanelById(parseInt(urlPanelId, 10));
+      if (!panel) {
+        this.setState({ notFound: true });
+        return;
+      }
+
+      this.setState({ panel });
+    }
+  }
 
   render() {
-    const { panelId } = this.props;
-    const { notFound, panel, dashboard } = this.state;
+    const { urlPanelId, dashboard } = this.props;
+    const { notFound, panel } = this.state;
 
     if (notFound) {
-      return (
-        <div className="alert alert-error">
-          Panel with id { panelId } not found
-        </div>
-      );
+      return <div className="alert alert-error">Panel with id {urlPanelId} not found</div>;
     }
 
     if (!panel) {
@@ -113,11 +93,13 @@ const mapStateToProps = (state: StoreState) => ({
   urlUid: state.location.routeParams.uid,
   urlSlug: state.location.routeParams.slug,
   urlType: state.location.routeParams.type,
-  panelId: state.location.query.panelId
+  urlPanelId: state.location.query.panelId,
+  loadingState: state.dashboard.loadingState,
+  dashboard: state.dashboard.model as DashboardModel,
 });
 
 const mapDispatchToProps = {
-  updateLocation
+  initDashboard,
 };
 
 export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(SoloPanelPage));

+ 0 - 1
public/app/features/dashboard/services/DashboardSrv.ts

@@ -8,7 +8,6 @@ export class DashboardSrv {
 
   /** @ngInject */
   constructor(private backendSrv, private $rootScope, private $location) {
-    appEvents.on('save-dashboard', this.saveDashboard.bind(this), $rootScope);
     appEvents.on('save-dashboard', this.saveDashboard.bind(this), $rootScope);
     appEvents.on('panel-change-view', this.onPanelChangeView);
   }

+ 15 - 6
public/app/features/dashboard/state/initDashboard.ts

@@ -25,16 +25,24 @@ export interface InitDashboardArgs {
   urlUid?: string;
   urlSlug?: string;
   urlType?: string;
-  urlFolderId: string;
+  urlFolderId?: string;
   routeInfo: string;
+  fixUrl: boolean;
 }
 
-async function redirectToNewUrl(slug: string, dispatch: any) {
+async function redirectToNewUrl(slug: string, dispatch: any, currentPath: string) {
   const res = await getBackendSrv().getDashboardBySlug(slug);
 
   if (res) {
-    const url = locationUtil.stripBaseFromUrl(res.meta.url.replace('/d/', '/d-solo/'));
-    dispatch(updateLocation(url));
+    let newUrl = res.meta.url;
+
+    // fix solo route urls
+    if (currentPath.indexOf('dashboard-solo') !== -1) {
+      newUrl = newUrl.replace('/d/', '/d-solo/');
+    }
+
+    const url = locationUtil.stripBaseFromUrl(newUrl);
+    dispatch(updateLocation({ path: url, partial: true, replace: true }));
   }
 }
 
@@ -46,6 +54,7 @@ export function initDashboard({
   urlType,
   urlFolderId,
   routeInfo,
+  fixUrl,
 }: InitDashboardArgs): ThunkResult<void> {
   return async (dispatch, getState) => {
     let dashDTO = null;
@@ -76,14 +85,14 @@ export function initDashboard({
         case DashboardRouteInfo.Normal: {
           // for old db routes we redirect
           if (urlType === 'db') {
-            redirectToNewUrl(urlSlug, dispatch);
+            redirectToNewUrl(urlSlug, dispatch, getState().location.path);
             return;
           }
 
           const loaderSrv = $injector.get('dashboardLoaderSrv');
           dashDTO = await loaderSrv.loadDashboard(urlType, urlSlug, urlUid);
 
-          if (dashDTO.meta.url) {
+          if (fixUrl && dashDTO.meta.url) {
             // check if the current url is correct (might be old slug)
             const dashboardUrl = locationUtil.stripBaseFromUrl(dashDTO.meta.url);
             const currentPath = getState().location.path;

+ 0 - 6
public/app/routes/GrafanaCtrl.ts

@@ -45,12 +45,6 @@ export class GrafanaCtrl {
     };
 
     $rootScope.colors = colors;
-
-    $scope.initDashboard = (dashboardData, viewScope) => {
-      $scope.appEvent('dashboard-fetch-end', dashboardData);
-      $controller('DashboardCtrl', { $scope: viewScope }).init(dashboardData);
-    };
-
     $rootScope.onAppEvent = function(name, callback, localScope) {
       const unbind = $rootScope.$on(name, callback);
       let callerScope = this;