Skip to content

Commit

Permalink
fix: Blank screen shown if server is unreachable; unsupported pages a…
Browse files Browse the repository at this point in the history
…re accessible via direct URLs (#2363)
  • Loading branch information
dblythy committed Jan 20, 2023
1 parent 070f649 commit 9855258
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 44 deletions.
6 changes: 3 additions & 3 deletions src/dashboard/Dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
21 changes: 21 additions & 0 deletions src/dashboard/Dashboard.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
173 changes: 132 additions & 41 deletions src/dashboard/DashboardView.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand All @@ -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',
});
}

Expand Down Expand Up @@ -195,7 +238,7 @@ export default class DashboardView extends React.Component {
});
}*/

let appSidebarSections = []
let appSidebarSections = [];

if (coreSubsections.length > 0) {
appSidebarSections.push({
Expand All @@ -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,
});
}
Expand All @@ -221,7 +264,7 @@ export default class DashboardView extends React.Component {
name: 'Analytics',
icon: 'analytics-outline',
link: '/analytics',
subsections: analyticsSidebarSections
subsections: analyticsSidebarSections,
});
}

Expand All @@ -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 = (
<Sidebar
sections={appSidebarSections}
appSelector={true}
section={this.section}
subsection={this.subsection}
prefix={'/apps/' + appSlug}
action={this.action}
primaryBackgroundColor={this.context.primaryBackgroundColor}
secondaryBackgroundColor={this.context.secondaryBackgroundColor}
<Sidebar
sections={appSidebarSections}
appSelector={true}
section={this.section}
subsection={this.subsection}
prefix={'/apps/' + appSlug}
action={this.action}
primaryBackgroundColor={this.context.primaryBackgroundColor}
secondaryBackgroundColor={this.context.secondaryBackgroundColor}
>
{sidebarChildren}
</Sidebar>);
{sidebarChildren}
</Sidebar>
);

let content = <div className={styles.content}>{this.renderContent()}</div>;
const canRoute = [...coreSubsections, ...pushSubsections]
.map(({ link }) => link.split('/')[1])
.includes(this.state.route);

if (!canRoute) {
content = (
<div className={styles.empty}>
<div className={baseStyles.center}>
<div className={styles.cloud}>
<Icon
width={110}
height={110}
name="cloud-surprise"
fill="#1e3b4d"
/>
</div>
<div className={styles.loadingError}>Feature unavailable</div>
</div>
</div>
);
}

if (this.context.serverInfo.error) {
content = (
<div className={styles.empty}>
<div className={baseStyles.center}>
<div className={styles.cloud}>
<Icon
width={110}
height={110}
name="cloud-surprise"
fill="#1e3b4d"
/>
</div>
<div className={styles.loadingError}>
{this.context.serverInfo.error.replace(/-/g, '\u2011')}
</div>
<Button
color="white"
value="Reload"
width="120px"
onClick={() => location.reload()}
/>
</div>
</div>
);
}

return (
<div className={styles.dashboard}>
<div className={styles.content}>
{this.renderContent()}
</div>
{content}
{sidebar}
</div>
);
Expand Down

0 comments on commit 9855258

Please sign in to comment.