From b601dd534f3852bd9c9bc3010a6abb8627c2f8cf Mon Sep 17 00:00:00 2001 From: dblythy Date: Fri, 20 Jan 2023 13:52:53 +1100 Subject: [PATCH 1/3] feat: allow export of schema --- src/dashboard/Data/Browser/Browser.react.js | 53 ++++++++++++++- .../Data/Browser/BrowserToolbar.react.js | 5 ++ .../Data/Browser/ExportSchemaDialog.react.js | 65 +++++++++++++++++++ 3 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 src/dashboard/Data/Browser/ExportSchemaDialog.react.js diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js index 8e35357351..d2c8d94e40 100644 --- a/src/dashboard/Data/Browser/Browser.react.js +++ b/src/dashboard/Data/Browser/Browser.react.js @@ -21,6 +21,7 @@ import AttachSelectedRowsDialog from 'dashboard/Data/Browser/AttachSel import CloneSelectedRowsDialog from 'dashboard/Data/Browser/CloneSelectedRowsDialog.react'; import EditRowDialog from 'dashboard/Data/Browser/EditRowDialog.react'; import ExportSelectedRowsDialog from 'dashboard/Data/Browser/ExportSelectedRowsDialog.react'; +import ExportSchemaDialog from 'dashboard/Data/Browser/ExportSchemaDialog.react'; import { List, Map } from 'immutable'; import Notification from 'dashboard/Data/Browser/Notification.react'; import Parse from 'parse'; @@ -56,6 +57,7 @@ class Browser extends DashboardView { showRemoveColumnDialog: false, showDropClassDialog: false, showExportDialog: false, + showExportSchemaDialog: false, showAttachRowsDialog: false, showEditRowDialog: false, showPointerKeyDialog: false, @@ -88,7 +90,7 @@ class Browser extends DashboardView { requiredColumnFields: [], useMasterKey: true, - currentUser: Parse.User.current() + currentUser: Parse.User.current(), }; this.prefetchData = this.prefetchData.bind(this); @@ -114,6 +116,7 @@ class Browser extends DashboardView { this.confirmCloneSelectedRows = this.confirmCloneSelectedRows.bind(this); this.cancelCloneSelectedRows = this.cancelCloneSelectedRows.bind(this); this.showExportSelectedRowsDialog = this.showExportSelectedRowsDialog.bind(this); + this.showExportSchemaDialog = this.showExportSchemaDialog.bind(this); this.confirmExportSelectedRows = this.confirmExportSelectedRows.bind(this); this.cancelExportSelectedRows = this.cancelExportSelectedRows.bind(this); this.getClassRelationColumns = this.getClassRelationColumns.bind(this); @@ -326,6 +329,38 @@ class Browser extends DashboardView { }); } + async exportSchema(className, all) { + try { + this.showNote('Exporting schema...'); + this.setState({ showExportSchemaDialog: false }); + let schema = []; + if (all) { + schema = await Parse.Schema.all(); + } else { + schema = await new Parse.Schema(className).get(); + } + const element = document.createElement('a'); + const file = new Blob( + [ + JSON.stringify( + schema, + null, + 2, + ), + ], + { type: 'application/json' } + ); + element.href = URL.createObjectURL(file); + element.download = `${all ? 'schema' : className}.json`; + document.body.appendChild(element); // Required for this to work in FireFox + element.click(); + document.body.removeChild(element); + } catch (msg) { + this.showNote(msg, true); + } + + } + newColumn(payload, required) { return this.props.schema.dispatch(ActionTypes.ADD_COLUMN, payload) .then(() => { @@ -1089,6 +1124,7 @@ class Browser extends DashboardView { this.state.showRemoveColumnDialog || this.state.showDropClassDialog || this.state.showExportDialog || + this.state.showExportSchema || this.state.rowsToDelete || this.state.showAttachRowsDialog || this.state.showAttachSelectedRowsDialog || @@ -1249,6 +1285,12 @@ class Browser extends DashboardView { }); } + showExportSchemaDialog() { + this.setState({ + showExportSchemaDialog: true + }) + } + cancelExportSelectedRows() { this.setState({ rowsToExport: null @@ -1545,6 +1587,7 @@ class Browser extends DashboardView { onEditSelectedRow={this.showEditRowDialog} onEditPermissions={this.onDialogToggle} onExportSelectedRows={this.showExportSelectedRowsDialog} + onExportSchema={this.showExportSchemaDialog} onSaveNewRow={this.saveNewRow} onShowPointerKey={this.showPointerKeyDialog} @@ -1659,6 +1702,14 @@ class Browser extends DashboardView { onCancel={() => this.setState({ showExportDialog: false })} onConfirm={() => this.exportClass(className)} /> ); + } else if (this.state.showExportSchemaDialog) { + extras = ( + this.setState({ showExportSchemaDialog: false })} + onConfirm={(...args) => this.exportSchema(...args)} /> + ); } else if (this.state.showAttachRowsDialog) { extras = ( onExportSelectedRows({ '*': true })} /> + onExportSchema()} + /> )} {onAddRow &&
} diff --git a/src/dashboard/Data/Browser/ExportSchemaDialog.react.js b/src/dashboard/Data/Browser/ExportSchemaDialog.react.js new file mode 100644 index 0000000000..dc8c9448b0 --- /dev/null +++ b/src/dashboard/Data/Browser/ExportSchemaDialog.react.js @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2016-present, Parse, LLC + * All rights reserved. + * + * This source code is licensed under the license found in the LICENSE file in + * the root directory of this source tree. + */ +import Modal from 'components/Modal/Modal.react'; +import React from 'react'; +import Dropdown from 'components/Dropdown/Dropdown.react'; +import Field from 'components/Field/Field.react'; +import Label from 'components/Label/Label.react'; +import Option from 'components/Dropdown/Option.react'; +import Toggle from 'components/Toggle/Toggle.react'; + +export default class ExportSchemaDialog extends React.Component { + constructor(props) { + super(); + const classes = Object.keys(props.schema.toObject()).sort(); + classes.sort((a, b) => { + if (a[0] === '_' && b[0] !== '_') { + return -1; + } + if (b[0] === '_' && a[0] !== '_') { + return 1; + } + return a.toUpperCase() < b.toUpperCase() ? -1 : 1; + }); + this.state = { + all: false, + className: props.className, + classes + }; + } + + + render() { + return ( + this.props.onConfirm(this.state.className, this.state.all)}> + {!this.state.all && + } + input={ + this.setState({ className })}> + {this.state.classes.map(schema => )} + + } /> + } + } + input={ {this.setState({all})}} />} /> + + ); + } +} From 1cd67b4e05bbc8edd7782069f7169647780023d9 Mon Sep 17 00:00:00 2001 From: dblythy Date: Fri, 20 Jan 2023 13:56:11 +1100 Subject: [PATCH 2/3] indent --- src/dashboard/Data/Browser/Browser.react.js | 49 +++++++++---------- .../Data/Browser/ExportSchemaDialog.react.js | 18 +++---- 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js index d2c8d94e40..9861b363d2 100644 --- a/src/dashboard/Data/Browser/Browser.react.js +++ b/src/dashboard/Data/Browser/Browser.react.js @@ -333,32 +333,31 @@ class Browser extends DashboardView { try { this.showNote('Exporting schema...'); this.setState({ showExportSchemaDialog: false }); - let schema = []; - if (all) { - schema = await Parse.Schema.all(); - } else { - schema = await new Parse.Schema(className).get(); + let schema = []; + if (all) { + schema = await Parse.Schema.all(); + } else { + schema = await new Parse.Schema(className).get(); + } + const element = document.createElement('a'); + const file = new Blob( + [ + JSON.stringify( + schema, + null, + 2, + ), + ], + { type: 'application/json' } + ); + element.href = URL.createObjectURL(file); + element.download = `${all ? 'schema' : className}.json`; + document.body.appendChild(element); // Required for this to work in FireFox + element.click(); + document.body.removeChild(element); + } catch (msg) { + this.showNote(msg, true); } - const element = document.createElement('a'); - const file = new Blob( - [ - JSON.stringify( - schema, - null, - 2, - ), - ], - { type: 'application/json' } - ); - element.href = URL.createObjectURL(file); - element.download = `${all ? 'schema' : className}.json`; - document.body.appendChild(element); // Required for this to work in FireFox - element.click(); - document.body.removeChild(element); - } catch (msg) { - this.showNote(msg, true); - } - } newColumn(payload, required) { diff --git a/src/dashboard/Data/Browser/ExportSchemaDialog.react.js b/src/dashboard/Data/Browser/ExportSchemaDialog.react.js index dc8c9448b0..0f2d7d84c2 100644 --- a/src/dashboard/Data/Browser/ExportSchemaDialog.react.js +++ b/src/dashboard/Data/Browser/ExportSchemaDialog.react.js @@ -45,16 +45,16 @@ export default class ExportSchemaDialog extends React.Component { cancelText='Cancel' onCancel={this.props.onCancel} onConfirm={() => this.props.onConfirm(this.state.className, this.state.all)}> - {!this.state.all && - } - input={ - this.setState({ className })}> + {!this.state.all && + } + input={ + this.setState({ className })}> {this.state.classes.map(schema => )} - - } /> + + } /> } } From 7bfea2eff754bbbacc226cb87cb17efac0d92b15 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 21 Jan 2023 07:03:56 +1100 Subject: [PATCH 3/3] Update src/dashboard/Data/Browser/BrowserToolbar.react.js Co-authored-by: Manuel <5673677+mtrezza@users.noreply.github.com> --- src/dashboard/Data/Browser/BrowserToolbar.react.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dashboard/Data/Browser/BrowserToolbar.react.js b/src/dashboard/Data/Browser/BrowserToolbar.react.js index e9d50599ba..5076c9a141 100644 --- a/src/dashboard/Data/Browser/BrowserToolbar.react.js +++ b/src/dashboard/Data/Browser/BrowserToolbar.react.js @@ -259,7 +259,7 @@ let BrowserToolbar = ({ onClick={() => onExportSelectedRows({ '*': true })} /> onExportSchema()} />