Skip to content

Commit 749e6e3

Browse files
committed
feat: add import dialog
1 parent 216438f commit 749e6e3

File tree

5 files changed

+123
-3
lines changed

5 files changed

+123
-3
lines changed

src/components/FileEditor/FileEditor.react.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export default class FileEditor extends React.Component {
8080
return (
8181
<div ref={this.inputRef} style={{ minWidth: this.props.width, display: 'none' }} className={styles.editor}>
8282
<a className={styles.upload}>
83-
<input ref={this.fileInputRef} id='fileInput' type='file' onChange={this.handleChange.bind(this)} />
83+
<input ref={this.fileInputRef} id='fileInput' type='file' onChange={this.handleChange.bind(this)} accept={this.props.accept} />
8484
<span>{file ? 'Replace file' : 'Upload file'}</span>
8585
</a>
8686
</div>

src/components/Modal/Modal.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
position: absolute;
4444
font-size: 14px;
4545
color: white;
46-
top: 52px;
46+
top: 56px;
4747
left: 28px;
4848
}
4949

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import DeleteRowsDialog from 'dashboard/Data/Browser/DeleteRow
1616
import DropClassDialog from 'dashboard/Data/Browser/DropClassDialog.react';
1717
import EmptyState from 'components/EmptyState/EmptyState.react';
1818
import ExportDialog from 'dashboard/Data/Browser/ExportDialog.react';
19+
import ImportDialog from 'dashboard/Data/Browser/ImportDialog.react';
1920
import AttachRowsDialog from 'dashboard/Data/Browser/AttachRowsDialog.react';
2021
import AttachSelectedRowsDialog from 'dashboard/Data/Browser/AttachSelectedRowsDialog.react';
2122
import CloneSelectedRowsDialog from 'dashboard/Data/Browser/CloneSelectedRowsDialog.react';
@@ -56,6 +57,7 @@ class Browser extends DashboardView {
5657
showRemoveColumnDialog: false,
5758
showDropClassDialog: false,
5859
showExportDialog: false,
60+
showImportDialog: false,
5961
showAttachRowsDialog: false,
6062
showEditRowDialog: false,
6163
showPointerKeyDialog: false,
@@ -101,6 +103,7 @@ class Browser extends DashboardView {
101103
this.showDeleteRows = this.showDeleteRows.bind(this);
102104
this.showDropClass = this.showDropClass.bind(this);
103105
this.showExport = this.showExport.bind(this);
106+
this.showImport = this.showImport.bind(this);
104107
this.login = this.login.bind(this);
105108
this.logout = this.logout.bind(this);
106109
this.toggleMasterKeyUsage = this.toggleMasterKeyUsage.bind(this);
@@ -277,6 +280,10 @@ class Browser extends DashboardView {
277280
this.setState({ showExportDialog: true });
278281
}
279282

283+
showImport() {
284+
this.setState({ showImportDialog: true });
285+
}
286+
280287
async login(username, password) {
281288
if (Parse.User.current()) {
282289
await Parse.User.logOut();
@@ -1089,6 +1096,7 @@ class Browser extends DashboardView {
10891096
this.state.showRemoveColumnDialog ||
10901097
this.state.showDropClassDialog ||
10911098
this.state.showExportDialog ||
1099+
this.state.showImportDialog ||
10921100
this.state.rowsToDelete ||
10931101
this.state.showAttachRowsDialog ||
10941102
this.state.showAttachSelectedRowsDialog ||
@@ -1539,6 +1547,7 @@ class Browser extends DashboardView {
15391547
onExport={this.showExport}
15401548
onChangeCLP={this.handleCLPChange}
15411549
onRefresh={this.refresh}
1550+
onImport={this.showImport}
15421551
onAttachRows={this.showAttachRowsDialog}
15431552
onAttachSelectedRows={this.showAttachSelectedRowsDialog}
15441553
onCloneSelectedRows={this.showCloneSelectedRowsDialog}
@@ -1659,7 +1668,15 @@ class Browser extends DashboardView {
16591668
onCancel={() => this.setState({ showExportDialog: false })}
16601669
onConfirm={() => this.exportClass(className)} />
16611670
);
1662-
} else if (this.state.showAttachRowsDialog) {
1671+
}
1672+
else if (this.state.showImportDialog) {
1673+
extras = (
1674+
<ImportDialog
1675+
className={className}
1676+
onCancel={() => this.setState({ showImportDialog: false })}
1677+
onConfirm={() => this.exportClass(className)} />
1678+
);
1679+
}else if (this.state.showAttachRowsDialog) {
16631680
extras = (
16641681
<AttachRowsDialog
16651682
relation={this.state.relation}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ let BrowserToolbar = ({
4646
onDropClass,
4747
onChangeCLP,
4848
onRefresh,
49+
onImport,
4950
onEditPermissions,
5051
hidePerms,
5152
isUnique,
@@ -260,6 +261,11 @@ let BrowserToolbar = ({
260261
</BrowserMenu>
261262
)}
262263
{onAddRow && <div className={styles.toolbarSeparator} />}
264+
<a className={classes.join(' ')} onClick={isPendingEditCloneRows ? null : onImport}>
265+
<Icon name="up-solid" width={14} height={14} />
266+
<span>Import</span>
267+
</a>
268+
<div className={styles.toolbarSeparator} />
263269
<a className={classes.join(' ')} onClick={isPendingEditCloneRows ? null : onRefresh}>
264270
<Icon name="refresh-solid" width={14} height={14} />
265271
<span>Refresh</span>
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
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 FileEditor from 'components/FileEditor/FileEditor.react';
10+
import React from 'react';
11+
import Pill from 'components/Pill/Pill.react';
12+
import getFileName from 'lib/getFileName';
13+
import { CurrentApp } from 'context/currentApp';
14+
15+
export default class ImportDialog extends React.Component {
16+
static contextType = CurrentApp;
17+
constructor() {
18+
super();
19+
this.state = {
20+
progress: undefined,
21+
file: null,
22+
showFileEditor: false
23+
};
24+
}
25+
26+
componentWillMount() {
27+
this.context.getExportProgress().then((progress) => {
28+
this.setState({ progress });
29+
});
30+
}
31+
32+
inProgress() {
33+
if (this.state.progress === undefined) {
34+
return false;
35+
}
36+
let found = false;
37+
if (Array.isArray(this.state.progress)) {
38+
this.state.progress.forEach((obj) => {
39+
if (obj.id === this.props.className) {
40+
found = true;
41+
}
42+
});
43+
}
44+
return found;
45+
}
46+
47+
openFileEditor() {
48+
this.setState({
49+
showFileEditor: true
50+
});
51+
}
52+
53+
hideFileEditor(file) {
54+
this.setState({
55+
showFileEditor: false,
56+
file
57+
});
58+
}
59+
60+
render() {
61+
let inProgress = this.inProgress();
62+
return (
63+
<div>
64+
<Modal
65+
type={Modal.Types.INFO}
66+
icon='up-outline'
67+
iconSize={40}
68+
title={`Import Data into ${this.props.className}`}
69+
subtitle='Note: If rows have a className, they will be imported into that class.'
70+
confirmText='Import'
71+
cancelText='Cancel'
72+
disabled={!this.state.file}
73+
buttonsInCenter={true}
74+
onCancel={this.props.onCancel}
75+
onConfirm={this.props.onConfirm}>
76+
<div style={{ padding: '25px' }}>
77+
{this.state.file && <Pill value={getFileName(this.state.file) }/>}
78+
<div style={{ cursor: 'pointer' }}>
79+
<Pill
80+
value={this.state.file ? 'Change file' : 'Select file'}
81+
onClick={() => this.openFileEditor()}
82+
/>
83+
{this.state.showFileEditor && (
84+
<FileEditor
85+
value={this.state.file}
86+
accept='.json,.csv'
87+
onCommit={(file) => this.hideFileEditor(file)}
88+
onCancel={() => this.hideFileEditor()}
89+
/>
90+
)}
91+
</div>
92+
</div>
93+
</Modal>
94+
</div>
95+
);
96+
}
97+
}

0 commit comments

Comments
 (0)