Skip to content

Adds support for viewing parse-server based jobs #514

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 7, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"parseDashboardFeatures": [
"Data Browser",
"Cloud Code Viewer",
"Cloud Code Jobs Viewer and Runner",
"Parse Config",
"API Console",
"Class Level Permissions Editor",
Expand Down
2 changes: 1 addition & 1 deletion src/dashboard/Dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ class Dashboard extends React.Component {
<Route path='cloud_code' component={CloudCode} />
<Route path='cloud_code/*' component={CloudCode} />
<Route path='webhooks' component={Webhooks} />
<Redirect from='jobs' to='/apps/:appId/jobs/scheduled' />
<Redirect from='jobs' to='/apps/:appId/jobs/all' />
<Route path='jobs' component={JobsData}>
<Route path='new' component={JobEdit} />
<Route path='edit/:jobId' component={JobEdit} />
Expand Down
5 changes: 2 additions & 3 deletions src/dashboard/DashboardView.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,13 @@ export default class DashboardView extends React.Component {
}
*/

/* Jobs not supported
if (...) {
if (features.cloudCode && features.cloudCode.jobs) {
coreSubsections.push({
name: 'Jobs',
link: '/jobs'
});
}
*/

if (features.logs && Object.keys(features.logs).some(key => features.logs[key])) {
coreSubsections.push({
name: 'Logs',
Expand Down
68 changes: 55 additions & 13 deletions src/dashboard/Data/Jobs/Jobs.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ import RunNowButton from 'dashboard/Data/Jobs/RunNowButton.react';
import SidebarAction from 'components/Sidebar/SidebarAction';
import StatusIndicator from 'components/StatusIndicator/StatusIndicator.react';
import styles from 'dashboard/Data/Jobs/Jobs.scss';
import browserStyles from 'dashboard/Data/Browser/Browser.scss';
import subscribeTo from 'lib/subscribeTo';
import TableHeader from 'components/Table/TableHeader.react';
import TableView from 'dashboard/TableView.react';
import Toolbar from 'components/Toolbar/Toolbar.react';

let subsections = {
scheduled: 'Scheduled Jobs',
all: 'All Jobs',
/*scheduled: 'Scheduled Jobs',*/
status: 'Job Status'
};

Expand Down Expand Up @@ -73,12 +75,7 @@ export default class Jobs extends TableView {
}

componentWillMount() {
this.props.jobs.dispatch(ActionTypes.FETCH).always(() => {
this.setState({ loading: false });
});
this.context.currentApp.getJobStatus().then((status) => {
this.setState({ jobStatus: status });
});
this.loadData();
}

componentWillReceiveProps(nextProps) {
Expand All @@ -89,6 +86,7 @@ export default class Jobs extends TableView {
}
}
this.action = null;
this.loadData();
}

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

loadData() {
this.props.jobs.dispatch(ActionTypes.FETCH).always(() => {
this.setState({ loading: false });
});
this.context.currentApp.getJobStatus().then((status) => {
this.setState({ jobStatus: status });
});
}

renderSidebar() {
let current = this.props.params.section || '';
return (
<CategoryList current={current} linkPrefix={'jobs/'} categories={[
{ name: 'Scheduled Jobs', id: 'scheduled' },
/* { name: 'Scheduled Jobs', id: 'scheduled' }, */
{ name: 'All Jobs', id: 'all' },
{ name: 'Job Status', id: 'status' }
]} />
);
}

renderRow(data) {
if (this.props.params.section === 'scheduled') {
if (this.props.params.section === 'all') {
return (
<tr key={data.objectId}>
<td style={{width: '60%'}}>{data.jobName}</td>
<td className={styles.buttonCell}>
<RunNowButton job={data} width={'100px'} />
</td>
</tr>
);
} else if (this.props.params.section === 'scheduled') {
return (
<tr key={data.objectId}>
<td style={{width: '20%'}}>{data.description}</td>
Expand Down Expand Up @@ -142,7 +159,12 @@ export default class Jobs extends TableView {
}

renderHeaders() {
if (this.props.params.section === 'scheduled') {
if (this.props.params.section === 'all') {
return [
<TableHeader key='name' width={60}>Name</TableHeader>,
<TableHeader key='actions' width={40}>Actions</TableHeader>,
];
} else if (this.props.params.section === 'scheduled') {
return [
<TableHeader key='name' width={20}>Name</TableHeader>,
<TableHeader key='func' width={20}>Function</TableHeader>,
Expand All @@ -160,11 +182,18 @@ export default class Jobs extends TableView {
}

renderEmpty() {
if (this.props.params.section === 'scheduled') {
if (this.props.params.section === 'all') {
return (
<EmptyState
title='Cloud Jobs'
description='Schedule your Cloud Code functions to run at specific times.'
description='Define Jobs on parse-server with Parse.Cloud.job()'
icon='cloud-happy' />
);
} else if (this.props.params.section === 'scheduled') {
return (
<EmptyState
title='Cloud Jobs'
description='Scheduling jobs is not supported on parse-server'
icon='cloud-happy' />
);
} else {
Expand Down Expand Up @@ -197,7 +226,7 @@ export default class Jobs extends TableView {

tableData() {
let data = undefined;
if (this.props.params.section === 'scheduled') {
if (this.props.params.section === 'scheduled' || this.props.params.section === 'all' ) {
if (this.props.jobs.data) {
let jobs = this.props.jobs.data.get('jobs');
if (jobs) {
Expand All @@ -210,13 +239,26 @@ export default class Jobs extends TableView {
return data;
}

onRefresh() {
this.setState({
toDelete: null,
jobStatus: undefined,
loading: true,
});
this.loadData();
}

renderToolbar() {
if (subsections[this.props.params.section]) {
return (
<Toolbar
section='Jobs'
subsection={subsections[this.props.params.section]}
details={ReleaseInfo({ release: this.props.release })}>
<a className={browserStyles.toolbarButton} onClick={this.onRefresh.bind(this)}>
<Icon name='refresh-solid' width={14} height={14} />
<span>Refresh</span>
</a>
{this.props.availableJobs && this.props.availableJobs.length > 0 ?
<Button color='white' value='Schedule a job' onClick={this.navigateToNew.bind(this)} /> : null}
</Toolbar>
Expand Down
14 changes: 7 additions & 7 deletions src/lib/ParseApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -507,21 +507,21 @@ export default class ParseApp {

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

getJobStatus() {
// Cache it for a minute
if (new Date() - this.jobStatus.lastFetched < 60000) {
return Parse.Promise.as(this.jobStatus.status);
}
let path = '/apps/' + this.slug + '/cloud_code/job_status/all';
return AJAX.get(path).then((status) => {
let query = new Parse.Query('_JobStatus');
query.descending('createdAt');
return query.find({ useMasterKey: true }).then((status) => {
this.jobStatus = {
status: status || null,
lastFetched: new Date()
};
return status;
return status.map((jobStatus) => {
return jobStatus.toJSON();
});
});
}

Expand Down
4 changes: 2 additions & 2 deletions src/lib/stores/JobsStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ function JobsStore(state, action) {
if (state && new Date() - state.get('lastFetch') < 60000) {
return Parse.Promise.as(state);
}
path = `/apps/${action.app.slug}/cloud_code/jobs?per_page=50`;
return AJAX.get(path).then((results) => {
path = `cloud_code/jobs?per_page=50`;
return Parse._request('GET', path).then((results) => {
return Map({ lastFetch: new Date(), jobs: List(results) });
});
case ActionTypes.CREATE:
Expand Down