Skip to content

Commit 90af3ff

Browse files
authored
Merge branch 'alpha' into download-all
2 parents a1c19b0 + 7180e9c commit 90af3ff

File tree

6 files changed

+165
-46
lines changed

6 files changed

+165
-46
lines changed

changelogs/CHANGELOG_alpha.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# [5.1.0-alpha.2](https://github.com/ParsePlatform/parse-dashboard/compare/5.1.0-alpha.1...5.1.0-alpha.2) (2023-01-20)
2+
3+
4+
### Bug Fixes
5+
6+
* Blank screen shown if server is unreachable; unsupported pages are accessible via direct URLs ([#2363](https://github.com/ParsePlatform/parse-dashboard/issues/2363)) ([9855258](https://github.com/ParsePlatform/parse-dashboard/commit/98552584df4d8d75d65d3e394b4acad522117a96))
7+
18
# [5.1.0-alpha.1](https://github.com/ParsePlatform/parse-dashboard/compare/5.0.0...5.1.0-alpha.1) (2022-11-05)
29

310

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "parse-dashboard",
3-
"version": "5.1.0-alpha.1",
3+
"version": "5.1.0-alpha.2",
44
"repository": {
55
"type": "git",
66
"url": "https://github.com/ParsePlatform/parse-dashboard"

src/dashboard/Dashboard.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,21 +138,21 @@ export default class Dashboard extends React.Component {
138138
if (error.code === 100) {
139139
app.serverInfo = {
140140
error: 'unable to connect to server',
141-
enabledFeatures: {},
141+
features: {},
142142
parseServerVersion: 'unknown'
143143
}
144144
return Promise.resolve(app);
145145
} else if (error.code === 107) {
146146
app.serverInfo = {
147147
error: 'server version too low',
148-
enabledFeatures: {},
148+
features: {},
149149
parseServerVersion: 'unknown'
150150
}
151151
return Promise.resolve(app);
152152
} else {
153153
app.serverInfo = {
154154
error: error.message || 'unknown error',
155-
enabledFeatures: {},
155+
features: {},
156156
parseServerVersion: 'unknown'
157157
}
158158
return Promise.resolve(app);

src/dashboard/Dashboard.scss

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,25 @@ body:global(.expanded) {
1717
.content {
1818
margin-left: $sidebarCollapsedWidth;
1919
}
20+
}
21+
22+
.loadingError {
23+
font-size: 58px;
24+
color: #ffffff;
25+
}
26+
27+
.empty {
28+
position: relative;
29+
background: #1e3b4d;
30+
min-height: 100vh;
31+
text-align: center;
32+
}
33+
34+
.cloud {
35+
width: 170px;
36+
height: 170px;
37+
border-radius: 100%;
38+
padding-top: 30px;
39+
background: #3E5566;
40+
margin: 0 auto 14px auto;
2041
}

src/dashboard/DashboardView.react.js

Lines changed: 132 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -8,82 +8,125 @@
88
import React from 'react';
99
import Sidebar from 'components/Sidebar/Sidebar.react';
1010
import styles from 'dashboard/Dashboard.scss';
11+
import Icon from 'components/Icon/Icon.react';
12+
import baseStyles from 'stylesheets/base.scss';
13+
import Button from 'components/Button/Button.react';
1114
import { CurrentApp } from 'context/currentApp';
1215

1316
export default class DashboardView extends React.Component {
1417
static contextType = CurrentApp;
15-
1618
/* A DashboardView renders two pieces: the sidebar, and the app itself */
19+
20+
constructor() {
21+
super();
22+
this.state = {
23+
route: '',
24+
};
25+
}
26+
27+
componentDidUpdate() {
28+
this.onRouteChanged();
29+
}
30+
componentDidMount() {
31+
this.onRouteChanged();
32+
}
33+
34+
onRouteChanged() {
35+
const appId = this.context.applicationId;
36+
const path = this.props.location?.pathname ?? window.location.pathname;
37+
const route = path.split(appId)[1].split('/')[1];
38+
if (route !== this.state.route) {
39+
this.setState({ route });
40+
}
41+
}
42+
1743
render() {
1844
let sidebarChildren = null;
1945
if (typeof this.renderSidebar === 'function') {
2046
sidebarChildren = this.renderSidebar();
2147
}
22-
let appSlug = (this.context ? this.context.slug : '');
48+
let appSlug = this.context ? this.context.slug : '';
2349

2450
if (!this.context.hasCheckedForMigraton) {
25-
this.context.getMigrations().promise
26-
.then(() => this.forceUpdate(), () => {});
51+
this.context.getMigrations().promise.then(
52+
() => this.forceUpdate(),
53+
() => {}
54+
);
2755
}
2856

2957
let features = this.context.serverInfo.features;
3058

3159
let coreSubsections = [];
32-
if (features.schemas &&
60+
if (
61+
features.schemas &&
3362
features.schemas.addField &&
3463
features.schemas.removeField &&
3564
features.schemas.addClass &&
36-
features.schemas.removeClass) {
65+
features.schemas.removeClass
66+
) {
3767
coreSubsections.push({
3868
name: 'Browser',
39-
link: '/browser'
69+
link: '/browser',
4070
});
4171
}
4272

4373
if (features.cloudCode && features.cloudCode.viewCode) {
4474
coreSubsections.push({
4575
name: 'Cloud Code',
46-
link: '/cloud_code'
76+
link: '/cloud_code',
4777
});
4878
}
4979

5080
//webhooks requires removal of heroku link code, then it should work.
51-
if (features.hooks && features.hooks.create && features.hooks.read && features.hooks.update && features.hooks.delete) {
81+
if (
82+
features.hooks &&
83+
features.hooks.create &&
84+
features.hooks.read &&
85+
features.hooks.update &&
86+
features.hooks.delete
87+
) {
5288
coreSubsections.push({
5389
name: 'Webhooks',
54-
link: '/webhooks'
90+
link: '/webhooks',
5591
});
5692
}
5793

5894
if (features.cloudCode && features.cloudCode.jobs) {
5995
coreSubsections.push({
6096
name: 'Jobs',
61-
link: '/jobs'
97+
link: '/jobs',
6298
});
6399
}
64100

65-
if (features.logs && Object.keys(features.logs).some(key => features.logs[key])) {
101+
if (
102+
features.logs &&
103+
Object.keys(features.logs).some((key) => features.logs[key])
104+
) {
66105
coreSubsections.push({
67106
name: 'Logs',
68-
link: '/logs'
107+
link: '/logs',
69108
});
70109
}
71110

72-
if (features.globalConfig &&
111+
if (
112+
features.globalConfig &&
73113
features.globalConfig.create &&
74114
features.globalConfig.read &&
75115
features.globalConfig.update &&
76-
features.globalConfig.delete) {
116+
features.globalConfig.delete
117+
) {
77118
coreSubsections.push({
78119
name: 'Config',
79-
link: '/config'
120+
link: '/config',
80121
});
81122
}
82123

83-
coreSubsections.push({
84-
name: 'API Console',
85-
link: '/api_console'
86-
});
124+
if (!this.context.serverInfo.error) {
125+
coreSubsections.push({
126+
name: 'API Console',
127+
link: '/api_console',
128+
});
129+
}
87130

88131
if (this.context.migration) {
89132
coreSubsections.push({
@@ -96,21 +139,21 @@ export default class DashboardView extends React.Component {
96139
if (features.push && features.push.immediatePush) {
97140
pushSubsections.push({
98141
name: 'Send New Push',
99-
link: '/push/new'
142+
link: '/push/new',
100143
});
101144
}
102145

103146
if (features.push && features.push.storedPushData) {
104147
pushSubsections.push({
105148
name: 'Past Pushes',
106-
link: '/push/activity'
149+
link: '/push/activity',
107150
});
108151
}
109152

110153
if (features.push && features.push.pushAudiences) {
111154
pushSubsections.push({
112155
name: 'Audiences',
113-
link: '/push/audiences'
156+
link: '/push/audiences',
114157
});
115158
}
116159

@@ -195,7 +238,7 @@ export default class DashboardView extends React.Component {
195238
});
196239
}*/
197240

198-
let appSidebarSections = []
241+
let appSidebarSections = [];
199242

200243
if (coreSubsections.length > 0) {
201244
appSidebarSections.push({
@@ -211,7 +254,7 @@ export default class DashboardView extends React.Component {
211254
name: 'Push',
212255
icon: 'push-outline',
213256
link: '/push',
214-
style: {paddingLeft: '16px'},
257+
style: { paddingLeft: '16px' },
215258
subsections: pushSubsections,
216259
});
217260
}
@@ -221,7 +264,7 @@ export default class DashboardView extends React.Component {
221264
name: 'Analytics',
222265
icon: 'analytics-outline',
223266
link: '/analytics',
224-
subsections: analyticsSidebarSections
267+
subsections: analyticsSidebarSections,
225268
});
226269
}
227270

@@ -230,29 +273,77 @@ export default class DashboardView extends React.Component {
230273
name: 'App Settings',
231274
icon: 'gear-solid',
232275
link: '/settings',
233-
subsections: settingsSections
276+
subsections: settingsSections,
234277
});
235278
}
236279

237280
let sidebar = (
238-
<Sidebar
239-
sections={appSidebarSections}
240-
appSelector={true}
241-
section={this.section}
242-
subsection={this.subsection}
243-
prefix={'/apps/' + appSlug}
244-
action={this.action}
245-
primaryBackgroundColor={this.context.primaryBackgroundColor}
246-
secondaryBackgroundColor={this.context.secondaryBackgroundColor}
281+
<Sidebar
282+
sections={appSidebarSections}
283+
appSelector={true}
284+
section={this.section}
285+
subsection={this.subsection}
286+
prefix={'/apps/' + appSlug}
287+
action={this.action}
288+
primaryBackgroundColor={this.context.primaryBackgroundColor}
289+
secondaryBackgroundColor={this.context.secondaryBackgroundColor}
247290
>
248-
{sidebarChildren}
249-
</Sidebar>);
291+
{sidebarChildren}
292+
</Sidebar>
293+
);
294+
295+
let content = <div className={styles.content}>{this.renderContent()}</div>;
296+
const canRoute = [...coreSubsections, ...pushSubsections]
297+
.map(({ link }) => link.split('/')[1])
298+
.includes(this.state.route);
299+
300+
if (!canRoute) {
301+
content = (
302+
<div className={styles.empty}>
303+
<div className={baseStyles.center}>
304+
<div className={styles.cloud}>
305+
<Icon
306+
width={110}
307+
height={110}
308+
name="cloud-surprise"
309+
fill="#1e3b4d"
310+
/>
311+
</div>
312+
<div className={styles.loadingError}>Feature unavailable</div>
313+
</div>
314+
</div>
315+
);
316+
}
317+
318+
if (this.context.serverInfo.error) {
319+
content = (
320+
<div className={styles.empty}>
321+
<div className={baseStyles.center}>
322+
<div className={styles.cloud}>
323+
<Icon
324+
width={110}
325+
height={110}
326+
name="cloud-surprise"
327+
fill="#1e3b4d"
328+
/>
329+
</div>
330+
<div className={styles.loadingError}>
331+
{this.context.serverInfo.error.replace(/-/g, '\u2011')}
332+
</div>
333+
<Button
334+
color="white"
335+
value="Reload"
336+
width="120px"
337+
onClick={() => location.reload()}
338+
/>
339+
</div>
340+
</div>
341+
);
342+
}
250343

251344
return (
252345
<div className={styles.dashboard}>
253-
<div className={styles.content}>
254-
{this.renderContent()}
255-
</div>
346+
{content}
256347
{sidebar}
257348
</div>
258349
);

0 commit comments

Comments
 (0)