From 60f700a1d217593ee1bca29d0be12328b21e0fde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Sat, 2 Feb 2019 19:23:19 +0100 Subject: [PATCH] wip: dashboard react --- .../dashboard/containers/DashboardCtrl.ts | 6 - .../dashboard/containers/DashboardPage.tsx | 138 ++++++++++++++++++ .../features/dashboard/state/initDashboard.ts | 5 + public/app/routes/routes.ts | 9 +- 4 files changed, 149 insertions(+), 9 deletions(-) create mode 100644 public/app/features/dashboard/containers/DashboardPage.tsx create mode 100644 public/app/features/dashboard/state/initDashboard.ts diff --git a/public/app/features/dashboard/containers/DashboardCtrl.ts b/public/app/features/dashboard/containers/DashboardCtrl.ts index 74795315504..0151f8f7331 100644 --- a/public/app/features/dashboard/containers/DashboardCtrl.ts +++ b/public/app/features/dashboard/containers/DashboardCtrl.ts @@ -31,12 +31,6 @@ export class DashboardCtrl { // temp hack due to way dashboards are loaded // can't use controllerAs on route yet $scope.ctrl = this; - - // TODO: break out settings view to separate view & controller - this.editTab = 0; - - // funcs called from React component bindings and needs this binding - this.getPanelContainer = this.getPanelContainer.bind(this); } setupDashboard(data) { diff --git a/public/app/features/dashboard/containers/DashboardPage.tsx b/public/app/features/dashboard/containers/DashboardPage.tsx new file mode 100644 index 00000000000..54eed34fc29 --- /dev/null +++ b/public/app/features/dashboard/containers/DashboardPage.tsx @@ -0,0 +1,138 @@ +// Libraries +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'; + +// Types +import { StoreState } from 'app/types'; +import { DashboardModel } from 'app/features/dashboard/state'; + +interface Props { + panelId: string; + urlUid?: string; + urlSlug?: string; + urlType?: string; + $scope: any; + $injector: any; + updateLocation: typeof updateLocation; + notifyApp: typeof notifyApp; +} + +interface State { + dashboard: DashboardModel | null; + notFound: boolean; +} + +export class DashboardPage extends Component { + state: State = { + dashboard: null, + notFound: false, + }; + + async componentDidMount() { + 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 }); + } + + render() { + const { notFound, dashboard } = this.state; + + if (notFound) { + return
Dashboard not found
; + } + + if (!dashboard) { + return ; + } + + return
title: {dashboard.title}
; + } +} + +const mapStateToProps = (state: StoreState) => ({ + urlUid: state.location.routeParams.uid, + urlSlug: state.location.routeParams.slug, + urlType: state.location.routeParams.type, + panelId: state.location.query.panelId, +}); + +const mapDispatchToProps = { + updateLocation, + notifyApp, +}; + +export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(DashboardPage)); diff --git a/public/app/features/dashboard/state/initDashboard.ts b/public/app/features/dashboard/state/initDashboard.ts new file mode 100644 index 00000000000..3b2307b3ccc --- /dev/null +++ b/public/app/features/dashboard/state/initDashboard.ts @@ -0,0 +1,5 @@ + + +export function initDashboard(dashboard: DashboardModel, $injector: any, $scope: any) { + +} diff --git a/public/app/routes/routes.ts b/public/app/routes/routes.ts index 0f4c09a9c77..cdd9ed89a08 100644 --- a/public/app/routes/routes.ts +++ b/public/app/routes/routes.ts @@ -20,6 +20,7 @@ import DataSourceDashboards from 'app/features/datasources/DataSourceDashboards' import DataSourceSettingsPage from '../features/datasources/settings/DataSourceSettingsPage'; import OrgDetailsPage from '../features/org/OrgDetailsPage'; import SoloPanelPage from '../features/dashboard/containers/SoloPanelPage'; +import DashboardPage from '../features/dashboard/containers/DashboardPage'; import config from 'app/core/config'; /** @ngInject */ @@ -34,10 +35,12 @@ export function setupAngularRoutes($routeProvider, $locationProvider) { pageClass: 'page-dashboard', }) .when('/d/:uid/:slug', { - templateUrl: 'public/app/partials/dashboard.html', - controller: 'LoadDashboardCtrl', - reloadOnSearch: false, + template: '', pageClass: 'page-dashboard', + reloadOnSearch: false, + resolve: { + component: () => DashboardPage, + }, }) .when('/d/:uid', { templateUrl: 'public/app/partials/dashboard.html',