Skip to content
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

UI updates #24

Open
wants to merge 15 commits into
base: develop
Choose a base branch
from
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "maap-dps-jupyter-extension",
"version": "0.7.2",
"version": "0.7.4",
"description": "A JupyterLab extension for submitting and viewing jobs.",
"keywords": [
"dps",
Expand Down
8 changes: 4 additions & 4 deletions src/classes/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,18 @@ export class ViewJobsReactAppWidget extends ReactWidget {

export class SubmitJobsReactAppWidget extends ReactWidget {
data: any
constructor(data: any) {
jupyterApp: JupyterFrontEnd
constructor(data: any, jupyterApp: JupyterFrontEnd) {
super()
this.addClass(JUPYTER_EXT.EXTENSION_CSS_CLASSNAME)
this.data = data
this.jupyterApp = jupyterApp
}

render(): JSX.Element {
return (
<Provider store={store}>
{/* <div>This is the jobs submission plugin</div> */}
<JobSubmissionForm />
{/* <Registering /> */}
<JobSubmissionForm jupyterApp={this.jupyterApp} />
</Provider>
)
}
Expand Down
112 changes: 72 additions & 40 deletions src/components/JobDetailsContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import { Nav, Tab } from 'react-bootstrap'
import { Button, Tab, Tabs } from 'react-bootstrap'
import { useSelector } from 'react-redux'
import { GeneralJobInfoTable } from './GeneralJobInfoTable'
import { InputsJobInfoTable } from './InputsJobInfoTable'
Expand All @@ -8,51 +8,83 @@ import { MetricsJobInfoTable } from './MetricsJobInfoTable'
import '../../style/JobDetailsContainer.css'
import { ErrorsJobInfoTable } from './ErrorsJobInfoTable'
import { OutputsJobInfoTable } from './OutputsJobInfoTable'
import { JOB_QUEUED, JOB_STARTED } from '../constants'
import { cancelJob } from '../api/maap_py'
import { Notification } from "@jupyterlab/apputils";

export const JobDetailsContainer = ({ jupyterApp }): JSX.Element => {

// Redux
const { selectedJob } = useSelector(selectJobs)

const cancelableStatuses: string[] = [JOB_STARTED, JOB_QUEUED]

const handleCancelJob = (job_id: string) => {
cancelJob(job_id)
.then((response) => {
if (response["exception_code"] === "") {
Notification.success(response["response"], { autoClose: false });
return;
}
Notification.error(response["response"], { autoClose: false });
})
.catch((error) => {
Notification.error(error.message, { autoClose: false });
});
};

return (
<div className="job-details-container">
<h2>Job Details</h2>
<Tab.Container id="left-tabs-example" defaultActiveKey="general">
<Nav variant="pills" className="nav-menu">
<Nav.Item>
<Nav.Link eventKey="general">General</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link eventKey="inputs">Inputs</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link eventKey="outputs">Outputs</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link eventKey="errors">Errors</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link eventKey="metrics">Metrics</Nav.Link>
</Nav.Item>
</Nav>
<Tab.Content className="content-padding">
<Tab.Pane eventKey="general">
{selectedJob ? <GeneralJobInfoTable /> : <div className='subtext'>No job selected</div>}
</Tab.Pane>
<Tab.Pane eventKey="inputs">
{selectedJob ? <InputsJobInfoTable /> : <span className='subtext'>No job selected</span>}
</Tab.Pane>
<Tab.Pane eventKey="outputs">
{selectedJob ? <OutputsJobInfoTable jupyterApp={jupyterApp}/> : <span className='subtext'>No job selected</span>}
</Tab.Pane>
<Tab.Pane eventKey="errors">
{selectedJob ? <ErrorsJobInfoTable /> : <span className='subtext'>No job selected</span>}
</Tab.Pane>
<Tab.Pane eventKey="metrics">
{selectedJob ? <MetricsJobInfoTable /> : <span className='subtext'>No job selected</span>}
</Tab.Pane>
</Tab.Content>
</Tab.Container>
<div className="job-details-container">
<div className='job-details-toolbar'>
<h2>Job Details</h2>
{selectedJob && cancelableStatuses.includes(selectedJob["jobInfo"]["status"]) ? (
// TODO
marjo-luc marked this conversation as resolved.
Show resolved Hide resolved
<Button variant="outline-primary" onClick={(e) => {
handleCancelJob(selectedJob["jobInfo"]["payload_id"])
e.currentTarget.blur();
}
}>Cancel Job</Button>
) : null}
</div>
)
<Tab.Container id="left-tabs-example" defaultActiveKey="general">
<Tabs defaultActiveKey="general">
<Tab eventKey="general" title="General">
{selectedJob ? (
<GeneralJobInfoTable />
) : (
<div className="subtext mt-4">No job selected</div>
)}
</Tab>
<Tab eventKey="inputs" title="Inputs">
{selectedJob ? (
<InputsJobInfoTable />
) : (
<span className="subtext mt-4">No job selected</span>
)}
</Tab>
<Tab eventKey="outputs" title="Outputs">
{selectedJob ? (
<OutputsJobInfoTable jupyterApp={jupyterApp} />
) : (
<span className="subtext mt-4">No job selected</span>
)}
</Tab>
<Tab eventKey="errors" title="Errors">
{selectedJob ? (
<ErrorsJobInfoTable />
) : (
<span className="subtext mt-4">No job selected</span>
)}
</Tab>
<Tab eventKey="metrics" title='Metrics'>
{selectedJob ? (
<MetricsJobInfoTable />
) : (
<span className="subtext mt-4">No job selected</span>
)}
</Tab>
</Tabs>
</Tab.Container>
</div>
);
}
20 changes: 15 additions & 5 deletions src/components/JobSubmissionForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@ import { algorithmsActions, selectAlgorithms } from '../redux/slices/algorithmsS
import { parseScienceKeywords } from '../utils/ogc_parsers'
import '../../style/JobSubmission.css'
import { Notification } from "@jupyterlab/apputils"
import { selectUserInfo, userInfoActions } from '../redux/slices/userInfoSlice'
import { jobsActions } from '../redux/slices/jobsSlice'
import { parseJobData } from '../utils/mapping'
import { copyTextToClipboard } from '../utils/utils'
import { copyTextToClipboard, openViewJobs } from '../utils/utils'
import { SUBMITTING_JOB_TEXT, SUBMITTED_JOB_SUCCESS, SUBMITTED_JOB_FAIL, SUBMITTED_JOB_ELEMENT_ID } from '../constants'


export const JobSubmissionForm = () => {
export const JobSubmissionForm = ({ jupyterApp }) => {

// Redux
const dispatch = useDispatch()
Expand Down Expand Up @@ -140,7 +139,13 @@ export const JobSubmissionForm = () => {
// Submit job
submitJob(jobParams).then((data) => {
let msg = " Job submitted successfully. " + data['response'];
Notification.success(msg, { autoClose: false });
Notification.success(msg, { autoClose: false, actions: [{
label: "View Jobs",
callback: () => {
openViewJobs(jupyterApp, null);
}

}] })
setSubmittedJobText(true, data['response'], null);
setTimeout(() => {
enableSubmitButton()
Expand Down Expand Up @@ -358,9 +363,14 @@ export const JobSubmissionForm = () => {

<hr />
<ButtonToolbar>
<div style={{ display: 'flex', gap: '8px' }}>
<Button type="submit" onClick={() => setShowWaitCursor(true)}>Submit Job</Button>
<Button variant="outline-secondary" onClick={clearForm}>Clear</Button>
<Button variant="outline-primary" style={{marginLeft: 'auto'}} onClick={buildNotebookCommand}>Copy as Jupyter Notebook Code</Button>
</div>
<div style={{ marginLeft: 'auto', display: 'flex', gap: '8px' }}>
<Button variant="outline-primary" onClick={() => openViewJobs(jupyterApp, null)}>View Jobs</Button>
<Button variant="outline-primary" onClick={buildNotebookCommand}>Copy as Jupyter Notebook Code</Button>
</div>
</ButtonToolbar>
<br />
<p id={SUBMITTED_JOB_ELEMENT_ID}></p>
Expand Down
Loading