From 92abb5e9e11328c813be0245f5b80f4cd70e227f Mon Sep 17 00:00:00 2001
From: Imre Toth <imre.toth@ess.eu>
Date: Thu, 11 Nov 2021 09:13:23 +0000
Subject: [PATCH] Icshwi 8184 ioc admin

---
 src/api/SwaggerApi.js                         |  21 ++++
 src/components/IOC/IOCAdmin.js                |  13 ++
 src/components/IOC/IOCDelete.js               |  70 +++++++++++
 src/components/IOC/IOCDetailAdmin.js          | 115 ++++++++++++++++++
 src/components/IOC/IOCService.js              |   4 +-
 .../ConfirmationDialog.js}                    |   2 +-
 src/views/IOC/IOCDetailsView.js               |  46 +++++--
 7 files changed, 258 insertions(+), 13 deletions(-)
 create mode 100644 src/components/IOC/IOCAdmin.js
 create mode 100644 src/components/IOC/IOCDelete.js
 create mode 100644 src/components/IOC/IOCDetailAdmin.js
 rename src/components/{IOC/ConfirmAdHocDialog.js => dialog/ConfirmationDialog.js} (95%)

diff --git a/src/api/SwaggerApi.js b/src/api/SwaggerApi.js
index f8498bca..56ee34bb 100644
--- a/src/api/SwaggerApi.js
+++ b/src/api/SwaggerApi.js
@@ -558,4 +558,25 @@ export function useAllowedGitProjects() {
   const api = useContext(apiContext);
   const method = callAndUnpack((repoUrl) => api.apis.Git.listProjects(), unpackAllowedGitProjects)
   return useAsync({ fcn: method, call: false, init: [] });
+}
+
+export function useDeleteIOC(id) {
+  const api = useContext(apiContext);
+  const method = callAndUnpack(api.apis.IOCs.deleteIoc);
+  return useAsync({ fcn: method.bind(null, {iocId: id}), call: false });
+}
+
+export function useUpdateIoc(id) {
+  const api = useContext(apiContext);
+  const method = callAndUnpack(
+    body => api.apis.IOCs.updateIoc({ iocId: id }, { requestBody: body }),
+    unpackUpdateIoc
+  );
+  return useAsync({ fcn: method, call: false });
+}
+
+export function unpackUpdateIoc(updateIoc) {
+  const d = { ...updateIoc };
+  console.log(d);
+  return d;
 }
