Skip to content
Snippets Groups Projects
ChangeHostAdmin.tsx 6.78 KiB
Newer Older
import {
  useState,
  useEffect,
  useCallback,
  useMemo,
Max Frederiksen's avatar
Max Frederiksen committed
  SetStateAction,
  Dispatch
} from "react";
import { ConfirmationDialog } from "@ess-ics/ce-ui-common";
  Button,
  Typography,
  Grid,
  Tooltip,
  CircularProgress,
  Autocomplete
} from "@mui/material";
import { AccessControl } from "../../auth/AccessControl";
import { useTypingTimer } from "../../../hooks/useTypingTimer";
import {
  HostInfoWithId,
  IocDetails,
  useLazyListHostsQuery
} from "../../../store/deployApi";
import { useUpdateActiveDeploymentHostMutation } from "../../../store/enhancedApi";
Imre Toth's avatar
Imre Toth committed
import { useCustomSnackbar } from "../../common/snackbar";
import { getErrorState } from "../../common/Alerts/AlertsData";
interface ChangeHostAdminProps {
  ioc: IocDetails;
  buttonDisabled: boolean;
  setButtonDisabled: Dispatch<SetStateAction<boolean>>;
}

export const ChangeHostAdmin = ({
  ioc,
  buttonDisabled,
  setButtonDisabled
}: ChangeHostAdminProps) => {
  const initHost = useMemo(
    () => ({
      fqdn: ioc?.activeDeployment?.host?.fqdn,
      hostId: ioc?.activeDeployment?.host?.hostId
    [ioc?.activeDeployment?.host]
  const [host, setHost] = useState<HostInfoWithId | null>(initHost);
  const [open, setOpen] = useState(false);
  const { value: query, onKeyUp: onHostKeyUp } = useTypingTimer({
    interval: 500
  });
Imre Toth's avatar
Imre Toth committed
  const { showSuccess } = useCustomSnackbar();
  const [getHosts, { data: hosts, isLoading: loadingHosts }] =
    useLazyListHostsQuery();
Imre Toth's avatar
Imre Toth committed
  const [updateHost, { isLoading, data: updatedIoc, error: updateHostError }] =
    useUpdateActiveDeploymentHostMutation();

  const noModification = useCallback(
    () => !host || host?.hostId === ioc?.activeDeployment?.host?.hostId,
  const onClose = useCallback(() => {
    setOpen(false);
    setHost(initHost);
  }, [setOpen, initHost]);
  const onConfirm = useCallback(() => {
    if (ioc.id) {
      setButtonDisabled(true);
      updateHost({
        iocId: ioc.id,
        updateHostRequest: {
          hostId: host?.hostId
        }
Imre Toth's avatar
Imre Toth committed
      })
        .unwrap()
        .then(() => {
          showSuccess("IOC host changed successfully");
          setButtonDisabled(false);
        })
        .catch(() => {
          setButtonDisabled(false);
        });
Imre Toth's avatar
Imre Toth committed
  }, [updateHost, ioc, host?.hostId, setButtonDisabled, showSuccess]);

  useEffect(() => {
    if (updatedIoc) {
        // Schema change related. Wait until all files have been migrated
        fqdn: updatedIoc?.activeDeployment?.host?.fqdn,
        hostId: updatedIoc?.activeDeployment?.host?.hostId
      setButtonDisabled(false);
  }, [updatedIoc, setButtonDisabled]);
    getHosts({ text: `${query}` });

  let disabledButtonTitle = "";
  if (buttonDisabled || ioc.operationInProgress) {
    disabledButtonTitle =
      "There is an ongoing operation, you cannot 'undeploy' the IOC right now";
  } else {
    if (!ioc.activeDeployment) {
      disabledButtonTitle = "IOC has no active deployment";
    }
  }

  return (
    <>
      <AccessControl
        allowedRoles={["DeploymentToolAdmin"]}
        renderNoAccess={() => <></>}
      >
        <ConfirmationDialog
          title={
            <Typography
              variant="h2"
              marginY={1}
            >
Imre Toth's avatar
Imre Toth committed
              Administratively change host
            <>
              <Typography component="span">
Imre Toth's avatar
Imre Toth committed
                Are you sure you want to update the IOC to be specified as
                deployed on
                <Typography
                  component="span"
                  fontFamily="monospace"
Imre Toth's avatar
Imre Toth committed
                  {host?.fqdn}
                </Typography>{" "}
                ?
              </Typography>
            </>
          }
          confirmText="Modify Host"
          cancelText="Cancel"
          open={open}
Imre Toth's avatar
Imre Toth committed
          onCancel={onClose}
          onClose={onClose}
          onConfirm={onConfirm}
Imre Toth's avatar
Imre Toth committed
          isLoading={isLoading}
          error={updateHostError && getErrorState(updateHostError).message}
        <Box sx={{ pt: 2 }}>
          <Typography
            sx={{ my: 2.5 }}
            component="h2"
Imre Toth's avatar
Imre Toth committed
            Change deployment host (e.g. if host has been replaced in NetBox)
          </Typography>
          <Grid
            container
            spacing={1}
          >
            <Grid
              item
              xs={12}
            >
              <Autocomplete
                autoHighlight
                id="host"
Sky Brewer's avatar
Sky Brewer committed
                options={query ? (hosts?.netBoxHosts ?? []) : []}
                loading={loadingHosts}
                clearOnBlur={false}
                value={host}
                getOptionLabel={(option) => {
                  return option?.fqdn ?? "";
                }}
                renderInput={(params) => (
                  <TextField
                    {...params}
                    label="host"
                    variant="outlined"
                    required
                    InputProps={{
                      ...params.InputProps,
                      endAdornment: (
                          {loadingHosts ? (
                            <CircularProgress
                              color="inherit"
                              size={20}
                            />
                          ) : null}
                          {params.InputProps.endAdornment}
                onChange={(_event, value: HostInfoWithId | null) => {
Sky Brewer's avatar
Sky Brewer committed
                onInputChange={(event) => {
Sky Brewer's avatar
Sky Brewer committed
                  if (event) {
                    onHostKeyUp(event as React.KeyboardEvent<HTMLInputElement>);
Sky Brewer's avatar
Sky Brewer committed
                  }
Sky Brewer's avatar
Sky Brewer committed
                filterOptions={(options) => options}
              />
            </Grid>
            <Grid
              item
              xs={12}
            >
              <Tooltip title={disabledButtonTitle}>
                <span>
                  <Button
                    color="primary"
                    variant="contained"
                    onClick={() => setOpen(true)}
                    disabled={
                      buttonDisabled ||
                      ioc.operationInProgress ||
                      !ioc.activeDeployment ||
Imre Toth's avatar
Imre Toth committed
                      isLoading ||
Imre Toth's avatar
Imre Toth committed
                    Change host
                  </Button>
                </span>
              </Tooltip>
      </AccessControl>
    </>
  );