Skip to content

Commit

Permalink
Add to Lookout to allow reprioritization of Jobs (#591)
Browse files Browse the repository at this point in the history
* Initial changes for Job reprioritization

* Functioning reprioritize

* Add newPriority input

* Displayed failed reprioritization better

* Add jobset reprioritization

* Formatting tweaks

* Formatting changes

* Fix jobset button states

* Handle new api structure

* Fix JobService to use new variable names

* Tidy up from codereview

* Tidy up from code review

* Use new css class names in job-set Outcomes

* Fix job sets

* Use Dialog instead of Modal

* Fix CancelJobSet ListItemText className

* Reset reprioritize contexts on deselectAll

* Remove forwardRef from RepioritizeJob components
  • Loading branch information
JamesMurkin authored Jun 18, 2021
1 parent cb2d468 commit 3ed91b8
Show file tree
Hide file tree
Showing 19 changed files with 996 additions and 70 deletions.
48 changes: 0 additions & 48 deletions internal/lookout/ui/src/components/job-sets/CancelJobSets.css

This file was deleted.

10 changes: 5 additions & 5 deletions internal/lookout/ui/src/components/job-sets/CancelJobSets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { List, ListItem, ListItemText, Paper } from "@material-ui/core"
import { JobSet } from "../../services/JobService"
import LoadingButton from "../jobs/LoadingButton"

import "./CancelJobSets.css"
import "./JobSetActions.css"

type CancelJobSetsProps = {
queue: string
Expand All @@ -16,12 +16,12 @@ type CancelJobSetsProps = {

export default function CancelJobSets(props: CancelJobSetsProps) {
return (
<div className="cancel-job-sets-container">
<p className="cancel-job-sets-text">The following Job Sets in queue {props.queue} will be cancelled:</p>
<List component={Paper} className="cancel-job-sets-table-container">
<div className="job-sets-action-container">
<p className="job-sets-action-text">The following Job Sets in queue {props.queue} will be cancelled:</p>
<List component={Paper} className="job-sets-action-table-container">
{props.jobSets.map((jobSet) => (
<ListItem key={jobSet.jobSetId}>
<ListItemText className="cancel-job-sets-wrap">{jobSet.jobSetId}</ListItemText>
<ListItemText className="job-sets-action-wrap">{jobSet.jobSetId}</ListItemText>
</ListItem>
))}
</List>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
import { CancelJobSetsResult } from "../../services/JobService"
import LoadingButton from "../jobs/LoadingButton"

import "./CancelJobSets.css"
import "./JobSetActions.css"

type CancelJobSetsOutcomeProps = {
cancelJobSetsResult: CancelJobSetsResult
Expand All @@ -26,13 +26,13 @@ type CancelJobSetsOutcomeProps = {

export default function CancelJobSetsOutcome(props: CancelJobSetsOutcomeProps) {
return (
<div className="cancel-job-sets-container">
<div className="job-sets-action-container">
{props.cancelJobSetsResult.cancelledJobSets.length > 0 && (
<Fragment>
<p className="cancel-job-sets-text">The following Job Sets were cancelled successfully:</p>
<List component={Paper} className="cancel-job-sets-table-container cancel-job-sets-success">
<p className=".job-sets-action-text">The following Job Sets were cancelled successfully:</p>
<List component={Paper} className="job-sets-action-table-container job-sets-action-success">
{props.cancelJobSetsResult.cancelledJobSets.map((jobSet) => (
<ListItem key={jobSet.jobSetId} className="cancel-job-sets-wrap">
<ListItem key={jobSet.jobSetId} className="job-sets-action-wrap">
<ListItemText>{jobSet.jobSetId}</ListItemText>
</ListItem>
))}
Expand All @@ -41,22 +41,22 @@ export default function CancelJobSetsOutcome(props: CancelJobSetsOutcomeProps) {
)}
{props.cancelJobSetsResult.failedJobSetCancellations.length > 0 && (
<Fragment>
<p className="cancel-job-sets-text">Some Job Sets failed to cancel:</p>
<TableContainer component={Paper} className="cancel-job-sets-table-container">
<Table stickyHeader className="cancel-job-sets-table">
<p className="job-sets-action-text">Some Job Sets failed to cancel:</p>
<TableContainer component={Paper} className="job-sets-action-table-container">
<Table stickyHeader className="job-sets-action-table">
<TableHead>
<TableRow>
<TableCell className="cancel-job-sets-id cancel-job-sets-failure-header">Job Set</TableCell>
<TableCell className="cancel-job-sets-error cancel-job-sets-failure-header">Error</TableCell>
<TableCell className="job-sets-action-id job-sets-action-failure-header">Job Set</TableCell>
<TableCell className="job-sets-action-error job-sets-action-failure-header">Error</TableCell>
</TableRow>
</TableHead>
<TableBody className="cancel-job-sets-failure">
<TableBody className="job-sets-action-failure">
{props.cancelJobSetsResult.failedJobSetCancellations.map((failedCancellation) => (
<TableRow key={failedCancellation.jobSet.jobSetId}>
<TableCell className="cancel-job-sets-id cancel-job-sets-wrap">
<TableCell className="job-sets-action-id job-sets-action-wrap">
{failedCancellation.jobSet.jobSetId}
</TableCell>
<TableCell className="cancel-job-sets-error cancel-job-sets-wrap">
<TableCell className="job-sets-action-error job-sets-action-wrap">
{failedCancellation.error}
</TableCell>
</TableRow>
Expand Down
48 changes: 48 additions & 0 deletions internal/lookout/ui/src/components/job-sets/JobSetActions.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
.job-sets-action-container {
padding: 0 4em 2em 4em;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
max-height: 100%;
}

.job-sets-action-container .job-sets-action-text {
width: 100%;
}

.job-sets-action-container .job-sets-action-table-container {
width: 100%;
max-height: 100%;
margin-bottom: 2em;
}

.job-sets-action-container .job-sets-action-table {
width: 100%;
table-layout: fixed;
}

.job-sets-action-container .job-sets-action-id {
width: 40%;
}

.job-sets-action-container .job-sets-action-error {
width: 60% !important;
}

.job-sets-action-container .job-sets-action-wrap {
white-space: normal;
word-wrap: break-word;
}

.job-sets-action-container .job-sets-action-success {
background-color: #e8f5e9;
}

.job-sets-action-container .job-sets-action-failure-header {
background-color: #ffcdd2 !important;
}

.job-sets-action-container .job-sets-action-failure {
background-color: #ffebee;
}
6 changes: 5 additions & 1 deletion internal/lookout/ui/src/components/job-sets/JobSets.css
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@
}

.job-sets-header .job-sets-actions .cancel-button {
margin-right: 4em;
margin-right: 3em;
}

.job-sets-header .job-sets-actions .reprioritize-button {
margin-right: 3em;
}

.job-sets-field {
Expand Down
14 changes: 14 additions & 0 deletions internal/lookout/ui/src/components/job-sets/JobSets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
TextField,
} from "@material-ui/core"
import CancelIcon from "@material-ui/icons/Cancel"
import LowPriority from "@material-ui/icons/LowPriority"
import RefreshIcon from "@material-ui/icons/Refresh"
import { AutoSizer } from "react-virtualized"

Expand All @@ -28,6 +29,7 @@ interface JobSetsProps {
jobSets: JobSet[]
selectedJobSets: Map<string, JobSet>
canCancel: boolean
canReprioritize: boolean
onQueueChange: (queue: string) => void
onViewChange: (view: JobSetsView) => void
onRefresh: () => void
Expand All @@ -36,6 +38,7 @@ interface JobSetsProps {
onShiftSelectJobSet: (index: number, selected: boolean) => void
onDeselectAllClick: () => void
onCancelJobSetsClick: () => void
onReprioritizeJobSetsClick: () => void
}

const menuProps: Partial<MenuProps> = {
Expand Down Expand Up @@ -129,6 +132,17 @@ export default function JobSets(props: JobSetsProps) {
</div>
</div>
<div className="job-sets-actions">
<div className="reprioritize-button">
<Button
disabled={!props.canReprioritize}
variant="contained"
color="primary"
startIcon={<LowPriority />}
onClick={props.onReprioritizeJobSetsClick}
>
Reprioritize
</Button>
</div>
<div className="cancel-button">
<Button
disabled={!props.canCancel}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from "react"

import { List, ListItem, ListItemText, Paper, TextField } from "@material-ui/core"

import { JobSet } from "../../services/JobService"
import LoadingButton from "../jobs/LoadingButton"

import "./JobSetActions.css"

type ReprioritizeJobSetsProps = {
queue: string
jobSets: JobSet[]
isLoading: boolean
isValid: boolean
onReprioritizeJobsSets: () => void
onPriorityChange: (e: string) => void
}

export default function ReprioritizeJobSets(props: ReprioritizeJobSetsProps) {
return (
<div className="job-sets-action-container">
<p className="job-sets-action-text">The following Job Sets in queue {props.queue} will be reprioritized:</p>
<List component={Paper} className="job-sets-action-table-container">
{props.jobSets.map((jobSet) => (
<ListItem key={jobSet.jobSetId}>
<ListItemText className="job-sets-action-wrap">{jobSet.jobSetId}</ListItemText>
</ListItem>
))}
</List>
<div>
<TextField
autoFocus={true}
placeholder={"New priority"}
margin={"normal"}
type={"text"}
error={!props.isValid}
helperText={!props.isValid ? "Value must be a number >= 0" : " "}
onChange={(event) => props.onPriorityChange(event.target.value)}
/>
<LoadingButton
content={"Reprioritize Job Sets"}
isDisabled={!props.isValid}
isLoading={props.isLoading}
onClick={props.onReprioritizeJobsSets}
/>
</div>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from "react"

import { Dialog, DialogContent, DialogTitle } from "@material-ui/core"

import { ReprioritizeJobSetsRequestStatus } from "../../containers/JobSetsContainer"
import { JobSet, ReprioritizeJobSetsResult } from "../../services/JobService"
import ReprioritizeJobSets from "./ReprioritizeJobSets"
import ReprioritizeJobSetsOutcome from "./ReprioritizeJobSetsOutcome"

export type ReprioritizeJobSetsDialogState = "ReprioritizeJobSets" | "ReprioritizeJobSetsResult" | "None"

export interface ReprioritizeJobSetsDialogContext {
dialogState: ReprioritizeJobSetsDialogState
queue: string
newPriority: number
isValid: boolean
jobSetsToReprioritize: JobSet[]
reprioritizeJobSetsResult: ReprioritizeJobSetsResult
reproiritizeJobSetsRequestStatus: ReprioritizeJobSetsRequestStatus
}

interface ReprioritizeJobSetsProps extends ReprioritizeJobSetsDialogContext {
onReprioritizeJobSets: () => void
onPriorityChange: (e: string) => void
onClose: () => void
}

export default function ReprioritizeJobSetsDialog(props: ReprioritizeJobSetsProps) {
const isOpen = props.dialogState === "ReprioritizeJobSets" || props.dialogState === "ReprioritizeJobSetsResult"
const isLoading = props.reproiritizeJobSetsRequestStatus === "Loading"

let content = <div />
if (props.dialogState === "ReprioritizeJobSets") {
content = (
<ReprioritizeJobSets
queue={props.queue}
jobSets={props.jobSetsToReprioritize}
isLoading={isLoading}
isValid={props.isValid}
onReprioritizeJobsSets={props.onReprioritizeJobSets}
onPriorityChange={props.onPriorityChange}
/>
)
}
if (props.dialogState === "ReprioritizeJobSetsResult") {
content = (
<ReprioritizeJobSetsOutcome
reprioritizeJobSetResult={props.reprioritizeJobSetsResult}
isLoading={isLoading}
newPriority={props.newPriority}
onReprioritizeJobSets={props.onReprioritizeJobSets}
/>
)
}

return (
<Dialog
open={isOpen}
aria-labelledby="reprioritize-job-sets-dialog-title"
aria-describedby="reprioritize-job-sets-dialog-description"
onClose={props.onClose}
maxWidth={"md"}
>
<DialogTitle id="-reprioritize-job-sets-dialog-title">Reprioritize Job Sets</DialogTitle>
<DialogContent>{content}</DialogContent>
</Dialog>
)
}
Loading

0 comments on commit 3ed91b8

Please sign in to comment.