Skip to content

Commit d8f19cb

Browse files
authored
Merge branch 'alpha' into download-all
2 parents 46b1346 + 9d5c72c commit d8f19cb

File tree

6 files changed

+130
-3
lines changed

6 files changed

+130
-3
lines changed

changelogs/CHANGELOG_alpha.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# [5.1.0-alpha.3](https://github.com/ParsePlatform/parse-dashboard/compare/5.1.0-alpha.2...5.1.0-alpha.3) (2023-01-20)
2+
3+
4+
### Features
5+
6+
* Add schema export ([#2362](https://github.com/ParsePlatform/parse-dashboard/issues/2362)) ([33df049](https://github.com/ParsePlatform/parse-dashboard/commit/33df0495a02c4e77f48b3566032bf5686227cce7))
7+
18
# [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)
29

310

package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

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

src/dashboard/Data/Browser/Browser.react.js

+51-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import AttachSelectedRowsDialog from 'dashboard/Data/Browser/AttachSel
2121
import CloneSelectedRowsDialog from 'dashboard/Data/Browser/CloneSelectedRowsDialog.react';
2222
import EditRowDialog from 'dashboard/Data/Browser/EditRowDialog.react';
2323
import ExportSelectedRowsDialog from 'dashboard/Data/Browser/ExportSelectedRowsDialog.react';
24+
import ExportSchemaDialog from 'dashboard/Data/Browser/ExportSchemaDialog.react';
2425
import { List, Map } from 'immutable';
2526
import Notification from 'dashboard/Data/Browser/Notification.react';
2627
import Parse from 'parse';
@@ -56,6 +57,7 @@ class Browser extends DashboardView {
5657
showRemoveColumnDialog: false,
5758
showDropClassDialog: false,
5859
showExportDialog: false,
60+
showExportSchemaDialog: false,
5961
showAttachRowsDialog: false,
6062
showEditRowDialog: false,
6163
showPointerKeyDialog: false,
@@ -90,7 +92,7 @@ class Browser extends DashboardView {
9092
requiredColumnFields: [],
9193

9294
useMasterKey: true,
93-
currentUser: Parse.User.current()
95+
currentUser: Parse.User.current(),
9496
};
9597

9698
this.prefetchData = this.prefetchData.bind(this);
@@ -116,6 +118,7 @@ class Browser extends DashboardView {
116118
this.confirmCloneSelectedRows = this.confirmCloneSelectedRows.bind(this);
117119
this.cancelCloneSelectedRows = this.cancelCloneSelectedRows.bind(this);
118120
this.showExportSelectedRowsDialog = this.showExportSelectedRowsDialog.bind(this);
121+
this.showExportSchemaDialog = this.showExportSchemaDialog.bind(this);
119122
this.confirmExportSelectedRows = this.confirmExportSelectedRows.bind(this);
120123
this.cancelExportSelectedRows = this.cancelExportSelectedRows.bind(this);
121124
this.getClassRelationColumns = this.getClassRelationColumns.bind(this);
@@ -328,6 +331,37 @@ class Browser extends DashboardView {
328331
});
329332
}
330333

334+
async exportSchema(className, all) {
335+
try {
336+
this.showNote('Exporting schema...');
337+
this.setState({ showExportSchemaDialog: false });
338+
let schema = [];
339+
if (all) {
340+
schema = await Parse.Schema.all();
341+
} else {
342+
schema = await new Parse.Schema(className).get();
343+
}
344+
const element = document.createElement('a');
345+
const file = new Blob(
346+
[
347+
JSON.stringify(
348+
schema,
349+
null,
350+
2,
351+
),
352+
],
353+
{ type: 'application/json' }
354+
);
355+
element.href = URL.createObjectURL(file);
356+
element.download = `${all ? 'schema' : className}.json`;
357+
document.body.appendChild(element); // Required for this to work in FireFox
358+
element.click();
359+
document.body.removeChild(element);
360+
} catch (msg) {
361+
this.showNote(msg, true);
362+
}
363+
}
364+
331365
newColumn(payload, required) {
332366
return this.props.schema.dispatch(ActionTypes.ADD_COLUMN, payload)
333367
.then(() => {
@@ -1091,6 +1125,7 @@ class Browser extends DashboardView {
10911125
this.state.showRemoveColumnDialog ||
10921126
this.state.showDropClassDialog ||
10931127
this.state.showExportDialog ||
1128+
this.state.showExportSchema ||
10941129
this.state.rowsToDelete ||
10951130
this.state.showAttachRowsDialog ||
10961131
this.state.showAttachSelectedRowsDialog ||
@@ -1251,6 +1286,12 @@ class Browser extends DashboardView {
12511286
});
12521287
}
12531288

1289+
showExportSchemaDialog() {
1290+
this.setState({
1291+
showExportSchemaDialog: true
1292+
})
1293+
}
1294+
12541295
cancelExportSelectedRows() {
12551296
this.setState({
12561297
rowsToExport: null
@@ -1605,6 +1646,7 @@ class Browser extends DashboardView {
16051646
onEditSelectedRow={this.showEditRowDialog}
16061647
onEditPermissions={this.onDialogToggle}
16071648
onExportSelectedRows={this.showExportSelectedRowsDialog}
1649+
onExportSchema={this.showExportSchemaDialog}
16081650

16091651
onSaveNewRow={this.saveNewRow}
16101652
onShowPointerKey={this.showPointerKeyDialog}
@@ -1719,6 +1761,14 @@ class Browser extends DashboardView {
17191761
onCancel={() => this.setState({ showExportDialog: false })}
17201762
onConfirm={() => this.exportClass(className)} />
17211763
);
1764+
} else if (this.state.showExportSchemaDialog) {
1765+
extras = (
1766+
<ExportSchemaDialog
1767+
className={className}
1768+
schema={this.props.schema.data.get('classes')}
1769+
onCancel={() => this.setState({ showExportSchemaDialog: false })}
1770+
onConfirm={(...args) => this.exportSchema(...args)} />
1771+
);
17221772
} else if (this.state.showAttachRowsDialog) {
17231773
extras = (
17241774
<AttachRowsDialog

src/dashboard/Data/Browser/BrowserToolbar.react.js

+5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ let BrowserToolbar = ({
4040
onAttachSelectedRows,
4141
onCloneSelectedRows,
4242
onExportSelectedRows,
43+
onExportSchema,
4344
onExport,
4445
onRemoveColumn,
4546
onDeleteRows,
@@ -257,6 +258,10 @@ let BrowserToolbar = ({
257258
text={'Export all rows'}
258259
onClick={() => onExportSelectedRows({ '*': true })}
259260
/>
261+
<MenuItem
262+
text={'Export schema'}
263+
onClick={() => onExportSchema()}
264+
/>
260265
</BrowserMenu>
261266
)}
262267
{onAddRow && <div className={styles.toolbarSeparator} />}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright (c) 2016-present, Parse, LLC
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the license found in the LICENSE file in
6+
* the root directory of this source tree.
7+
*/
8+
import Modal from 'components/Modal/Modal.react';
9+
import React from 'react';
10+
import Dropdown from 'components/Dropdown/Dropdown.react';
11+
import Field from 'components/Field/Field.react';
12+
import Label from 'components/Label/Label.react';
13+
import Option from 'components/Dropdown/Option.react';
14+
import Toggle from 'components/Toggle/Toggle.react';
15+
16+
export default class ExportSchemaDialog extends React.Component {
17+
constructor(props) {
18+
super();
19+
const classes = Object.keys(props.schema.toObject()).sort();
20+
classes.sort((a, b) => {
21+
if (a[0] === '_' && b[0] !== '_') {
22+
return -1;
23+
}
24+
if (b[0] === '_' && a[0] !== '_') {
25+
return 1;
26+
}
27+
return a.toUpperCase() < b.toUpperCase() ? -1 : 1;
28+
});
29+
this.state = {
30+
all: false,
31+
className: props.className,
32+
classes
33+
};
34+
}
35+
36+
37+
render() {
38+
return (
39+
<Modal
40+
type={Modal.Types.INFO}
41+
icon='down-outline'
42+
iconSize={40}
43+
title={`Export SCHEMA for ${this.state.className}`}
44+
confirmText='Export'
45+
cancelText='Cancel'
46+
onCancel={this.props.onCancel}
47+
onConfirm={() => this.props.onConfirm(this.state.className, this.state.all)}>
48+
{!this.state.all &&
49+
<Field
50+
label={<Label text='Select class' />}
51+
input={
52+
<Dropdown
53+
value={this.state.className}
54+
onChange={(className) => this.setState({ className })}>
55+
{this.state.classes.map(schema => <Option value={schema} key={schema}>{schema}</Option>)}
56+
</Dropdown>
57+
} />
58+
}
59+
<Field
60+
label={<Label text='Export all classes' />}
61+
input={<Toggle value={this.state.all} type={Toggle.Types.YES_NO} onChange={(all) => {this.setState({all})}} />} />
62+
</Modal>
63+
);
64+
}
65+
}

0 commit comments

Comments
 (0)