Skip to content
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
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { FC, useState } from 'react';
import styled from 'styled-components';
import { Typography } from '@mui/material';

import { Container } from 'src/graphql/typings';

Expand All @@ -15,7 +14,7 @@ export const SessionManagement: FC = ({ }) => {
const [containerSelected, setContainerSelected] = useState<Container | null>(null);

return <Styled>
<Typography variant="h3">Compute Sessions</Typography>
<h1>Compute Sessions</h1>
{containerSelected ?
<ContainerDetail row={containerSelected} back={() => setContainerSelected(null)} />
:
Expand Down
88 changes: 65 additions & 23 deletions components/ui/web/components/content/jobs/detail/jobFullDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { FC, useMemo, useState } from 'react';
import { useRouter } from 'next/router';
import { useQuery } from '@apollo/client';
import { useMutation, useQuery } from '@apollo/client';
import styled from 'styled-components';

import { IconButton, Snackbar, Typography } from '@mui/material';
import { IconButton, Snackbar, Tooltip } from '@mui/material';
import {
ArrowBackIos as ArrowBackIcon,
ContentCopy as ContentCopyIcon,
Close as CloseIcon,
Download as DownloadIcon
Download as DownloadIcon,
Replay as ReplayIcon
} from '@mui/icons-material';
import { DataGrid, GridActionsCellItem, GridColDef } from '@mui/x-data-grid';

Expand All @@ -17,11 +18,12 @@ import ReactMarkdown from 'react-markdown';
import rehypeRaw from 'rehype-raw';
import { filesize } from 'filesize';

import { File, JobDetails } from 'src/graphql/typings';
import { JOB_DETAIL_VIEW } from 'src/graphql/jobs';
import { File, Job, JobDetails } from 'src/graphql/typings';
import { CREATE_JOB, JOB_DETAIL_VIEW } from 'src/graphql/jobs';

import { CustomizedTabs } from 'components/common/tabs';
import { LoadingAnimation } from 'components/common/loadingAnimation';
import Swal from 'sweetalert2';

const Styled = styled.div`
.header {
Expand Down Expand Up @@ -94,6 +96,7 @@ const Styled = styled.div`
`;

const tabOptions = ['Summary', 'Files'];

export const JobFullDetail: FC = () => {

const router = useRouter();
Expand All @@ -110,6 +113,24 @@ export const JobFullDetail: FC = () => {
variables: { jobId: id }
}
);
const [createJob] = useMutation(CREATE_JOB, {
onError: () => Swal.fire({
title: 'Unable to add docker job',
text: 'Please email <a href=\"mailto:sciserver-helpdesk@jhu.edu\">sciserver-helpdesk@jhu.edu</a> for more assistance.',
icon: 'error',
confirmButtonText: 'OK'
}).then(() => {
return;
}).catch(Error),
onCompleted: () => Swal.fire({
title: 'Job created successfully',
text: 'Your job has been created and is now queued.',
icon: 'success',
confirmButtonText: 'OK'
}).then(() => {
router.reload();
})
});

const jobDetail = useMemo<JobDetails>(() => {

Expand All @@ -118,9 +139,25 @@ export const JobFullDetail: FC = () => {
}
}, [data]);


const getDownloadURL = (row: File): string => {
return `${process.env.NEXT_PUBLIC_FILE_SERVICE_URL}file/${jobDetail.job.resultsFolderURI.replace('/home/idies/workspace/', '')}/${row.name}`;
return `${process.env.NEXT_PUBLIC_FILE_SERVICE_URL}file/${jobDetail.job.resultsFolderURI.replace('/home/idies/workspace/', '')}/${encodeURIComponent(row.name)}`;
};

const rerunJob = (job: Job) => {
createJob({
variables: {
createJobParams: {
dockerComputeEndpoint: job.dockerComputeEndpoint,
dockerImageName: job.dockerImageName,
resultsFolderURI: job.resultsFolderURI,
submitterDID: job.submitterDID,
volumeContainers: job.dataVolumes.map(dv => dv.publisherDID),
userVolumes: job.userVolumes.map(uv => uv.id),
command: job.command,
scriptURI: job.scriptURI || ''
}
}
});
};

const columns: GridColDef<File>[] = [
Expand Down Expand Up @@ -170,40 +207,45 @@ export const JobFullDetail: FC = () => {
</IconButton>
<div>
<div className="job-field">
<Typography variant="h5" gutterBottom component="div">
<h3>
Job ID:
</Typography>
<Typography variant="body1" gutterBottom component="div">
</h3>
<p>
{jobDetail.job.id}
</Typography>
</p>
</div>
<div className="job-field">
<Typography variant="h5" gutterBottom component="div">
<h3>
Image:
</Typography>
<Typography variant="body1" gutterBottom component="div">
</h3>
<p>
{jobDetail.job.dockerImageName}
</Typography>
</p>
</div>
</div>
<div>
<div className="job-field">
<Typography variant="h5" gutterBottom component="div">
<h3>
Started:
</Typography>
<Typography variant="body1" gutterBottom component="div">
</h3>
<p>
{jobDetail.job.startTime ? new Date(jobDetail.job.startTime).toLocaleString() : 'N/A'}
</Typography>
</p>
</div>
<div className="job-field">
<Typography variant="h5" gutterBottom component="div">
<h3>
Ended:
</Typography>
<Typography variant="body1" gutterBottom component="div">
</h3>
<p>
{jobDetail.job.endTime ? new Date(jobDetail.job.endTime).toLocaleString() : 'N/A'}
</Typography>
</p>
</div>
</div>
<Tooltip title="Re-run Job">
<IconButton color="primary" aria-label="Re-run job" onClick={() => rerunJob(jobDetail.job)}>
<ReplayIcon />
</IconButton>
</Tooltip>
</div>
{jobDetail.job.command &&
<div className="command">
Expand Down
38 changes: 19 additions & 19 deletions components/ui/web/components/content/jobs/detail/jobShortDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ import { useRouter } from 'next/router';
const StyledTableRow = styled(TableRow)`
.job-details {
display: flex;
gap: 2rem;
justify-content: space-between;
align-items: center;

.job-field {
display : flex;
gap: 1rem;
gap: 0.5rem;
align-items: center;
}
}
Expand Down Expand Up @@ -70,46 +71,45 @@ export const JobShortDetail: FC<Props> = ({ job, isOpen }) => {
<div className="job-details">
<div>
<div className="job-field">
<Typography variant="h5" gutterBottom component="div">
<h3>
Job ID:
</Typography>
<Typography variant="body1" gutterBottom component="div">
</h3>
<p>
{job.id}
</Typography>
</p>
</div>
<div className="job-field">
<Typography variant="h5" gutterBottom component="div">
<h3>
Image:
</Typography>
<Typography variant="body1" gutterBottom component="div">
</h3>
<p>
{job.dockerImageName}
</Typography>
</p>
</div>
</div>
<div>
<div className="job-field">
<Typography variant="h5" gutterBottom component="div">
<h3>
Started:
</Typography>
<Typography variant="body1" gutterBottom component="div">
</h3>
<p>
{job.startTime ? new Date(job.startTime).toLocaleString() : 'N/A'}
</Typography>
</p>
</div>
<div className="job-field">
<Typography variant="h5" gutterBottom component="div">
<h3>
Ended:
</Typography>
<Typography variant="body1" gutterBottom component="div">
</h3>
<p>
{job.endTime ? new Date(job.endTime).toLocaleString() : 'N/A'}
</Typography>
</p>
</div>
</div>
<div>
<Button onClick={() => router.push(`/jobs/${job.id}`)} variant="contained" color="primary">
See full details
</Button>
</div>

</div>
{job.command &&
<div className="command">
Expand Down
15 changes: 2 additions & 13 deletions components/ui/web/components/content/jobs/list/jobDatagrid.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { FC, useState } from 'react';
import styled from 'styled-components';
import {
Replay as ReplayIcon,
KeyboardArrowUp as KeyboardArrowUpIcon,
KeyboardArrowDown as KeyboardArrowDownIcon
} from '@mui/icons-material';
Expand All @@ -15,8 +14,7 @@ import {
TableCell,
TableContainer,
TableHead,
TableRow,
Tooltip
TableRow
} from '@mui/material';

import { Job } from 'src/graphql/typings';
Expand Down Expand Up @@ -46,10 +44,9 @@ margin-top: 2rem;

type Props = {
jobsList: Job[];
createJob: (variables: Job) => void;
}

export const JobsDataGrid: FC<Props> = ({ jobsList, createJob }) => {
export const JobsDataGrid: FC<Props> = ({ jobsList }) => {
// State to track which job rows are expanded by their ID
const [openRows, setOpenRows] = useState<Set<string>>(new Set());

Expand Down Expand Up @@ -95,7 +92,6 @@ export const JobsDataGrid: FC<Props> = ({ jobsList, createJob }) => {
<TableCell className="column-header">Submitted At</TableCell>
<TableCell className="column-header">Name</TableCell>
<TableCell className="column-header">Status</TableCell>
<TableCell className="column-header" align="right">Actions</TableCell>
</TableRow>
</TableHead>
<TableBody>
Expand All @@ -116,13 +112,6 @@ export const JobsDataGrid: FC<Props> = ({ jobsList, createJob }) => {
</TableCell>
<TableCell className="cell">{job.submitterDID}</TableCell>
<TableCell className="cell">{getStatus(job)}</TableCell>
<TableCell className="cell" align="right">
<Tooltip title="Re Run Job">
<IconButton color="primary" onClick={() => createJob(job)}>
<ReplayIcon />
</IconButton>
</Tooltip>
</TableCell>
</TableRow>
<JobShortDetail job={job} isOpen={isRowOpen(job.id)} />
</>
Expand Down
43 changes: 2 additions & 41 deletions components/ui/web/components/content/jobs/list/jobsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,59 +73,20 @@ export const JobsList: FC = () => {
}
);

const [createJob, { data: newJob, error }] = useMutation(CREATE_JOB, {
onError: () => Swal.fire({
title: 'Unable to add docker job',
text: 'Please email <a href=\"mailto:sciserver-helpdesk@jhu.edu\">sciserver-helpdesk@jhu.edu</a> for more assistance.',
icon: 'error',
confirmButtonText: 'OK'
}).then(() => {
return;
}).catch(Error),
onCompleted: () => Swal.fire({
title: 'Job created successfully',
text: 'Your job has been created and is now queued.',
icon: 'success',
confirmButtonText: 'OK'
}).then(() => {
router.reload();
})
});

const jobsList = useMemo<Job[]>(() => {
if (allJobs && allJobs.getJobs) {
return allJobs.getJobs;
}
if (newJob && newJob.createJob) {
return [...allJobs.getJobs, newJob.createJob];
}
return [];
}, [allJobs, newJob]);

const createJobHandler = (job: Job) => {
createJob({
variables: {
createJobParams: {
dockerComputeEndpoint: job.dockerComputeEndpoint,
dockerImageName: job.dockerImageName,
resultsFolderURI: job.resultsFolderURI,
submitterDID: job.submitterDID,
volumeContainers: job.dataVolumes.map(dv => dv.publisherDID),
userVolumes: job.userVolumes.map(uv => uv.id),
command: job.command,
scriptURI: job.scriptURI || ''
}
}
});
};
}, [allJobs]);

return <Styled>
<h1>Jobs</h1>
{loading &&
<LoadingAnimation backDropIsOpen={loading} />
}
{jobsList.length > 0 &&
<JobsDataGrid createJob={createJobHandler} jobsList={jobsList} />
<JobsDataGrid jobsList={jobsList} />
}
{!loading && !jobsList.length &&
<div className="no-active-containers">
Expand Down
Loading
Loading