From eb000dd72ca8f8efb27b74b4d2250f1e124f9dbf Mon Sep 17 00:00:00 2001
From: Zoltan Runyo <zoltan.runyo@ess.eu>
Date: Wed, 25 Jan 2023 14:18:40 +0100
Subject: [PATCH] ICSHWI-11234: Extend admin features

---
 src/api/SwaggerApi.js                 |  18 +++
 src/components/IOC/ChangeHostAdmin.js | 217 ++++++++++++++++++++++++++
 src/components/IOC/IOCAdmin.js        |   9 ++
 3 files changed, 244 insertions(+)
 create mode 100644 src/components/IOC/ChangeHostAdmin.js

diff --git a/src/api/SwaggerApi.js b/src/api/SwaggerApi.js
index b1801af2..db012c89 100644
--- a/src/api/SwaggerApi.js
+++ b/src/api/SwaggerApi.js
@@ -1100,6 +1100,24 @@ export function useUndeployInDb(id, onError) {
   const boundMethod = useCallback(method.bind(null, { ioc_id: id }), [id]);
   return useAsync({ fcn: boundMethod, call: false, onError: onError });
 }
+
+export function unpackUpdateActiveDeploymentHost(ioc) {
+  return { ...ioc };
+}
+
+export function useUpdateActiveDeploymentHost(id, onError) {
+  const api = useContext(apiContext);
+  const method = useCallAndUnpack(
+    (body) =>
+      api.apis.IOCs.updateActiveDeploymentHost(
+        { ioc_id: id },
+        { requestBody: body }
+      ),
+    unpackUpdateActiveDeploymentHost
+  );
+  return useAsync({ fcn: method, call: false, onError: onError });
+}
+
 export function useAnnouncements() {
   const api = useContext(apiContext);
   const method = useCallAndUnpack(
diff --git a/src/components/IOC/ChangeHostAdmin.js b/src/components/IOC/ChangeHostAdmin.js
new file mode 100644
index 00000000..a8960522
--- /dev/null
+++ b/src/components/IOC/ChangeHostAdmin.js
@@ -0,0 +1,217 @@
+import React, { useState, useRef, useEffect, useCallback } from "react";
+import AccessControl from "../auth/AccessControl";
+import { SimpleAccordion } from "../common/Accordion/SimpleAccordion";
+import {
+  Button,
+  Typography,
+  Grid,
+  Tooltip,
+  TextField
+} from "@material-ui/core";
+import { SimpleModal } from "../../components/common/SimpleModal/SimpleModal";
+import { ConfirmationDialog } from "../dialog/ConfirmationDialog";
+import {
+  useUpdateActiveDeploymentHost,
+  useCSEntrySearch
+} from "../../api/SwaggerApi";
+import { Alert, Autocomplete } from "@material-ui/lab";
+import { useTypingTimer } from "../common/SearchBoxFilter/TypingTimer";
+import { transformHostQuery } from "../common/Helper";
+
+export default function ChangeHostAdmin({
+  ioc,
+  getIOC,
+  resetTab,
+  buttonDisabled
+}) {
+  const initHost = {
+    csEntryHost: {
+      fqdn: ioc.activeDeployment.host.fqdn,
+      id: ioc.activeDeployment.host.csEntryId
+    }
+  };
+
+  const [hosts, getHosts] = useCSEntrySearch();
+  const [host, setHost] = useState(initHost);
+  const [query, onHostKeyUp] = useTypingTimer({ interval: 500 });
+
+  function onError(message) {
+    setError(message);
+  }
+
+  const noModification = useCallback(
+    () => !host || host.csEntryHost.id === ioc.activeDeployment.host.csEntryId,
+    [host, ioc]
+  );
+
+  // for the dialog
+  const [error, setError] = useState();
+  const [adHocDialogOpen, setAdHocDialogOpen] = useState(false);
+  const [adHocDialogTitle, setAdHocDiatlogTitle] = useState();
+  const [adHocDialogDescription, setAdHocDialogDescription] = useState();
+  const callbackRef = useRef();
+
+  const [updatedIoc, updateHost] = useUpdateActiveDeploymentHost(
+    ioc.id,
+    onError
+  );
+  const [comment, setComment] = useState("");
+
+  useEffect(() => {
+    if (updatedIoc) {
+      getIOC();
+      resetTab();
+    }
+  }, [updatedIoc, getIOC, resetTab]);
+
+  useEffect(
+    () => getHosts({ query: transformHostQuery(`${query}`) }),
+    [query, getHosts]
+  );
+
+  const openModifyModal = () => {
+    setAdHocDiatlogTitle("Modifying deployment host");
+    setAdHocDialogDescription(
+      <>
+        <Typography style={{ display: "inline-block" }}>
+          Are you sure want to modify deployment host of &nbsp;
+        </Typography>
+        <Typography
+          style={{ fontFamily: "monospace", display: "inline-block" }}
+        >
+          {" "}
+          {ioc.namingName}?{" "}
+        </Typography>
+      </>
+    );
+    callbackRef.current = modifyHost;
+    setAdHocDialogOpen(true);
+  };
+
+  const modifyHost = () => {
+    updateHost({
+      hostCSEntryId: host.csEntryHost.id,
+      comment: comment
+    });
+  };
+
+  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={() => <></>}
+      >
+        <>
+          <SimpleModal
+            open={adHocDialogOpen}
+            setOpen={setAdHocDialogOpen}
+          >
+            <ConfirmationDialog
+              open={adHocDialogOpen}
+              setOpen={setAdHocDialogOpen}
+              title={adHocDialogTitle}
+              description={adHocDialogDescription}
+              callback={callbackRef.current}
+            />
+          </SimpleModal>
+
+          <SimpleAccordion
+            summary="Change deployment host"
+            defaultExpanded
+          >
+            <Grid
+              container
+              spacing={1}
+            >
+              {error ? (
+                <Grid
+                  item
+                  xs={12}
+                >
+                  <Alert severity="error">{error}</Alert>
+                </Grid>
+              ) : (
+                <></>
+              )}
+              <Grid
+                item
+                xs={12}
+              >
+                <Autocomplete
+                  autoHighlight
+                  id="host"
+                  options={hosts.hostList}
+                  defaultValue={initHost}
+                  getOptionLabel={(option) => {
+                    return option?.csEntryHost?.fqdn;
+                  }}
+                  renderInput={(params) => (
+                    <TextField
+                      {...params}
+                      label="host"
+                      variant="outlined"
+                      required
+                    />
+                  )}
+                  onChange={(event, value, reason) => {
+                    setHost(value);
+                  }}
+                  onInputChange={(event, value, reason) => {
+                    event && onHostKeyUp(event.nativeEvent);
+                  }}
+                  autoSelect
+                  filterOptions={(options, state) => options}
+                />
+              </Grid>
+              <Grid
+                item
+                xs={12}
+              >
+                <TextField
+                  id="comment"
+                  autoComplete="off"
+                  label="Deployment comment"
+                  variant="outlined"
+                  onChange={(event) => setComment(event.target.value)}
+                  fullWidth
+                />
+              </Grid>
+              <Grid
+                item
+                xs={12}
+              >
+                <Tooltip title={disabledButtonTitle}>
+                  <span>
+                    <Button
+                      color="primary"
+                      variant="contained"
+                      onClick={openModifyModal}
+                      disabled={
+                        buttonDisabled ||
+                        ioc.operationInProgress ||
+                        !ioc.activeDeployment ||
+                        noModification()
+                      }
+                    >
+                      CHANGE HOST
+                    </Button>
+                  </span>
+                </Tooltip>
+              </Grid>
+            </Grid>
+          </SimpleAccordion>
+        </>
+      </AccessControl>
+    </>
+  );
+}
diff --git a/src/components/IOC/IOCAdmin.js b/src/components/IOC/IOCAdmin.js
index da29d7ed..9d981f51 100644
--- a/src/components/IOC/IOCAdmin.js
+++ b/src/components/IOC/IOCAdmin.js
@@ -2,6 +2,7 @@ import React from "react";
 import AdministerUndeployment from "./AdministerUndeployment";
 import IOCDelete from "./IOCDelete";
 import IOCDetailAdmin from "./IOCDetailAdmin";
+import ChangeHostAdmin from "./ChangeHostAdmin";
 
 export default function IOCAdmin({ ioc, getIOC, resetTab, buttonDisabled }) {
   return (
@@ -12,6 +13,14 @@ export default function IOCAdmin({ ioc, getIOC, resetTab, buttonDisabled }) {
         resetTab={resetTab}
         buttonDisabled={buttonDisabled}
       />
+      {ioc.activeDeployment && (
+        <ChangeHostAdmin
+          ioc={ioc}
+          getIOC={getIOC}
+          resetTab={resetTab}
+          buttonDisabled={buttonDisabled}
+        />
+      )}
       <AdministerUndeployment
         ioc={ioc}
         buttonDisabled={buttonDisabled}
-- 
GitLab