diff --git a/lib/sockets/clients/Initiator.js b/lib/sockets/clients/Initiator.js index 2600444..93cc77b 100644 --- a/lib/sockets/clients/Initiator.js +++ b/lib/sockets/clients/Initiator.js @@ -17,6 +17,7 @@ export default class Initiator { (() => { console.log("job pipeline closed"); }); + this.sk = null; } async newJob(jobRequest, onLog, onClose, onCreate) { @@ -26,11 +27,11 @@ export default class Initiator { onLog = onLog ?? this.onLog.bind(this); onClose = onClose ?? this.onClose.bind(this); onCreate = onCreate ?? this.onCreate.bind(this); - const sk = mgr.socket("/"); - sk.on(events.JOB_LOG, onLog); - sk.on(events.JOB_CLS, onClose); + this.sk = mgr.socket("/"); + this.sk.on(events.JOB_LOG, onLog); + this.sk.on(events.JOB_CLS, onClose); return new Promise((res) => - sk.on(events.JOB_CRT, function onJobCreate(id) { + this.sk.on(events.JOB_CRT, function onJobCreate(id) { onCreate(id); res({ ...jobRequest, id }); }) @@ -78,13 +79,13 @@ export default class Initiator { ); }); onPipelineClose = onPipelineClose ?? this.onPipelineClose.bind(this); - const sk = mgr.socket("/"); - sk.on(events.JOB_LOG, onLog); - sk.on(events.JOB_CLS, onClose); - sk.on(events.PPL_TRG, onPipelineTrigger); - sk.on(events.PPL_CLS, onPipelineClose); + this.sk = mgr.socket("/"); + this.sk.on(events.JOB_LOG, onLog); + this.sk.on(events.JOB_CLS, onClose); + this.sk.on(events.PPL_TRG, onPipelineTrigger); + this.sk.on(events.PPL_CLS, onPipelineClose); return new Promise((res) => - sk.on(events.JOB_CRT, function onJobCreate(id) { + this.sk.on(events.JOB_CRT, function onJobCreate(id) { onCreate(id); res({ ...jobRequest, id }); }) diff --git a/src/ctx/JobContext.jsx b/src/ctx/JobContext.jsx index b84cc76..073b748 100644 --- a/src/ctx/JobContext.jsx +++ b/src/ctx/JobContext.jsx @@ -43,12 +43,12 @@ const reducer = (state, action) => { return { ...state, jobs }; case ACTIONS.UPDATE: - jobIndex = jobs.find((j) => j.id === (action.job.id ?? action.jobId)); + jobIndex = jobs.findIndex((j) => j.jobId === (action.job.jobId ?? action.jobId)); jobs[jobIndex] = { ...jobs[jobIndex], ...action.job }; return { ...state, jobs }; case ACTIONS.DELETE: - jobIndex = jobs.find((j) => j.id === action.jobId); + jobIndex = jobs.findIndex((j) => j.jobId === action.jobId); jobs.splice(jobIndex, 1); return { ...state, jobs }; @@ -66,6 +66,25 @@ export const JobProvider = ({ children }) => { dispatch({ type: ACTIONS.CREATE, job: { ...job, log: [] } }); const jobDelete = (jobId) => dispatch({ type: ACTIONS.DELETE, jobId }); + function jobCancel(jobId){ + const job = state.jobs.find((j)=>j.jobId===jobId); + if(job.initiator.sk) + + job.initiator.sk.close(); + job.status = jobStatus.CANCELED; + jobUpdate({ ...job }, jobId); + + } + + function jobDestroy(jobId){ + const job = state.jobs.find((j)=>j.jobId===jobId); + if(job.initiator.sk && job.status !== jobStatus.OK && job.status !== jobStatus.ERROR && job.status !== jobStatus.CANCELED){ + job.initiator.sk.close(); + } + + jobDelete(jobId); + } + function retryAll(failing) { // Query Full Locator console.log("Would retry all failing tests!"); @@ -89,6 +108,7 @@ export const JobProvider = ({ children }) => { jobId, isPipeline: false, builderCache, + initiator: i, }; const request = { @@ -141,6 +161,8 @@ export const JobProvider = ({ children }) => { retryAll, retrySingle, jobFactory, + jobCancel, + jobDestroy }; const contextValue = useMemo(() => context, [state, dispatch]); diff --git a/src/ctx/StoreContext.jsx b/src/ctx/StoreContext.jsx index 974f295..550762a 100644 --- a/src/ctx/StoreContext.jsx +++ b/src/ctx/StoreContext.jsx @@ -9,11 +9,11 @@ const localStorage = { setItem: () => {}, getItem: () => {} }; const localSettings = localStorage.getItem("settings"); const defaultSettings = { - focusJob: true, + focusJob: false, simplifiedControls: false, logAppDetails: true, defaultRegion: "us", - defaultPage: "failing", + defaultPage: "jobs", }; const settings = localSettings ? JSON.parse(localSettings) : defaultSettings; diff --git a/src/views/Views.jsx b/src/views/Views.jsx index 68c5e3a..79d82eb 100644 --- a/src/views/Views.jsx +++ b/src/views/Views.jsx @@ -33,7 +33,7 @@ export default function Views() { } + element={} /> } /> } /> diff --git a/src/views/jobs/JobView.jsx b/src/views/jobs/JobView.jsx index 14fa4e0..252cb99 100644 --- a/src/views/jobs/JobView.jsx +++ b/src/views/jobs/JobView.jsx @@ -1,6 +1,7 @@ import React, { useContext, useState, useEffect } from "react"; import { useNavigate } from "react-router-dom"; import JobContext, { jobStatus } from "../../ctx/JobContext.jsx"; +import StoreContext from "../../ctx/StoreContext.jsx"; import Box from "@mui/material/Box"; import AppBar from "@mui/material/AppBar"; import Toolbar from "@mui/material/Toolbar"; @@ -16,12 +17,17 @@ import MoreVertIcon from "@mui/icons-material/MoreVert"; import DownloadIcon from "@mui/icons-material/Download"; import ReplayIcon from "@mui/icons-material/Replay"; import ArrowBackIcon from "@mui/icons-material/ArrowBack"; +import DoNotDisturbIcon from "@mui/icons-material/DoNotDisturb"; +import DeleteIcon from "@mui/icons-material/Delete"; +import PlayArrowIcon from "@mui/icons-material/PlayArrow"; + + export default function JobView(props) { const navigate = useNavigate(); const { job } = props; - const { jobFactory } = useContext(JobContext); - + const { jobFactory, jobCancel, jobDestroy } = useContext(JobContext); + const {state: store} = useContext(StoreContext); const [anchorEl, setAnchorEl] = React.useState(null); const open = Boolean(anchorEl); const handleClick = (event) => { @@ -45,7 +51,8 @@ export default function JobView(props) { } function retryJob() { - jobFactory(job.builderCache); + const jobId = jobFactory(job.builderCache); + if(store.focusJob) navigate(`/qualiteer/jobs#${jobId}`); } function downloadLog() { @@ -53,6 +60,16 @@ export default function JobView(props) { download(`${job.jobId}.txt`, job.log.join("\n")); } + function cancelJob(){ + jobCancel(job.jobId); + + } + + function deleteJob(){ + jobDestroy(job.jobId); + navigateToJobs(); + } + const menuSelect = (cb) => () => { handleClose(); cb(); @@ -90,18 +107,30 @@ export default function JobView(props) { - - - - - Retry - - + Download Log + + + {job.status === jobStatus.OK || job.status === jobStatus.ERROR ? : } + + {job.status === jobStatus.ERROR? "Retry" : "Duplicate"} + + {job.status === jobStatus.OK || job.status === jobStatus.ERROR || job.status === jobStatus.CANCELED? null : + + + + Cancel + } + + + + + Delete + );