mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
wip: minor progress
This commit is contained in:
parent
60f700a1d2
commit
d86e773c75
@ -3,21 +3,16 @@ import React, { Component } from 'react';
|
||||
import { hot } from 'react-hot-loader';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
// Utils & Services
|
||||
import locationUtil from 'app/core/utils/location_util';
|
||||
import { getBackendSrv } from 'app/core/services/backend_srv';
|
||||
import { createErrorNotification } from 'app/core/copy/appNotification';
|
||||
|
||||
// Components
|
||||
import { LoadingPlaceholder } from '@grafana/ui';
|
||||
|
||||
// Redux
|
||||
import { updateLocation } from 'app/core/actions';
|
||||
import { notifyApp } from 'app/core/actions';
|
||||
import { initDashboard } from '../state/initDashboard';
|
||||
|
||||
// Types
|
||||
import { StoreState } from 'app/types';
|
||||
import { DashboardModel } from 'app/features/dashboard/state';
|
||||
import { DashboardLoadingState } from 'app/types/dashboard';
|
||||
|
||||
interface Props {
|
||||
panelId: string;
|
||||
@ -26,8 +21,9 @@ interface Props {
|
||||
urlType?: string;
|
||||
$scope: any;
|
||||
$injector: any;
|
||||
updateLocation: typeof updateLocation;
|
||||
notifyApp: typeof notifyApp;
|
||||
initDashboard: typeof initDashboard;
|
||||
loadingState: DashboardLoadingState;
|
||||
dashboard: DashboardModel;
|
||||
}
|
||||
|
||||
interface State {
|
||||
@ -42,81 +38,54 @@ export class DashboardPage extends Component<Props, State> {
|
||||
};
|
||||
|
||||
async componentDidMount() {
|
||||
const { $injector, urlUid, urlType, urlSlug } = this.props;
|
||||
this.props.initDashboard({
|
||||
injector: this.props.$injector,
|
||||
scope: this.props.$scope,
|
||||
urlSlug: this.props.urlSlug,
|
||||
urlUid: this.props.urlUid,
|
||||
urlType: this.props.urlType,
|
||||
})
|
||||
|
||||
// handle old urls with no uid
|
||||
if (!urlUid && !(urlType === 'script' || urlType === 'snapshot')) {
|
||||
this.redirectToNewUrl();
|
||||
return;
|
||||
}
|
||||
|
||||
const loaderSrv = $injector.get('dashboardLoaderSrv');
|
||||
const dashDTO = await loaderSrv.loadDashboard(urlType, urlSlug, urlUid);
|
||||
|
||||
try {
|
||||
this.initDashboard(dashDTO);
|
||||
} catch (err) {
|
||||
this.props.notifyApp(createErrorNotification('Failed to init dashboard', err.toString()));
|
||||
console.log(err);
|
||||
}
|
||||
// const { $injector, urlUid, urlType, urlSlug } = this.props;
|
||||
//
|
||||
// // handle old urls with no uid
|
||||
// if (!urlUid && !(urlType === 'script' || urlType === 'snapshot')) {
|
||||
// this.redirectToNewUrl();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// const loaderSrv = $injector.get('dashboardLoaderSrv');
|
||||
// const dashDTO = await loaderSrv.loadDashboard(urlType, urlSlug, urlUid);
|
||||
//
|
||||
// try {
|
||||
// this.initDashboard(dashDTO);
|
||||
// } catch (err) {
|
||||
// this.props.notifyApp(createErrorNotification('Failed to init dashboard', err.toString()));
|
||||
// console.log(err);
|
||||
// }
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
initDashboard(dashDTO: any) {
|
||||
const dashboard = new DashboardModel(dashDTO.dashboard, dashDTO.meta);
|
||||
|
||||
// init services
|
||||
this.timeSrv.init(dashboard);
|
||||
this.annotationsSrv.init(dashboard);
|
||||
|
||||
// template values service needs to initialize completely before
|
||||
// the rest of the dashboard can load
|
||||
this.variableSrv
|
||||
.init(dashboard)
|
||||
// template values failes are non fatal
|
||||
.catch(this.onInitFailed.bind(this, 'Templating init failed', false))
|
||||
// continue
|
||||
.finally(() => {
|
||||
this.dashboard = dashboard;
|
||||
this.dashboard.processRepeats();
|
||||
this.dashboard.updateSubmenuVisibility();
|
||||
this.dashboard.autoFitPanels(window.innerHeight);
|
||||
|
||||
this.unsavedChangesSrv.init(dashboard, this.$scope);
|
||||
|
||||
// TODO refactor ViewStateSrv
|
||||
this.$scope.dashboard = dashboard;
|
||||
this.dashboardViewState = this.dashboardViewStateSrv.create(this.$scope);
|
||||
|
||||
this.keybindingSrv.setupDashboardBindings(this.$scope, dashboard);
|
||||
this.setWindowTitleAndTheme();
|
||||
|
||||
appEvents.emit('dashboard-initialized', dashboard);
|
||||
})
|
||||
.catch(this.onInitFailed.bind(this, 'Dashboard init failed', true));
|
||||
|
||||
this.setState({ dashboard });
|
||||
}
|
||||
// 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);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// initDashboard(dashDTO: any) {
|
||||
// const dashboard = new DashboardModel(dashDTO.dashboard, dashDTO.meta);
|
||||
// this.setState({ dashboard });
|
||||
// }
|
||||
|
||||
render() {
|
||||
const { notFound, dashboard } = this.state;
|
||||
|
||||
if (notFound) {
|
||||
return <div className="alert alert-error">Dashboard not found</div>;
|
||||
}
|
||||
const { loadingState, dashboard } = this.props;
|
||||
|
||||
if (!dashboard) {
|
||||
return <LoadingPlaceholder text="Loading dashboard" />;
|
||||
return <LoadingPlaceholder text={loadingState.toString()} />;
|
||||
}
|
||||
|
||||
return <div>title: {dashboard.title}</div>;
|
||||
@ -128,11 +97,12 @@ const mapStateToProps = (state: StoreState) => ({
|
||||
urlSlug: state.location.routeParams.slug,
|
||||
urlType: state.location.routeParams.type,
|
||||
panelId: state.location.query.panelId,
|
||||
loadingState: state.dashboard.loadingState,
|
||||
dashboard: state.dashboard as DashboardModel,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
updateLocation,
|
||||
notifyApp,
|
||||
initDashboard
|
||||
};
|
||||
|
||||
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(DashboardPage));
|
||||
|
@ -1,8 +1,18 @@
|
||||
// Libaries
|
||||
import { StoreState } from 'app/types';
|
||||
import { ThunkAction } from 'redux-thunk';
|
||||
|
||||
// Services & Utils
|
||||
import { getBackendSrv } from 'app/core/services/backend_srv';
|
||||
import appEvents from 'app/core/app_events';
|
||||
import { actionCreatorFactory } from 'app/core/redux';
|
||||
import { ActionOf } from 'app/core/redux/actionCreatorFactory';
|
||||
import { createSuccessNotification } from 'app/core/copy/appNotification';
|
||||
|
||||
// Actions
|
||||
import { loadPluginDashboards } from '../../plugins/state/actions';
|
||||
import { notifyApp } from 'app/core/actions';
|
||||
|
||||
// Types
|
||||
import {
|
||||
DashboardAcl,
|
||||
DashboardAclDTO,
|
||||
@ -10,30 +20,14 @@ import {
|
||||
DashboardAclUpdateDTO,
|
||||
NewDashboardAclItem,
|
||||
} from 'app/types/acl';
|
||||
import { DashboardLoadingState } from 'app/types/dashboard';
|
||||
|
||||
export enum ActionTypes {
|
||||
LoadDashboardPermissions = 'LOAD_DASHBOARD_PERMISSIONS',
|
||||
LoadStarredDashboards = 'LOAD_STARRED_DASHBOARDS',
|
||||
}
|
||||
export const loadDashboardPermissions = actionCreatorFactory<DashboardAclDTO[]>('LOAD_DASHBOARD_PERMISSIONS').create();
|
||||
export const setDashboardLoadingState = actionCreatorFactory<DashboardLoadingState>('SET_DASHBOARD_LOADING_STATE').create();
|
||||
|
||||
export interface LoadDashboardPermissionsAction {
|
||||
type: ActionTypes.LoadDashboardPermissions;
|
||||
payload: DashboardAcl[];
|
||||
}
|
||||
export type Action = ActionOf<DashboardAclDTO[]>;
|
||||
|
||||
export interface LoadStarredDashboardsAction {
|
||||
type: ActionTypes.LoadStarredDashboards;
|
||||
payload: DashboardAcl[];
|
||||
}
|
||||
|
||||
export type Action = LoadDashboardPermissionsAction | LoadStarredDashboardsAction;
|
||||
|
||||
type ThunkResult<R> = ThunkAction<R, StoreState, undefined, any>;
|
||||
|
||||
export const loadDashboardPermissions = (items: DashboardAclDTO[]): LoadDashboardPermissionsAction => ({
|
||||
type: ActionTypes.LoadDashboardPermissions,
|
||||
payload: items,
|
||||
});
|
||||
export type ThunkResult<R> = ThunkAction<R, StoreState, undefined, any>;
|
||||
|
||||
export function getDashboardPermissions(id: number): ThunkResult<void> {
|
||||
return async dispatch => {
|
||||
@ -124,7 +118,7 @@ export function addDashboardPermission(dashboardId: number, newItem: NewDashboar
|
||||
export function importDashboard(data, dashboardTitle: string): ThunkResult<void> {
|
||||
return async dispatch => {
|
||||
await getBackendSrv().post('/api/dashboards/import', data);
|
||||
appEvents.emit('alert-success', ['Dashboard Imported', dashboardTitle]);
|
||||
dispatch(notifyApp(createSuccessNotification('Dashboard Imported', dashboardTitle)));
|
||||
dispatch(loadPluginDashboards());
|
||||
};
|
||||
}
|
||||
@ -135,3 +129,4 @@ export function removeDashboard(uri: string): ThunkResult<void> {
|
||||
dispatch(loadPluginDashboards());
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,70 @@
|
||||
// Libaries
|
||||
import { StoreState } from 'app/types';
|
||||
import { ThunkAction } from 'redux-thunk';
|
||||
|
||||
// Services & Utils
|
||||
import { getBackendSrv } from 'app/core/services/backend_srv';
|
||||
import { createErrorNotification } from 'app/core/copy/appNotification';
|
||||
|
||||
export function initDashboard(dashboard: DashboardModel, $injector: any, $scope: any) {
|
||||
// Actions
|
||||
import { updateLocation } from 'app/core/actions';
|
||||
import { notifyApp } from 'app/core/actions';
|
||||
import locationUtil from 'app/core/utils/location_util';
|
||||
import { setDashboardLoadingState, ThunkResult } from './actions';
|
||||
|
||||
// Types
|
||||
import { DashboardLoadingState } from 'app/types/dashboard';
|
||||
import { DashboardModel } from './DashboardModel';
|
||||
|
||||
export interface InitDashboardArgs {
|
||||
injector: any;
|
||||
scope: any;
|
||||
urlUid?: string;
|
||||
urlSlug?: string;
|
||||
urlType?: string;
|
||||
}
|
||||
|
||||
export function initDashboard({ injector, scope, urlUid, urlSlug, urlType }: InitDashboardArgs): ThunkResult<void> {
|
||||
return async dispatch => {
|
||||
const loaderSrv = injector.get('dashboardLoaderSrv');
|
||||
|
||||
dispatch(setDashboardLoadingState(DashboardLoadingState.Fetching));
|
||||
|
||||
try {
|
||||
// fetch dashboard from api
|
||||
const dashDTO = await loaderSrv.loadDashboard(urlType, urlSlug, urlUid);
|
||||
// set initializing state
|
||||
dispatch(setDashboardLoadingState(DashboardLoadingState.Initializing));
|
||||
// create model
|
||||
const dashboard = new DashboardModel(dashDTO.dashboard, dashDTO.meta);
|
||||
// init services
|
||||
|
||||
injector.get('timeSrv').init(dashboard);
|
||||
injector.get('annotationsSrv').init(dashboard);
|
||||
|
||||
// template values service needs to initialize completely before
|
||||
// the rest of the dashboard can load
|
||||
injector.get('variableSrv').init(dashboard)
|
||||
.catch(err => {
|
||||
dispatch(notifyApp(createErrorNotification('Templating init failed')));
|
||||
})
|
||||
.finally(() => {
|
||||
|
||||
dashboard.processRepeats();
|
||||
dashboard.updateSubmenuVisibility();
|
||||
dashboard.autoFitPanels(window.innerHeight);
|
||||
|
||||
injector.get('unsavedChangesSrv').init(dashboard, scope);
|
||||
|
||||
scope.dashboard = dashboard;
|
||||
injector.get('dashboardViewStateSrv').create(scope);
|
||||
injector.get('keybindingSrv').setupDashboardBindings(scope, dashboard);
|
||||
})
|
||||
.catch(err => {
|
||||
dispatch(setDashboardLoadingState(DashboardLoadingState.Error));
|
||||
});
|
||||
} catch (err) {
|
||||
dispatch(setDashboardLoadingState(DashboardLoadingState.Error));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Action, ActionTypes } from './actions';
|
||||
import { Action } from './actions';
|
||||
import { OrgRole, PermissionLevel, DashboardState } from 'app/types';
|
||||
import { initialState, dashboardReducer } from './reducers';
|
||||
|
||||
@ -8,7 +8,7 @@ describe('dashboard reducer', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
const action: Action = {
|
||||
type: ActionTypes.LoadDashboardPermissions,
|
||||
type: 'LOAD_DASHBOARD_PERMISSIONS',
|
||||
payload: [
|
||||
{ id: 2, dashboardId: 1, role: OrgRole.Viewer, permission: PermissionLevel.View },
|
||||
{ id: 3, dashboardId: 1, role: OrgRole.Editor, permission: PermissionLevel.Edit },
|
||||
|
@ -1,21 +1,30 @@
|
||||
import { DashboardState } from 'app/types';
|
||||
import { Action, ActionTypes } from './actions';
|
||||
import { DashboardState, DashboardLoadingState } from 'app/types/dashboard';
|
||||
import { loadDashboardPermissions, setDashboardLoadingState } from './actions';
|
||||
import { reducerFactory } from 'app/core/redux';
|
||||
import { processAclItems } from 'app/core/utils/acl';
|
||||
|
||||
export const initialState: DashboardState = {
|
||||
loadingState: DashboardLoadingState.NotStarted,
|
||||
dashboard: null,
|
||||
permissions: [],
|
||||
};
|
||||
|
||||
export const dashboardReducer = (state = initialState, action: Action): DashboardState => {
|
||||
switch (action.type) {
|
||||
case ActionTypes.LoadDashboardPermissions:
|
||||
return {
|
||||
...state,
|
||||
permissions: processAclItems(action.payload),
|
||||
};
|
||||
}
|
||||
return state;
|
||||
};
|
||||
export const dashboardReducer = reducerFactory(initialState)
|
||||
.addMapper({
|
||||
filter: loadDashboardPermissions,
|
||||
mapper: (state, action) => ({
|
||||
...state,
|
||||
permissions: processAclItems(action.payload),
|
||||
}),
|
||||
})
|
||||
.addMapper({
|
||||
filter: setDashboardLoadingState,
|
||||
mapper: (state, action) => ({
|
||||
...state,
|
||||
loadingState: action.payload
|
||||
}),
|
||||
})
|
||||
.create()
|
||||
|
||||
export default {
|
||||
dashboard: dashboardReducer,
|
||||
|
@ -1,5 +1,18 @@
|
||||
import { DashboardAcl } from './acl';
|
||||
|
||||
export interface DashboardState {
|
||||
permissions: DashboardAcl[];
|
||||
export interface Dashboard {
|
||||
}
|
||||
|
||||
export enum DashboardLoadingState {
|
||||
NotStarted = 'Not started',
|
||||
Fetching = 'Fetching',
|
||||
Initializing = 'Initializing',
|
||||
Error = 'Error',
|
||||
Done = 'Done',
|
||||
}
|
||||
|
||||
export interface DashboardState {
|
||||
dashboard: Dashboard | null;
|
||||
loadingState: DashboardLoadingState;
|
||||
permissions: DashboardAcl[] | null;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user