diff --git a/src/dashboard/Dashboard.js b/src/dashboard/Dashboard.js index 3a639cdb79..9993dc0722 100644 --- a/src/dashboard/Dashboard.js +++ b/src/dashboard/Dashboard.js @@ -138,21 +138,21 @@ export default class Dashboard extends React.Component { if (error.code === 100) { app.serverInfo = { error: 'unable to connect to server', - enabledFeatures: {}, + features: {}, parseServerVersion: 'unknown' } return Promise.resolve(app); } else if (error.code === 107) { app.serverInfo = { error: 'server version too low', - enabledFeatures: {}, + features: {}, parseServerVersion: 'unknown' } return Promise.resolve(app); } else { app.serverInfo = { error: error.message || 'unknown error', - enabledFeatures: {}, + features: {}, parseServerVersion: 'unknown' } return Promise.resolve(app); diff --git a/src/dashboard/Dashboard.scss b/src/dashboard/Dashboard.scss index 140c11b2bd..c99ad86341 100644 --- a/src/dashboard/Dashboard.scss +++ b/src/dashboard/Dashboard.scss @@ -17,4 +17,25 @@ body:global(.expanded) { .content { margin-left: $sidebarCollapsedWidth; } +} + +.loadingError { + font-size: 58px; + color: #ffffff; +} + +.empty { + position: relative; + background: #1e3b4d; + min-height: 100vh; + text-align: center; +} + +.cloud { + width: 170px; + height: 170px; + border-radius: 100%; + padding-top: 30px; + background: #3E5566; + margin: 0 auto 14px auto; } \ No newline at end of file diff --git a/src/dashboard/DashboardView.react.js b/src/dashboard/DashboardView.react.js index 15972fd8e6..4846ae4c72 100644 --- a/src/dashboard/DashboardView.react.js +++ b/src/dashboard/DashboardView.react.js @@ -8,82 +8,125 @@ import React from 'react'; import Sidebar from 'components/Sidebar/Sidebar.react'; import styles from 'dashboard/Dashboard.scss'; +import Icon from 'components/Icon/Icon.react'; +import baseStyles from 'stylesheets/base.scss'; +import Button from 'components/Button/Button.react'; import { CurrentApp } from 'context/currentApp'; export default class DashboardView extends React.Component { static contextType = CurrentApp; - /* A DashboardView renders two pieces: the sidebar, and the app itself */ + + constructor() { + super(); + this.state = { + route: '', + }; + } + + componentDidUpdate() { + this.onRouteChanged(); + } + componentDidMount() { + this.onRouteChanged(); + } + + onRouteChanged() { + const appId = this.context.applicationId; + const path = this.props.location?.pathname ?? window.location.pathname; + const route = path.split(appId)[1].split('/')[1]; + if (route !== this.state.route) { + this.setState({ route }); + } + } + render() { let sidebarChildren = null; if (typeof this.renderSidebar === 'function') { sidebarChildren = this.renderSidebar(); } - let appSlug = (this.context ? this.context.slug : ''); + let appSlug = this.context ? this.context.slug : ''; if (!this.context.hasCheckedForMigraton) { - this.context.getMigrations().promise - .then(() => this.forceUpdate(), () => {}); + this.context.getMigrations().promise.then( + () => this.forceUpdate(), + () => {} + ); } let features = this.context.serverInfo.features; let coreSubsections = []; - if (features.schemas && + if ( + features.schemas && features.schemas.addField && features.schemas.removeField && features.schemas.addClass && - features.schemas.removeClass) { + features.schemas.removeClass + ) { coreSubsections.push({ name: 'Browser', - link: '/browser' + link: '/browser', }); } if (features.cloudCode && features.cloudCode.viewCode) { coreSubsections.push({ name: 'Cloud Code', - link: '/cloud_code' + link: '/cloud_code', }); } //webhooks requires removal of heroku link code, then it should work. - if (features.hooks && features.hooks.create && features.hooks.read && features.hooks.update && features.hooks.delete) { + if ( + features.hooks && + features.hooks.create && + features.hooks.read && + features.hooks.update && + features.hooks.delete + ) { coreSubsections.push({ name: 'Webhooks', - link: '/webhooks' + link: '/webhooks', }); } if (features.cloudCode && features.cloudCode.jobs) { coreSubsections.push({ name: 'Jobs', - link: '/jobs' + link: '/jobs', }); } - if (features.logs && Object.keys(features.logs).some(key => features.logs[key])) { + if ( + features.logs && + Object.keys(features.logs).some((key) => features.logs[key]) + ) { coreSubsections.push({ name: 'Logs', - link: '/logs' + link: '/logs', }); } - if (features.globalConfig && + if ( + features.globalConfig && features.globalConfig.create && features.globalConfig.read && features.globalConfig.update && - features.globalConfig.delete) { + features.globalConfig.delete + ) { coreSubsections.push({ name: 'Config', - link: '/config' + link: '/config', }); } - coreSubsections.push({ - name: 'API Console', - link: '/api_console' - }); + if (!this.context.serverInfo.error) { + coreSubsections.push({ + name: 'API Console', + link: '/api_console', + }); + } if (this.context.migration) { coreSubsections.push({ @@ -96,21 +139,21 @@ export default class DashboardView extends React.Component { if (features.push && features.push.immediatePush) { pushSubsections.push({ name: 'Send New Push', - link: '/push/new' + link: '/push/new', }); } if (features.push && features.push.storedPushData) { pushSubsections.push({ name: 'Past Pushes', - link: '/push/activity' + link: '/push/activity', }); } if (features.push && features.push.pushAudiences) { pushSubsections.push({ name: 'Audiences', - link: '/push/audiences' + link: '/push/audiences', }); } @@ -195,7 +238,7 @@ export default class DashboardView extends React.Component { }); }*/ - let appSidebarSections = [] + let appSidebarSections = []; if (coreSubsections.length > 0) { appSidebarSections.push({ @@ -211,7 +254,7 @@ export default class DashboardView extends React.Component { name: 'Push', icon: 'push-outline', link: '/push', - style: {paddingLeft: '16px'}, + style: { paddingLeft: '16px' }, subsections: pushSubsections, }); } @@ -221,7 +264,7 @@ export default class DashboardView extends React.Component { name: 'Analytics', icon: 'analytics-outline', link: '/analytics', - subsections: analyticsSidebarSections + subsections: analyticsSidebarSections, }); } @@ -230,29 +273,77 @@ export default class DashboardView extends React.Component { name: 'App Settings', icon: 'gear-solid', link: '/settings', - subsections: settingsSections + subsections: settingsSections, }); } let sidebar = ( - - {sidebarChildren} - ); + {sidebarChildren} + + ); + + let content =
{this.renderContent()}
; + const canRoute = [...coreSubsections, ...pushSubsections] + .map(({ link }) => link.split('/')[1]) + .includes(this.state.route); + + if (!canRoute) { + content = ( +
+
+
+ +
+
Feature unavailable
+
+
+ ); + } + + if (this.context.serverInfo.error) { + content = ( +
+
+
+ +
+
+ {this.context.serverInfo.error.replace(/-/g, '\u2011')} +
+
+
+ ); + } return (
-
- {this.renderContent()} -
+ {content} {sidebar}
);