Skip to content

Commit 5e7538c

Browse files
committed
2 parents 206b3f1 + 2a5c050 commit 5e7538c

File tree

4 files changed

+62
-25
lines changed

4 files changed

+62
-25
lines changed

src/components/SaveButton/SaveButton.example.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ export const demos = [
5555
<div style={{padding: 10}}>
5656
<SaveButton state={SaveButton.States.FAILED} />
5757
</div>
58+
<div style={{padding: 10}}>
59+
<SaveButton state={SaveButton.States.WAITING} />
60+
</div>
5861
</div>
5962
)
6063
}, {

src/components/SaveButton/SaveButton.react.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ let SaveButton = ({
5252
</span>;
5353
};
5454

55-
SaveButton.States = keyMirror(['SAVING', 'SUCCEEDED', 'FAILED']);
55+
SaveButton.States = keyMirror(['SAVING', 'SUCCEEDED', 'FAILED', 'WAITING']);
5656

5757
let {...forwardedButtonProps} = Button.propTypes;
5858
delete forwardedButtonProps.value;

src/dashboard/Data/CloudCode/CloudCode.react.js

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,19 @@
55
* This source code is licensed under the license found in the LICENSE file in
66
* the root directory of this source tree.
77
*/
8-
import CodeSnippet from 'components/CodeSnippet/CodeSnippet.react';
8+
import CodeEditor from 'components/CodeEditor/CodeEditor.react';
99
import DashboardView from 'dashboard/DashboardView.react';
1010
import EmptyState from 'components/EmptyState/EmptyState.react';
1111
import FileTree from 'components/FileTree/FileTree.react';
1212
import history from 'dashboard/history';
1313
import React from 'react';
1414
import styles from 'dashboard/Data/CloudCode/CloudCode.scss';
1515
import Toolbar from 'components/Toolbar/Toolbar.react';
16+
import SaveButton from 'components/SaveButton/SaveButton.react';
1617

1718
function getPath(params) {
18-
return params.splat;
19+
const last = params.location.pathname.split('cloud_code/')[1]
20+
return last;
1921
}
2022

2123
export default class CloudCode extends DashboardView {
@@ -26,17 +28,19 @@ export default class CloudCode extends DashboardView {
2628

2729
this.state = {
2830
files: undefined,
29-
source: undefined
31+
source: undefined,
32+
saveState: SaveButton.States.WAITING,
33+
saveError: '',
3034
};
3135
}
3236

3337
componentWillMount() {
34-
this.fetchSource(this.context.currentApp, getPath(this.props.params));
38+
this.fetchSource(this.context.currentApp, getPath(this.props));
3539
}
3640

3741
componentWillReceiveProps(nextProps, nextContext) {
3842
if (this.context !== nextContext) {
39-
this.fetchSource(nextContext.currentApp, getPath(nextProps.params));
43+
this.fetchSource(nextContext.currentApp, getPath(nextProps));
4044
}
4145
}
4246

@@ -52,11 +56,17 @@ export default class CloudCode extends DashboardView {
5256

5357
if (!fileName || release.files[fileName] === undefined) {
5458
// Means we're still in /cloud_code/. Let's redirect to /cloud_code/main.js
55-
history.replace(this.context.generatePath('cloud_code/main.js'))
59+
history.replace(this.context.generatePath(`cloud_code/${Object.keys(release.files)[0]}`))
5660
} else {
5761
// Means we can load /cloud_code/<fileName>
62+
this.setState({ source: undefined })
5863
app.getSource(fileName).then(
59-
(source) => this.setState({ source: source }),
64+
(source) => {
65+
this.setState({ source: source })
66+
if (this.editor) {
67+
this.editor.value = source;
68+
}
69+
},
6070
() => this.setState({ source: undefined })
6171
);
6272
}
@@ -66,7 +76,7 @@ export default class CloudCode extends DashboardView {
6676
}
6777

6878
renderSidebar() {
69-
let current = getPath(this.props.params) || '';
79+
let current = getPath(this.props) || '';
7080
let files = this.state.files;
7181
if (!files) {
7282
return null;
@@ -86,11 +96,27 @@ export default class CloudCode extends DashboardView {
8696
</div>
8797
);
8898
}
89-
99+
async getCode() {
100+
if (!this.editor) {
101+
return;
102+
}
103+
this.setState({ saveState: SaveButton.States.SAVING });
104+
let fileName = getPath(this.props);
105+
try {
106+
await this.context.currentApp.saveSource(fileName,this.editor.value);
107+
this.setState({ saveState: SaveButton.States.SUCCEEDED });
108+
setTimeout(()=> {
109+
this.setState({ saveState: SaveButton.States.WAITING });
110+
},2000);
111+
} catch (e) {
112+
this.setState({ saveState: SaveButton.States.FAILED });
113+
this.setState({ saveError: e.message || e });
114+
}
115+
}
90116
renderContent() {
91117
let toolbar = null;
92118
let content = null;
93-
let fileName = getPath(this.props.params);
119+
let fileName = getPath(this.props);
94120

95121
if (!this.state.files || Object.keys(this.state.files).length === 0) {
96122
content = (
@@ -110,10 +136,20 @@ export default class CloudCode extends DashboardView {
110136
subsection={fileName} />;
111137

112138
let source = this.state.files[fileName];
113-
if (source && source.source) {
139+
if ((source && source.source) || this.state.source) {
114140
content = (
115141
<div className={styles.content}>
116-
<CodeSnippet source={source.source} language='javascript' />
142+
<CodeEditor
143+
placeHolder={this.state.source || source.source}
144+
ref={editor => (this.editor = editor)}
145+
fontSize={'14px'}
146+
/>
147+
<SaveButton
148+
state={this.state.saveState}
149+
waitingText={this.state.submitText}
150+
savingText={this.state.inProgressText}
151+
failedText={this.state.saveError}
152+
onClick={() => this.getCode(this)}></SaveButton>
117153
</div>
118154
);
119155
}

src/lib/ParseApp.js

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,15 @@ export default class ParseApp {
119119
return this.apiRequest('GET', path, {}, { useMasterKey: true });
120120
}
121121

122+
/**
123+
* Saves source of a Cloud Code hosted file from api.parse.com
124+
* fileName - the name of the file to be fetched
125+
* data - the text to save to the cloud file
126+
*/
127+
saveSource(fileName,data) {
128+
return this.apiRequest('POST', `scripts/${fileName}`, {data}, { useMasterKey: true });
129+
}
130+
122131
/**
123132
* Fetches source of a Cloud Code hosted file from api.parse.com
124133
* fileName - the name of the file to be fetched
@@ -129,22 +138,11 @@ export default class ParseApp {
129138
// No release yet
130139
return Promise.resolve(null);
131140
}
132-
133-
let fileMetaData = release.files[fileName];
134-
if (fileMetaData && fileMetaData.source) {
135-
return Promise.resolve(fileMetaData.source);
136-
}
137-
138-
let params = {
139-
version: fileMetaData.version,
140-
checksum: fileMetaData.checksum
141-
}
142-
return this.apiRequest('GET', `scripts/${fileName}`, params, { useMasterKey: true });
141+
return this.apiRequest('GET', `scripts/${fileName}`, {}, { useMasterKey: true });
143142
}).then((source) => {
144143
if (this.latestRelease.files) {
145144
this.latestRelease.files[fileName].source = source;
146145
}
147-
148146
return Promise.resolve(source);
149147
});
150148
}

0 commit comments

Comments
 (0)