\ No newline at end of file
diff --git a/src/components/IOC/IOCAdmin.js b/src/components/IOC/IOCAdmin.js
new file mode 100644
index 00000000..0b33b719
--- /dev/null
+++ b/src/components/IOC/IOCAdmin.js
@@ -0,0 +1,13 @@
+import React from 'react';
+import IOCDelete from './IOCDelete';
+import IOCDetailAdmin from './IOCDetailAdmin';
+
+export default function IOCAdmin({ ioc, getIOC, resetTab }) {
+
+    return (
+        <>
+            <IOCDetailAdmin ioc={ioc} getIOC={getIOC} resetTab={resetTab}/>
+            <IOCDelete ioc={ioc} />
+        </>
+    );
+}
\ No newline at end of file
diff --git a/src/components/IOC/IOCDelete.js b/src/components/IOC/IOCDelete.js
new file mode 100644
index 00000000..614319ed
--- /dev/null
+++ b/src/components/IOC/IOCDelete.js
@@ -0,0 +1,70 @@
+import React, { useState, useRef } from 'react';
+import { useHistory } from "react-router-dom";
+import { makeStyles } from '@material-ui/core/styles';
+import { Button, Typography } from "@material-ui/core";
+import { theme } from "../../Theme";
+import { useDeleteIOC } from '../../api/SwaggerApi';
+import { SimpleAccordion } from "../common/Accordion/SimpleAccordion";
+import { ConfirmationDialog } from "../dialog/ConfirmationDialog";
+import { SimpleModal } from "../../components/common/SimpleModal/SimpleModal";
+
+const useStyles = makeStyles({
+    deleteButton: {
+        backgroundColor: '#aa2e25',
+        color: '#FFFFFF',
+        "&:disabled": {
+            backgroundColor: '#8d8d8d',
+            color: '#FFFFFF',
+        },
+        "&:hover": {
+            backgroundColor: '#6c0000',
+            color: '#FFFFFF',
+        }
+    },
+});
+
+export default function IOCDelete({ ioc }) {
+    const classes = useStyles(theme);
+
+    const history = useHistory();
+
+    //for the dialog
+    const [adHocDialogOpen, setAdHocDialogOpen] = useState(false);
+    const [adHocDialogTitle, setAdHocDiatlogTitle] = useState();
+    const [adHocDialogDescription, setAdHocDialogDescription] = useState();
+    const callbackRef = useRef();
+
+    const [, deleteIOC] = useDeleteIOC(ioc.id);
+
+    //Setting up dialog properties
+    const openDeleteModal = () => {
+        setAdHocDiatlogTitle("Deleting IOC");
+        setAdHocDialogDescription(
+            <>
+                <Typography style={{ display: 'inline-block' }}>Are you sure want to delete &nbsp;</Typography>
+                <Typography style={{ fontFamily: "monospace", display: 'inline-block' }}> {ioc.namingName}? </Typography>
+            </>);
+        callbackRef.current = deleteIoc;
+        setAdHocDialogOpen(true);
+    }
+
+    //what to do when deleting IOC
+    const deleteIoc = async () => {
+
+        await deleteIOC();
+        history.goBack();
+    }
+
+
+    return (
+        <>
+            <SimpleModal open={adHocDialogOpen} setOpen={setAdHocDialogOpen}>
+                <ConfirmationDialog open={adHocDialogOpen} setOpen={setAdHocDialogOpen} title={adHocDialogTitle} description={adHocDialogDescription} callback={callbackRef.current} />
+            </SimpleModal>
+
+            <SimpleAccordion summary="Delete IOC" defaultExpanded>
+                <Button className={classes.deleteButton} onClick={openDeleteModal}>Delete IOC</Button>
+            </SimpleAccordion>
+        </>
+    );
+}
\ No newline at end of file
diff --git a/src/components/IOC/IOCDetailAdmin.js b/src/components/IOC/IOCDetailAdmin.js
new file mode 100644
index 00000000..34ed4801
--- /dev/null
+++ b/src/components/IOC/IOCDetailAdmin.js
@@ -0,0 +1,115 @@
+import React, { useState, useEffect, useRef } from 'react';
+import { SimpleAccordion } from "../common/Accordion/SimpleAccordion";
+import { Button, makeStyles, TextField, Typography } from "@material-ui/core";
+import { Autocomplete } from "@material-ui/lab";
+import { useAllowedGitProjects, useNamingNames, useUpdateIoc } from "../../api/SwaggerApi";
+import { useTypingTimer } from "../common/SearchBoxFilter/TypingTimer";
+import { ConfirmationDialog } from "../dialog/ConfirmationDialog";
+import { SimpleModal } from "../../components/common/SimpleModal/SimpleModal";
+
+const useStyles = makeStyles((theme) => ({
+    textField: {
+        marginBottom: theme.spacing(1),
+    },
+}));
+
+export default function IOCDetailAdmin({ ioc, getIOC, resetTab }) {
+    const classes = useStyles();
+
+    const [gitUrl, setGitUrl] = useState(ioc.git);
+    const [allowedGitProjects, getAllowedGitProjects] = useAllowedGitProjects();
+    const [nameQuery, onNameKeyUp] = useTypingTimer({ interval: 500 });
+    const [names, getNames] = useNamingNames();
+    const [name, setName] = useState({ id: ioc.latestVersion.externalNameId, description: ioc.description, name: ioc.latestVersion.namingName });
+    const [owner, setOwner] = useState(ioc.owner);
+
+    //for the dialog
+    const [adHocDialogOpen, setAdHocDialogOpen] = useState(false);
+    const [adHocDialogTitle, setAdHocDiatlogTitle] = useState();
+    const [adHocDialogDescription, setAdHocDialogDescription] = useState();
+    const callbackRef = useRef();
+
+    const [uioc, actionUpdateIoc] = useUpdateIoc(ioc.id);
+
+    useEffect(() => {
+        getAllowedGitProjects();
+    }, [getAllowedGitProjects]);
+
+    useEffect(() => getNames(nameQuery), [nameQuery, getNames]);
+
+    //when user clicks Submit button a dialog should open
+    const onSubmit = (event) => {
+        event.preventDefault();
+
+        openModifyModal();
+    }
+
+    //Setting up dialog properties
+    const openModifyModal = () => {
+        setAdHocDiatlogTitle("Modifying IOC");
+        setAdHocDialogDescription(
+            <>
+                <Typography style={{ display: 'inline-block' }}>Are you sure want to modify &nbsp;</Typography>
+                <Typography style={{ fontFamily: "monospace", display: 'inline-block' }}> {ioc.namingName}? </Typography>
+            </>);
+        callbackRef.current = modifyIoc;
+        setAdHocDialogOpen(true);
+    }
+
+    //what to do when modifying IOC
+    const modifyIoc = () => {
+
+         actionUpdateIoc({
+            owner: owner,
+            sourceUrl: gitUrl,
+            externalNameId: name ? parseInt(name.id) : null
+        });
+    }
+
+    useEffect(() => 
+    {
+      if(uioc) {
+        getIOC();
+        resetTab();
+      }
+    }, [uioc, getIOC, resetTab]);
+
+    return (
+        <>
+            <SimpleModal open={adHocDialogOpen} setOpen={setAdHocDialogOpen}>
+                <ConfirmationDialog open={adHocDialogOpen} setOpen={setAdHocDialogOpen} title={adHocDialogTitle} description={adHocDialogDescription} callback={callbackRef.current} />
+            </SimpleModal>
+
+            <SimpleAccordion summary="Modify IOC" defaultExpanded>
+                <form onSubmit={onSubmit} style={{ width: "100%" }}>
+                    <Autocomplete
+                        className={classes.textField}
+                        autoHighlight
+                        id="namingName"
+                        options={names}
+                        defaultValue={name}
+                        getOptionLabel={(option) => { console.log(option?.name); return option?.name }}
+                        renderInput={(params) => <TextField {...params} label="IOC name" variant="outlined" required />}
+                        onChange={(event, value, reason) => setName(value)}
+                        onInputChange={(event, value, reason) => { event && onNameKeyUp(event.nativeEvent) }}
+                    />
+
+                    <Autocomplete
+                        className={classes.textField}
+                        autoHighlight
+                        id="gitUrl"
+                        options={allowedGitProjects}
+                        defaultValue={gitUrl}
+                        getOptionLabel={(option) => { return option }}
+                        onChange={(event, value, reason) => setGitUrl(value)}
+                        renderInput={(params) => <TextField {...params} label="Git repository" variant="outlined" fullWidth required />} />
+
+                    <TextField id="owner" label="Owner" variant="outlined" fullWidth required value={owner} onChange={(event) => setOwner(event.target.value)} />
+
+                    <br /><br />
+                    <Button color="primary" variant="contained" type="submit">Modify IOC</Button>
+                </form>
+            </SimpleAccordion>
+        </>
+    )
+}
\ No newline at end of file
diff --git a/src/components/IOC/IOCService.js b/src/components/IOC/IOCService.js
index 2e14c67f..f523e4dc 100644
--- a/src/components/IOC/IOCService.js
+++ b/src/components/IOC/IOCService.js
@@ -4,7 +4,7 @@ import React, { useState, useEffect, useRef, useContext } from "react";
 import { useStartIOC, useStopIOC } from "../../api/SwaggerApi";
 import { CommandJobStatus } from "./CommandJobStatus";
 import { SimpleModal } from "../../components/common/SimpleModal/SimpleModal";
