فهرست منبع

Basic loading state for slow dashboards

Torkel Ödegaard 6 سال پیش
والد
کامیت
08925ffad8

+ 0 - 1
packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx

@@ -45,7 +45,6 @@ export class CustomScrollbar extends PureComponent<Props> {
       if (this.props.scrollTop > 10000) {
         ref.scrollToBottom();
       } else {
-        console.log('scrollbar set scrollTop');
         ref.scrollTop(this.props.scrollTop);
       }
     }

+ 2 - 4
public/app/core/redux/index.ts

@@ -1,4 +1,2 @@
-import { actionCreatorFactory } from './actionCreatorFactory';
-import { reducerFactory } from './reducerFactory';
-
-export { actionCreatorFactory, reducerFactory };
+export { actionCreatorFactory, noPayloadActionCreatorFactory, ActionOf } from './actionCreatorFactory';
+export { reducerFactory } from './reducerFactory';

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

@@ -38,6 +38,7 @@ interface Props {
   urlEdit: boolean;
   urlFullscreen: boolean;
   loadingState: DashboardLoadingState;
+  isLoadingSlow: boolean;
   dashboard: DashboardModel;
   initDashboard: typeof initDashboard;
   setDashboardModel: typeof setDashboardModel;
@@ -52,6 +53,7 @@ interface State {
   fullscreenPanel: PanelModel | null;
   scrollTop: number;
   rememberScrollTop: number;
+  showLoadingState: boolean;
 }
 
 export class DashboardPage extends PureComponent<Props, State> {
@@ -59,6 +61,7 @@ export class DashboardPage extends PureComponent<Props, State> {
     isSettingsOpening: false,
     isEditing: false,
     isFullscreen: false,
+    showLoadingState: false,
     fullscreenPanel: null,
     scrollTop: 0,
     rememberScrollTop: 0,
@@ -196,11 +199,24 @@ export class DashboardPage extends PureComponent<Props, State> {
     this.setState({ scrollTop: 0 });
   };
 
+  renderLoadingState() {
+    return (
+      <div className="dashboard-loading">
+        <div className="dashboard-loading__text">
+          <i className="fa fa-spinner fa-spin" /> Dashboard {this.props.loadingState}
+        </div>
+      </div>
+    );
+  }
+
   render() {
-    const { dashboard, editview, $injector } = this.props;
+    const { dashboard, editview, $injector, isLoadingSlow } = this.props;
     const { isSettingsOpening, isEditing, isFullscreen, scrollTop } = this.state;
 
     if (!dashboard) {
+      if (isLoadingSlow) {
+        return this.renderLoadingState();
+      }
       return null;
     }
 
@@ -249,6 +265,7 @@ const mapStateToProps = (state: StoreState) => ({
   urlFullscreen: state.location.query.fullscreen === true,
   urlEdit: state.location.query.edit === true,
   loadingState: state.dashboard.loadingState,
+  isLoadingSlow: state.dashboard.isLoadingSlow,
   dashboard: state.dashboard.model as DashboardModel,
 });
 

+ 2 - 2
public/app/features/dashboard/state/actions.ts

@@ -3,8 +3,7 @@ import { ThunkAction } from 'redux-thunk';
 
 // Services & Utils
 import { getBackendSrv } from 'app/core/services/backend_srv';
-import { actionCreatorFactory } from 'app/core/redux';
-import { ActionOf } from 'app/core/redux/actionCreatorFactory';
+import { actionCreatorFactory, noPayloadActionCreatorFactory, ActionOf } from 'app/core/redux';
 import { createSuccessNotification } from 'app/core/copy/appNotification';
 
 // Actions
@@ -25,6 +24,7 @@ import { DashboardLoadingState, MutableDashboard } from 'app/types/dashboard';
 export const loadDashboardPermissions = actionCreatorFactory<DashboardAclDTO[]>('LOAD_DASHBOARD_PERMISSIONS').create();
 export const setDashboardLoadingState = actionCreatorFactory<DashboardLoadingState>('SET_DASHBOARD_LOADING_STATE').create();
 export const setDashboardModel = actionCreatorFactory<MutableDashboard>('SET_DASHBOARD_MODEL').create();
+export const setDashboardLoadingSlow = noPayloadActionCreatorFactory('SET_DASHBOARD_LOADING_SLOW').create();
 
 export type Action = ActionOf<DashboardAclDTO[]>;
 export type ThunkResult<R> = ThunkAction<R, StoreState, undefined, any>;

+ 9 - 1
public/app/features/dashboard/state/initDashboard.ts

@@ -12,7 +12,7 @@ import { config } from 'app/core/config';
 import { updateLocation } from 'app/core/actions';
 import { notifyApp } from 'app/core/actions';
 import locationUtil from 'app/core/utils/location_util';
-import { setDashboardLoadingState, ThunkResult, setDashboardModel } from './actions';
+import { setDashboardLoadingState, ThunkResult, setDashboardModel, setDashboardLoadingSlow } from './actions';
 import { removePanel } from '../utils/panel';
 
 // Types
@@ -71,6 +71,14 @@ export function initDashboard({
     // set fetching state
     dispatch(setDashboardLoadingState(DashboardLoadingState.Fetching));
 
+    // Detect slow loading / initializing and set state flag
+    // This is in order to not show loading indication for fast loading dashboards as it creates blinking/flashing
+    setTimeout(() => {
+      if (getState().dashboard.model === null) {
+        dispatch(setDashboardLoadingSlow());
+      }
+    }, 500);
+
     try {
       switch (routeInfo) {
         // handle old urls with no uid

+ 11 - 2
public/app/features/dashboard/state/reducers.ts

@@ -1,10 +1,11 @@
 import { DashboardState, DashboardLoadingState } from 'app/types/dashboard';
-import { loadDashboardPermissions, setDashboardLoadingState, setDashboardModel } from './actions';
+import { loadDashboardPermissions, setDashboardLoadingState, setDashboardModel, setDashboardLoadingSlow } from './actions';
 import { reducerFactory } from 'app/core/redux';
 import { processAclItems } from 'app/core/utils/acl';
 
 export const initialState: DashboardState = {
   loadingState: DashboardLoadingState.NotStarted,
+  isLoadingSlow: false,
   model: null,
   permissions: [],
 };
@@ -28,7 +29,15 @@ export const dashboardReducer = reducerFactory(initialState)
     filter: setDashboardModel,
     mapper: (state, action) => ({
       ...state,
-      model: action.payload
+      model: action.payload,
+      isLoadingSlow: false,
+    }),
+  })
+  .addMapper({
+    filter: setDashboardLoadingSlow,
+    mapper: (state, action) => ({
+      ...state,
+      isLoadingSlow: true,
     }),
   })
   .create();

+ 1 - 0
public/app/types/dashboard.ts

@@ -25,5 +25,6 @@ export enum DashboardLoadingState {
 export interface DashboardState {
   model: MutableDashboard | null;
   loadingState: DashboardLoadingState;
+  isLoadingSlow: boolean;
   permissions: DashboardAcl[] | null;
 }

+ 11 - 0
public/sass/pages/_dashboard.scss

@@ -276,3 +276,14 @@ div.flot-text {
 .panel-full-edit {
   padding-top: $dashboard-padding;
 }
+
+.dashboard-loading {
+  height: 60vh;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.dashboard-loading__text {
+  font-size: $font-size-lg;
+}