Skip to content

Commit ecf572b

Browse files
flovilmartdrew-gross
authored andcommitted
Adds support for viewing parse-server based jobs (#514)
* Adds support for parse-server based jobs - Removes the scheduled endpoint (we don't schedule on parse-server) - Adds /all endpoint with just run method - Supports _JobStatus query * Adds info about the features
1 parent b88705c commit ecf572b

File tree

6 files changed

+68
-26
lines changed

6 files changed

+68
-26
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"parseDashboardFeatures": [
44
"Data Browser",
55
"Cloud Code Viewer",
6+
"Cloud Code Jobs Viewer and Runner",
67
"Parse Config",
78
"API Console",
89
"Class Level Permissions Editor",

src/dashboard/Dashboard.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ class Dashboard extends React.Component {
217217
<Route path='cloud_code' component={CloudCode} />
218218
<Route path='cloud_code/*' component={CloudCode} />
219219
<Route path='webhooks' component={Webhooks} />
220-
<Redirect from='jobs' to='/apps/:appId/jobs/scheduled' />
220+
<Redirect from='jobs' to='/apps/:appId/jobs/all' />
221221
<Route path='jobs' component={JobsData}>
222222
<Route path='new' component={JobEdit} />
223223
<Route path='edit/:jobId' component={JobEdit} />

src/dashboard/DashboardView.react.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,13 @@ export default class DashboardView extends React.Component {
5656
}
5757
*/
5858

59-
/* Jobs not supported
60-
if (...) {
59+
if (features.cloudCode && features.cloudCode.jobs) {
6160
coreSubsections.push({
6261
name: 'Jobs',
6362
link: '/jobs'
6463
});
6564
}
66-
*/
65+
6766
if (features.logs && Object.keys(features.logs).some(key => features.logs[key])) {
6867
coreSubsections.push({
6968
name: 'Logs',

src/dashboard/Data/Jobs/Jobs.react.js

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@ import RunNowButton from 'dashboard/Data/Jobs/RunNowButton.react';
2020
import SidebarAction from 'components/Sidebar/SidebarAction';
2121
import StatusIndicator from 'components/StatusIndicator/StatusIndicator.react';
2222
import styles from 'dashboard/Data/Jobs/Jobs.scss';
23+
import browserStyles from 'dashboard/Data/Browser/Browser.scss';
2324
import subscribeTo from 'lib/subscribeTo';
2425
import TableHeader from 'components/Table/TableHeader.react';
2526
import TableView from 'dashboard/TableView.react';
2627
import Toolbar from 'components/Toolbar/Toolbar.react';
2728

2829
let subsections = {
29-
scheduled: 'Scheduled Jobs',
30+
all: 'All Jobs',
31+
/*scheduled: 'Scheduled Jobs',*/
3032
status: 'Job Status'
3133
};
3234

@@ -73,12 +75,7 @@ export default class Jobs extends TableView {
7375
}
7476

7577
componentWillMount() {
76-
this.props.jobs.dispatch(ActionTypes.FETCH).always(() => {
77-
this.setState({ loading: false });
78-
});
79-
this.context.currentApp.getJobStatus().then((status) => {
80-
this.setState({ jobStatus: status });
81-
});
78+
this.loadData();
8279
}
8380

8481
componentWillReceiveProps(nextProps) {
@@ -89,6 +86,7 @@ export default class Jobs extends TableView {
8986
}
9087
}
9188
this.action = null;
89+
this.loadData();
9290
}
9391

9492
navigateToNew() {
@@ -99,18 +97,37 @@ export default class Jobs extends TableView {
9997
history.push(this.context.generatePath(`jobs/edit/${jobId}`))
10098
}
10199

100+
loadData() {
101+
this.props.jobs.dispatch(ActionTypes.FETCH).always(() => {
102+
this.setState({ loading: false });
103+
});
104+
this.context.currentApp.getJobStatus().then((status) => {
105+
this.setState({ jobStatus: status });
106+
});
107+
}
108+
102109
renderSidebar() {
103110
let current = this.props.params.section || '';
104111
return (
105112
<CategoryList current={current} linkPrefix={'jobs/'} categories={[
106-
{ name: 'Scheduled Jobs', id: 'scheduled' },
113+
/* { name: 'Scheduled Jobs', id: 'scheduled' }, */
114+
{ name: 'All Jobs', id: 'all' },
107115
{ name: 'Job Status', id: 'status' }
108116
]} />
109117
);
110118
}
111119

112120
renderRow(data) {
113-
if (this.props.params.section === 'scheduled') {
121+
if (this.props.params.section === 'all') {
122+
return (
123+
<tr key={data.objectId}>
124+
<td style={{width: '60%'}}>{data.jobName}</td>
125+
<td className={styles.buttonCell}>
126+
<RunNowButton job={data} width={'100px'} />
127+
</td>
128+
</tr>
129+
);
130+
} else if (this.props.params.section === 'scheduled') {
114131
return (
115132
<tr key={data.objectId}>
116133
<td style={{width: '20%'}}>{data.description}</td>
@@ -142,7 +159,12 @@ export default class Jobs extends TableView {
142159
}
143160

144161
renderHeaders() {
145-
if (this.props.params.section === 'scheduled') {
162+
if (this.props.params.section === 'all') {
163+
return [
164+
<TableHeader key='name' width={60}>Name</TableHeader>,
165+
<TableHeader key='actions' width={40}>Actions</TableHeader>,
166+
];
167+
} else if (this.props.params.section === 'scheduled') {
146168
return [
147169
<TableHeader key='name' width={20}>Name</TableHeader>,
148170
<TableHeader key='func' width={20}>Function</TableHeader>,
@@ -160,11 +182,18 @@ export default class Jobs extends TableView {
160182
}
161183

162184
renderEmpty() {
163-
if (this.props.params.section === 'scheduled') {
185+
if (this.props.params.section === 'all') {
164186
return (
165187
<EmptyState
166188
title='Cloud Jobs'
167-
description='Schedule your Cloud Code functions to run at specific times.'
189+
description='Define Jobs on parse-server with Parse.Cloud.job()'
190+
icon='cloud-happy' />
191+
);
192+
} else if (this.props.params.section === 'scheduled') {
193+
return (
194+
<EmptyState
195+
title='Cloud Jobs'
196+
description='Scheduling jobs is not supported on parse-server'
168197
icon='cloud-happy' />
169198
);
170199
} else {
@@ -197,7 +226,7 @@ export default class Jobs extends TableView {
197226

198227
tableData() {
199228
let data = undefined;
200-
if (this.props.params.section === 'scheduled') {
229+
if (this.props.params.section === 'scheduled' || this.props.params.section === 'all' ) {
201230
if (this.props.jobs.data) {
202231
let jobs = this.props.jobs.data.get('jobs');
203232
if (jobs) {
@@ -210,13 +239,26 @@ export default class Jobs extends TableView {
210239
return data;
211240
}
212241

242+
onRefresh() {
243+
this.setState({
244+
toDelete: null,
245+
jobStatus: undefined,
246+
loading: true,
247+
});
248+
this.loadData();
249+
}
250+
213251
renderToolbar() {
214252
if (subsections[this.props.params.section]) {
215253
return (
216254
<Toolbar
217255
section='Jobs'
218256
subsection={subsections[this.props.params.section]}
219257
details={ReleaseInfo({ release: this.props.release })}>
258+
<a className={browserStyles.toolbarButton} onClick={this.onRefresh.bind(this)}>
259+
<Icon name='refresh-solid' width={14} height={14} />
260+
<span>Refresh</span>
261+
</a>
220262
{this.props.availableJobs && this.props.availableJobs.length > 0 ?
221263
<Button color='white' value='Schedule a job' onClick={this.navigateToNew.bind(this)} /> : null}
222264
</Toolbar>

src/lib/ParseApp.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -507,21 +507,21 @@ export default class ParseApp {
507507

508508
getAvailableJobs() {
509509
let path = '/apps/' + this.slug + '/cloud_code/jobs/data';
510-
return AJAX.get(path);
510+
return Parse._request('GET', path);
511511
}
512512

513513
getJobStatus() {
514514
// Cache it for a minute
515-
if (new Date() - this.jobStatus.lastFetched < 60000) {
516-
return Parse.Promise.as(this.jobStatus.status);
517-
}
518-
let path = '/apps/' + this.slug + '/cloud_code/job_status/all';
519-
return AJAX.get(path).then((status) => {
515+
let query = new Parse.Query('_JobStatus');
516+
query.descending('createdAt');
517+
return query.find({ useMasterKey: true }).then((status) => {
520518
this.jobStatus = {
521519
status: status || null,
522520
lastFetched: new Date()
523521
};
524-
return status;
522+
return status.map((jobStatus) => {
523+
return jobStatus.toJSON();
524+
});
525525
});
526526
}
527527

src/lib/stores/JobsStore.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ function JobsStore(state, action) {
2929
if (state && new Date() - state.get('lastFetch') < 60000) {
3030
return Parse.Promise.as(state);
3131
}
32-
path = `/apps/${action.app.slug}/cloud_code/jobs?per_page=50`;
33-
return AJAX.get(path).then((results) => {
32+
path = `cloud_code/jobs?per_page=50`;
33+
return Parse._request('GET', path).then((results) => {
3434
return Map({ lastFetch: new Date(), jobs: List(results) });
3535
});
3636
case ActionTypes.CREATE:

0 commit comments

Comments
 (0)