diff --git a/frontend/src/components/resources/deployment/actions.tsx b/frontend/src/components/resources/deployment/actions.tsx index 4be8d38d0..3ae3bf084 100644 --- a/frontend/src/components/resources/deployment/actions.tsx +++ b/frontend/src/components/resources/deployment/actions.tsx @@ -8,25 +8,50 @@ import { useExecute, useInvalidate, useRead, useWrite } from "@lib/hooks"; import { useNavigate } from "react-router-dom"; import { Input } from "@ui/input"; import { useToast } from "@ui/use-toast"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { Types } from "@monitor/client"; +import { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectTrigger, +} from "@ui/select"; +import { DockerContainerState } from "@monitor/client/dist/types"; interface DeploymentId { id: string; } export const RedeployContainer = ({ id }: DeploymentId) => { + const deployment = useRead("GetDeployment", { deployment: id }).data; + const [signal, setSignal] = useState(); + + useEffect( + () => setSignal(deployment?.config.termination_signal), + [deployment?.config.termination_signal] + ); + const { mutate, isPending } = useExecute("Deploy"); + const deployments = useRead("ListDeployments", {}).data; - const deployment = deployments?.find((d) => d.id === id); + const deployment_item = deployments?.find((d) => d.id === id); + const deploying = useRead("GetDeploymentActionState", { deployment: id }).data ?.deploying; + const pending = isPending || deploying; + if (!deployment) return null; + + const deployed = + deployment_item?.info.state !== DockerContainerState.NotDeployed && + deployment_item?.info.state !== DockerContainerState.Unknown; + return ( @@ -34,9 +59,18 @@ export const RedeployContainer = ({ id }: DeploymentId) => { ) } - onClick={() => mutate({ deployment: id })} + onClick={() => mutate({ deployment: id, stop_signal: signal })} disabled={pending} loading={pending} + additional={ + deployed && deployment.config.term_signal_labels.length > 1 ? ( + + ) : undefined + } /> ); }; @@ -63,23 +97,39 @@ const StartContainer = ({ id }: DeploymentId) => { }; const StopContainer = ({ id }: DeploymentId) => { - const { data: d } = useRead("GetDeployment", { deployment: id }); + const deployment = useRead("GetDeployment", { deployment: id }).data; + const [signal, setSignal] = useState(); + + useEffect( + () => setSignal(deployment?.config.termination_signal), + [deployment?.config.termination_signal] + ); + const { mutate, isPending } = useExecute("StopContainer"); const stopping = useRead("GetDeploymentActionState", { deployment: id, }).data?.stopping; const pending = isPending || stopping; - if (!d) return null; + if (!deployment) return null; return ( } - onClick={() => mutate({ deployment: id })} + onClick={() => mutate({ deployment: id, signal })} disabled={pending} loading={pending} + additional={ + deployment.config.term_signal_labels.length > 1 ? ( + + ) : undefined + } /> ); }; @@ -98,6 +148,13 @@ export const StartOrStopContainer = ({ id }: DeploymentId) => { export const RemoveContainer = ({ id }: DeploymentId) => { const deployment = useRead("GetDeployment", { deployment: id }).data; + const [signal, setSignal] = useState(); + + useEffect( + () => setSignal(deployment?.config.termination_signal), + [deployment?.config.termination_signal] + ); + const { mutate, isPending } = useExecute("RemoveContainer"); const deployments = useRead("ListDeployments", {}).data; @@ -116,15 +173,62 @@ export const RemoveContainer = ({ id }: DeploymentId) => { } - onClick={() => mutate({ deployment: id })} + onClick={() => mutate({ deployment: id, signal })} disabled={pending} loading={pending} + additional={ + deployment.config.term_signal_labels.length > 1 ? ( + + ) : undefined + } /> ); }; +const TermSignalSelector = ({ + signals, + signal, + setSignal, +}: { + signals: Types.TerminationSignalLabel[]; + signal: Types.TerminationSignal | undefined; + setSignal: (signal: Types.TerminationSignal) => void; +}) => { + const label = signals.find((s) => s.signal === signal)?.label; + return ( +
+
Termination
+
+ {label} + +
+
+ ); +}; + export const DeleteDeployment = ({ id }: { id: string }) => { const nav = useNavigate(); const { data: d } = useRead("GetDeployment", { deployment: id }); diff --git a/frontend/src/components/util.tsx b/frontend/src/components/util.tsx index 8a6155df2..9cbadc0c4 100644 --- a/frontend/src/components/util.tsx +++ b/frontend/src/components/util.tsx @@ -105,6 +105,7 @@ export const ActionWithDialog = ({ disabled, loading, onClick, + additional, }: { name: string; title: string; @@ -112,6 +113,7 @@ export const ActionWithDialog = ({ disabled?: boolean; loading?: boolean; onClick?: () => void; + additional?: ReactNode; }) => { const [open, setOpen] = useState(false); const [input, setInput] = useState(""); @@ -146,6 +148,7 @@ export const ActionWithDialog = ({

setInput(e.target.value)} /> + {additional}