-import { ConfirmAdHocDialog } from "./ConfirmAdHocDialog";
+import { ConfirmationDialog } from "../dialog/ConfirmationDialog";
 import { notificationContext } from "../../components/common/notification/Notifications";
 import { theme } from "../../Theme";
 
@@ -148,7 +148,7 @@ export function IOCService({ ioc, getIOC, ongoingCommand, getCommands }) {
   return (
     <>
       <SimpleModal open={adHocDialogOpen} setOpen={setAdHocDialogOpen}>
-        <ConfirmAdHocDialog open={adHocDialogOpen} setOpen={setAdHocDialogOpen} title={adHocDialogTitle} description={adHocDialogDescription} callback={callbackRef.current} />
+        <ConfirmationDialog open={adHocDialogOpen} setOpen={setAdHocDialogOpen} title={adHocDialogTitle} description={adHocDialogDescription} callback={callbackRef.current} />
       </SimpleModal>
 
       <Grid container spacing={1}>
diff --git a/src/components/IOC/ConfirmAdHocDialog.js b/src/components/dialog/ConfirmationDialog.js
similarity index 95%
rename from src/components/IOC/ConfirmAdHocDialog.js
rename to src/components/dialog/ConfirmationDialog.js
index 4994b55b..86432129 100644
--- a/src/components/IOC/ConfirmAdHocDialog.js
+++ b/src/components/dialog/ConfirmationDialog.js
@@ -8,7 +8,7 @@ const useStyles = makeStyles((theme) => ({
      }
  }));
 
-export function ConfirmAdHocDialog({ open, setOpen, title, description, callback }) {
+export function ConfirmationDialog({ open, setOpen, title, description, callback }) {
     const classes = useStyles();
 
     const handleClose = () => {
diff --git a/src/views/IOC/IOCDetailsView.js b/src/views/IOC/IOCDetailsView.js
index 219221fb..e7b0c743 100644
--- a/src/views/IOC/IOCDetailsView.js
+++ b/src/views/IOC/IOCDetailsView.js
@@ -5,6 +5,8 @@ import { useIOC } from "../../api/SwaggerApi";
 import { IOCLiveStatus } from "../../components/IOC/IOCLiveStatus";
 import { IOCManage } from "../../components/IOC/IOCManage";
 import { useHistory } from "react-router-dom";
+import IOCAdmin from "../../components/IOC/IOCAdmin";
+import AccessControl from "../../components/auth/AccessControl";
 
 export function IOCDetailsView({ id }) {
   const [selectedTab, setSelectedTab] = useState("Manage deployment");
@@ -28,6 +30,14 @@ export function IOCDetailsView({ id }) {
     history.goBack();
   };
 
+  function resetTab() {
+    if (ioc && ioc.activeDeployment) {
+      setSelectedTab("Live Status");
+    } else {
+      setSelectedTab("Manage deployment");
+    }
+  }
+
   return (
     <Paper>
       <Grid container spacing={1}>
@@ -38,20 +48,36 @@ export function IOCDetailsView({ id }) {
         </Grid>
         <Grid item xs={11}>
           <Grid container justify="center">
-            <Tabs
-              value={selectedTab}
-              onChange={handleTabChange}
-              indicatorColor="primary"
-              textColor="primary"
-            >
-              {ioc && ioc.activeDeployment && <Tab label={<Typography variant="h5">Live Status</Typography>} value="Live Status" />}
-              {ioc && <Tab label={<Typography variant="h5">Manage deployment</Typography>} value="Manage deployment" />}
-            </Tabs>
+            <AccessControl allowedRoles={["DeploymentToolAdmin"]}
+              renderNoAccess={() =>
+                <Tabs
+                  value={selectedTab}
+                  onChange={handleTabChange}
+                  indicatorColor="primary"
+                  textColor="primary"
+                >
+                  {ioc && ioc.activeDeployment && <Tab label={<Typography variant="h5">Live Status</Typography>} value="Live Status" />}
+                  {ioc && <Tab label={<Typography variant="h5">Manage deployment</Typography>} value="Manage deployment" />}
+                </Tabs>
+              }>
+                
+              <Tabs
+                value={selectedTab}
+                onChange={handleTabChange}
+                indicatorColor="primary"
+                textColor="primary"
+              >
+                {ioc && ioc.activeDeployment && <Tab label={<Typography variant="h5">Live Status</Typography>} value="Live Status" />}
+                {ioc && <Tab label={<Typography variant="h5">Manage deployment</Typography>} value="Manage deployment" />}
+                {ioc && <Tab label={<Typography variant="h5">IOC Admin</Typography>} value="IOC Admin" />}
+              </Tabs>
+            </AccessControl>
           </Grid>
         </Grid>
-        <Grid item xs={12} style={{paddingBottom: 0}}>
+        <Grid item xs={12} style={{ paddingBottom: 0 }}>
           {selectedTab === "Live Status" && <IOCLiveStatus ioc={ioc} getIOC={getIOC} />}
           {selectedTab === "Manage deployment" && <IOCManage ioc={ioc} getIOC={getIOC} />}
+          {selectedTab === "IOC Admin" && <IOCAdmin ioc={ioc} getIOC={getIOC} resetTab={resetTab}/>}
         </Grid>
       </Grid>
     </Paper>
-- 
GitLab