Skip to content

Commit

Permalink
Add component Alert and KillButton
Browse files Browse the repository at this point in the history
1. Move Alert and kill-run Button from Run Page
    to `Alert` and `KillButton` component respectively
2. lib/teuthologyAPI: add useRunKill
    (which uses `useMutation` to send POST req at /kill to t-api)

Signed-off-by: Vallari Agrawal <val.agl002@gmail.com>
  • Loading branch information
VallariAg committed Dec 1, 2023
1 parent 8398c0e commit 1ba3665
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 59 deletions.
29 changes: 29 additions & 0 deletions src/components/Alert/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Snackbar from "@mui/material/Snackbar";
import Alert from "@mui/material/Alert";
import { useState } from "react";

type AlertProps = {
severity: "success" | "error",
message: string,
};

export default function AlertComponent(props: AlertProps) {
const [isOpen, setIsOpen] = useState(true);
const handleClose = (
event?: React.SyntheticEvent | Event,
reason?: string
) => {
if (reason === "clickaway") {
return;
}
setIsOpen(false);
};

return (
<Snackbar autoHideDuration={3000} open={isOpen} onClose={handleClose}>
<Alert onClose={handleClose} severity={props.severity} sx={{ width: "100%" }}>
{props.message}
</Alert>
</Snackbar>
);
}
50 changes: 50 additions & 0 deletions src/components/KillButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import type { UseMutationResult } from "@tanstack/react-query";
import Button from "@mui/material/Button";
import Box from "@mui/material/Box";
import { CircularProgress } from "@mui/material";

import { Run } from "../../lib/paddles.d"
import Alert from "../Alert";


type KillButtonProps = {
mutation: UseMutationResult;
text: string;
runDetails?: Run;
};


// TODO: make this generic for killing runs and job
export default function KillButton(props: KillButtonProps) {
const mutation: UseMutationResult = props.mutation;

const killPayload = {
"--run": props.runDetails?.name,
"--owner": props.runDetails?.user,
"--machine-type": props.runDetails?.machine_type,
"--user": props.runDetails?.user,
}

return (
<div>
<div style={{ display: "flex" }}>
<Button
variant="contained"
color="error"
size="large"
onClick={() => mutation.mutate(killPayload)}
disabled={(mutation.isLoading)}
>
{props.text}
</Button>
{(mutation.isLoading) ? (
<Box sx={{ p: 1 }}>
<CircularProgress size={20} color="inherit" />
</Box>
) : null}
</div>
{ (mutation.isError) ? <Alert severity="error" message="Unable to kill run" /> : null }
{ (mutation.isSuccess) ? <Alert severity="success" message="Run killed successfully" /> : null }
</div>
);
};
2 changes: 2 additions & 0 deletions src/lib/paddles.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ export type Run = {
jobs: Job[];
scheduled: string;
results: RunResults;
user: string;
machine_type: string;
};

export type Node = {
Expand Down
21 changes: 18 additions & 3 deletions src/lib/teuthologyAPI.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import axios from "axios";
import { useQuery } from "@tanstack/react-query";
import { useQuery, useMutation } from "@tanstack/react-query";
import type { UseQueryResult, UseMutationResult } from "@tanstack/react-query";
import { Cookies } from "react-cookie";
import type { UseQueryResult } from "@tanstack/react-query";

const TEUTHOLOGY_API_SERVER =
import.meta.env.VITE_TEUTHOLOGY_API || "";
Expand Down Expand Up @@ -56,9 +56,24 @@ function useUserData(): Map<string, string> {
return new Map();
}

function useRunKill(): UseMutationResult {
const url = getURL("/kill?dry_run=false&logs=true");
const mutation: UseMutationResult = useMutation({
mutationKey: ['run-kill', { url }],
mutationFn: (payload) => (
axios.post(url, payload, {
withCredentials: true
})
),
retry: 0,
});
return mutation;
}

export {
doLogin,
doLogout,
useSession,
useUserData
useUserData,
useRunKill,
}
60 changes: 4 additions & 56 deletions src/pages/Run/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,19 @@ import { PropsWithChildren } from 'react'
import { useQueryParams, StringParam, NumberParam } from "use-query-params";
import { styled } from "@mui/material/styles";
import { useParams } from "react-router-dom";
import { useState } from "react";
import Typography from "@mui/material/Typography";
import Button from "@mui/material/Button";
import ButtonGroup from "@mui/material/ButtonGroup";
import Alert from "@mui/material/Alert";
import Box from "@mui/material/Box";
import CircularProgress from "@mui/material/CircularProgress";
import Snackbar from "@mui/material/Snackbar";
import { format } from "date-fns";
import { Helmet } from "react-helmet";

import type { Run, RunParams } from "../../lib/paddles.d";

import { useRun } from "../../lib/paddles";
import { useRunKill } from "../../lib/teuthologyAPI";
import JobList from "../../components/JobList";
import Link from "../../components/Link";
import KillButton from "../../components/KillButton";

const PREFIX = "index";

Expand Down Expand Up @@ -53,29 +50,8 @@ export default function Run() {
page: NumberParam,
pageSize: NumberParam,
});
const [kill, setKill] = useState(false);
const [success, setSuccess] = useState(false);
const [error, setError] = useState(false);
const killRun = async () => {
setKill(true);
// Using a mock API endpoint for testing
const response = await fetch("https://reqres.in/api/users/2?delay=3");
const status = response.status;
if (status === 200) setSuccess(true);
else setError(true);
setKill(false);
};
const handleClose = (
event?: React.SyntheticEvent | Event,
reason?: string
) => {
if (reason === "clickaway") {
return;
}
setSuccess(false);
setError(false);
};
const { name } = useParams<RunParams>();
const killMutation = useRunKill();
const query = useRun(name === undefined ? "" : name);
if (query === null) return <Typography>404</Typography>;
if (query.isError) return null;
Expand Down Expand Up @@ -111,35 +87,7 @@ export default function Run() {
date
</FilterLink>
</div>
<div
style={{
display: "flex",
}}
>
<Button
variant="contained"
color="error"
size="large"
onClick={killRun}
>
Kill Run
</Button>
{kill ? (
<Box sx={{ p: 1 }}>
<CircularProgress size={20} color="inherit" />
</Box>
) : null}
</div>
<Snackbar autoHideDuration={3000} open={success} onClose={handleClose}>
<Alert onClose={handleClose} severity="success" sx={{ width: "100%" }}>
Run killed successfully
</Alert>
</Snackbar>
<Snackbar autoHideDuration={3000} open={error} onClose={handleClose}>
<Alert onClose={handleClose} severity="error" sx={{ width: "100%" }}>
Unable to kill run
</Alert>
</Snackbar>
<KillButton mutation={killMutation} text="Kill run" runDetails={data} />
<ButtonGroup style={{ display: "flex", justifyContent: "center" }}>
<Button
onClick={() => {
Expand Down

0 comments on commit 1ba3665

Please sign in to comment.