From 7b432a415fb0a0a2b0209bb506c1ac8c11007922 Mon Sep 17 00:00:00 2001
From: Imre Toth <imre.toth@ess.eu>
Date: Tue, 25 Jan 2022 11:03:04 +0000
Subject: [PATCH] Icshwi 7362 datatable operations on backend

---
 src/api/SwaggerApi.js                         | 129 ++++++++++++++----
 src/components/IOC/IOCCommandTable.js         |   9 +-
 src/components/IOC/IOCDeployDialog.js         |   2 +-
 src/components/IOC/IOCLiveStatus.js           |   8 +-
 src/components/IOC/IOCManage.js               |  39 +++++-
 src/components/IOC/IOCService.js              |  14 +-
 src/components/IOC/IOCTable.js                |  30 ++--
 src/components/common/Helper.js               |  20 +++
 src/components/common/table/CustomTable.js    |  21 ++-
 .../deployments/DeploymentsTable.js           |  14 +-
 src/components/host/HostTable.js              |  12 +-
 src/views/IOC/IOCDetailsView.js               |  26 +++-
 src/views/IOC/IOCListView.js                  |  43 ++++--
 src/views/deployments/DeploymentsView.js      |  76 ++++++++---
 src/views/home/HomeView.js                    |  45 ++++--
 src/views/host/HostDetailsView.js             |  31 ++++-
 src/views/host/HostListView.js                |  26 +++-
 17 files changed, 435 insertions(+), 110 deletions(-)

diff --git a/src/api/SwaggerApi.js b/src/api/SwaggerApi.js
index 800c7898..10fd1a8a 100644
--- a/src/api/SwaggerApi.js
+++ b/src/api/SwaggerApi.js
@@ -196,24 +196,40 @@ export function unpackIocInfo(ioc) {
   return unpackedIOC;
 }
 
+const emptyIocListResponse = {
+  totalCount: 0,
+    pageNumber: 0,
+    limit: 0,
+    iocList : []
+}
+
 export function unpackIOCList(iocs) {
-  console.log(iocs);
-  return iocs.iocList.map((ioc) => unpackIocInfo(ioc));
+  
+  let iocArray = iocs.iocList.map((ioc) => unpackIocInfo(ioc));
+
+  let unpackedIOCList = {
+    totalCount: iocs.totalCount,
+    pageNumber: iocs.pageNumber,
+    limit: iocs.limit,
+    iocList : iocArray
+  };
+
+  return unpackedIOCList;
 }
 
 export function useIOCList() {
   const api = useContext(apiContext);
   const method = callAndUnpack(api.apis.IOCs.listIocs, unpackIOCList);
-  return useAsync({ fcn: method, init: [] });
+  return useAsync({ fcn: method, init: emptyIocListResponse });
 }
 
 export function useIOCSearch() {
   const api = useContext(apiContext);
   const method = callAndUnpack(
-    (query) => api.apis.IOCs.listIocs({ query: query }),
+    (owner, query, page, limit) => api.apis.IOCs.listIocs({ owner: owner, query: query, page:page, limit: limit }),
     unpackIOCList
   );
-  return useAsync({ fcn: method, call: false, init: [] });
+  return useAsync({ fcn: method, call: false, init: emptyIocListResponse });
 }
 
 export function useIOC(id) {
@@ -238,17 +254,33 @@ export function unpackDeployment(deployment) {
 }
 
 export function unpackDeploymentList(deployments) {
-  console.log(deployments);
-  return deployments.deployments.map(d => unpackDeployment(d));
+  
+  let deploymentArr = deployments.deployments.map(d => unpackDeployment(d));
+  
+  let unpackedDeploymentList = {
+    totalCount: deployments.totalCount,
+    pageNumber: deployments.pageNumber,
+    limit: deployments.limit,
+    deploymentList : deploymentArr
+  };
+
+  return unpackedDeploymentList;
+}
+
+const emptyDeploymentListResponse = {
+  totalCount: 0,
+    pageNumber: 0,
+    limit: 0,
+    deploymentList : []
 }
 
 export function useDeploymentListForIOC() {
   const api = useContext(apiContext);
   const method = callAndUnpack(
-    (iocId) => api.apis.Deployments.listDeployments({ iocId: iocId }),
+    (iocId, page, limit) => api.apis.Deployments.listDeployments({ iocId: iocId, page: page, limit: limit }),
     unpackDeploymentList
   );
-  return useAsync({ fcn: method, call: false, init: [] });
+  return useAsync({ fcn: method, call: false, init: emptyDeploymentListResponse });
 }
 
 export function unpackCommand(command) {
@@ -257,14 +289,31 @@ export function unpackCommand(command) {
   return c;
 }
 
+const emptyCommandListResponse = {
+  totalCount: 0,
+    pageNumber: 0,
+    limit: 0,
+    commandList : []
+}
+
 export function unpackCommandList(commandList) {
-  return commandList.commands.map(c => unpackCommand(c));
+  let commandArr = commandList.commands.map(c => unpackCommand(c));
+
+  let unpackedCommandList = {
+    totalCount: commandList.totalCount,
+    pageNumber: commandList.pageNumber,
+    limit: commandList.limit,
+    commandList : commandArr
+  };
+
+  return unpackedCommandList;
 }
 
-export function useCommandList(deploymentId) {
+export function useCommandList() {
   const api = useContext(apiContext);
-  const method = callAndUnpack(api.apis.Deployments.listCommandsByDeployment, unpackCommandList)
-  return useAsync({ fcn: method.bind(null, { deploymentId : deploymentId  }), init: [] });
+  const method = callAndUnpack(
+    (deploymentId, page, limit) => api.apis.Deployments.listCommandsByDeployment({deploymentId : deploymentId, page: page, limit: limit}), unpackCommandList)
+  return useAsync({ fcn: method, call: false, init: emptyCommandListResponse });
 }
 
 export function useDeploymentSearch() {
@@ -273,7 +322,7 @@ export function useDeploymentSearch() {
     (query) => api.apis.Deployments.listDeployments({ query: query }),
     unpackDeploymentList
   );
-  return useAsync({ fcn: method, call: false, init: [] });
+  return useAsync({ fcn: method, call: false, init: emptyDeploymentListResponse });
 }
 
 export function useDeployment(id) {
@@ -368,30 +417,62 @@ export function unpackCSEntryHost(host) {
   return { ...host };
 }
 
+const emptyHostListResponse = {
+  totalCount: 0,
+    pageNumber: 0,
+    limit: 0,
+    hostList : []
+}
+
 export function unpackCSEntryHostList(hosts) {
-  return hosts.csEntryHosts.map(h => unpackCSEntryHost(h));
+  let hostArr = hosts.csEntryHosts.map(h => unpackCSEntryHost(h));
+  
+  let unpackedHostList = {
+    totalCount: hosts.totalCount,
+    pageNumber: hosts.pageNumber,
+    limit: hosts.limit,
+    hostList : hostArr
+  };
+
+  return unpackedHostList;
 }
 
 export function useCSEntrySearch() {
   const api = useContext(apiContext);
   const method = callAndUnpack(
-    (query) => api.apis.Hosts.listHosts({ query: query }),
+    (query, page, limit) => api.apis.Hosts.listHosts({ query: query, page: page, limit: limit }),
     unpackCSEntryHostList
   );
-  return useAsync({ fcn: method, call: false, init: [] });
+  return useAsync({ fcn: method, call: false, init: emptyHostListResponse });
+}
+
+const emptyHostIocListResponse = {
+  totalCount: 0,
+    pageNumber: 0,
+    limit: 0,
+    deployedList : []
 }
 
 export function unpackHostIOCList(iocs) {
-  console.log({ ...iocs });
-  const deployed = iocs.deployedIocs.map(ioc => unpackIocInfo(ioc))
-  const result = { deployed };
-  return result;
+  
+  const deployedArr = iocs.deployedIocs.map(ioc => unpackIocInfo(ioc))
+  
+  let unpackedHostIocList = {
+    totalCount: iocs.totalCount,
+    pageNumber: iocs.pageNumber,
+    limit: iocs.limit,
+    deployedList : deployedArr
+  };
+
+  return unpackedHostIocList;
 }
 
-export function useHostIOCList(id) {
+export function useHostIOCList() {
   const api = useContext(apiContext);
-  const method = callAndUnpack(api.apis.Hosts.findAssociatedIocsByHostId, unpackHostIOCList)
-  return useAsync({ fcn: method.bind(null, { hostCSEntryId: id }), init: { deployed: [], undeployed: [] } });
+  const method = callAndUnpack(
+    (params) => api.apis.Hosts.findAssociatedIocsByHostId({ hostCSEntryId: params.hostCSEntryId, page: params.page, limit: params.limit }), 
+    unpackHostIOCList);
+  return useAsync({ fcn: method, call: false, init: emptyHostIocListResponse });
 }
 
 export function unpackLogin(loginResponse) {
diff --git a/src/components/IOC/IOCCommandTable.js b/src/components/IOC/IOCCommandTable.js
index 70c2c116..0df7c5f9 100644
--- a/src/components/IOC/IOCCommandTable.js
+++ b/src/components/IOC/IOCCommandTable.js
@@ -19,8 +19,8 @@ const dateTemplate = (rowData) => {
 const columns = [
   { id: "status", label: 'Status', width: '10%' },
   { id: "type", label: 'Command', width: '10%' },
-  { id: "user", label: 'User', width: '40%', sortable: true },
-  { id: 'start', label: 'Timestamp', width: '40%', body: dateTemplate, sortable: true }
+  { id: "user", label: 'User', width: '40%', sortable: false },
+  { id: 'start', label: 'Timestamp', width: '40%', body: dateTemplate, sortable: false }
 ]
 
 function createTableRow(command) {
@@ -39,9 +39,10 @@ function createTableRow(command) {
   };
 }
 
-export function IOCCommandTable({ commands }) {
+export function IOCCommandTable({ commands, commandLazyParams, setCommandLazyParams, commandColumnSort, setCommandColumnSort }) {
   
   return (
-    <CustomTable columns={columns} rows={commands.map(command => createTableRow(command))} rowsPerPage={5} />
+    <CustomTable columns={columns} rows={commands.commandList.map(command => createTableRow(command))} totalCount={commands.totalCount}
+      lazyParams={commandLazyParams} setLazyParams={setCommandLazyParams} columnSort={commandColumnSort} setColumnSort={setCommandColumnSort} />
   );
 }
\ No newline at end of file
diff --git a/src/components/IOC/IOCDeployDialog.js b/src/components/IOC/IOCDeployDialog.js
index a3deb6a8..f9324055 100644
--- a/src/components/IOC/IOCDeployDialog.js
+++ b/src/components/IOC/IOCDeployDialog.js
@@ -72,7 +72,7 @@ export function IOCDeployDialog({ open, setOpen, submitCallback, hasActiveDeploy
             className={classes.textField}
             autoHighlight
             id="host"
-            options={hosts}
+            options={hosts.hostList}
             defaultValue = { init }
             getOptionLabel={option => {console.log(option); return option?.csEntryHost?.fqdn}}
             renderInput={(params) => <TextField {...params} label="host" variant="outlined" required/>}
diff --git a/src/components/IOC/IOCLiveStatus.js b/src/components/IOC/IOCLiveStatus.js
index 02ee70a7..6b7257d3 100644
--- a/src/components/IOC/IOCLiveStatus.js
+++ b/src/components/IOC/IOCLiveStatus.js
@@ -11,7 +11,8 @@ import { IOCService } from "./IOCService";
 import { IOCCommandTable } from "./IOCCommandTable";
 
 
-export function IOCLiveStatus({ ioc, ongoingCommand, commands, getCommands, buttonDisabled, setOperationQueued }) {
+export function IOCLiveStatus({ ioc, ongoingCommand, commands, getCommands, buttonDisabled, setOperationQueued, 
+  commandLazyParams, setCommandLazyParams, commandColumnSort, setCommandColumnSort }) {
   const liveIOC = { ...ioc };
   liveIOC.name = ioc.namingName;
   
@@ -25,7 +26,7 @@ export function IOCLiveStatus({ ioc, ongoingCommand, commands, getCommands, butt
       description,
       "Deployed on": <Typography><Link to={`/hosts/${ioc.activeDeployment?.host.csEntryId}`}>{ioc.activeDeployment?.host.fqdn}</Link></Typography>,
       "IOC Service Controls": showControlls ? <IOCService ioc={ioc} ongoingCommand={ongoingCommand} getCommands={getCommands} 
-        buttonDisabled={buttonDisabled} setOperationQueued={setOperationQueued} /> : "Can't be controlled, because IOC is not (yet) deployed succesfully",
+        buttonDisabled={buttonDisabled} setOperationQueued={setOperationQueued} commandColumnSort={commandColumnSort} commandLazyParams={commandLazyParams}/> : "Can't be controlled, because IOC is not (yet) deployed succesfully",
       /*"Open IOC host in CSentry": <a href={`https://csentry.esss.lu.se/network/hosts/view/${hostName}`} target="_blank" rel="noreferrer">{`https://csentry.esss.lu.se/network/hosts/view/${hostName}`}</a>,
       "Host status": status?.toLowerCase(),*/
     })
@@ -41,7 +42,8 @@ export function IOCLiveStatus({ ioc, ongoingCommand, commands, getCommands, butt
     <>
       <IOCDetails ioc={liveIOC} getSubset={getSubset} alert={<IOCAlerts ioc={liveIOC}/>}/>
       <SimpleAccordion summary="IOC Service Control log">
-        <IOCCommandTable commands={commands} />
+        <IOCCommandTable commands={commands} 
+        commandLazyParams={commandLazyParams} setCommandLazyParams={setCommandLazyParams} commandColumnSort={commandColumnSort} setCommandColumnSort={setCommandColumnSort}/>
       </SimpleAccordion>
       <SimpleAccordion summary="ProcServLog info" defaultExpanded>
         {iocHost && 
diff --git a/src/components/IOC/IOCManage.js b/src/components/IOC/IOCManage.js
index b8cbb341..2d520ea2 100644
--- a/src/components/IOC/IOCManage.js
+++ b/src/components/IOC/IOCManage.js
@@ -10,18 +10,50 @@ import IOCAlerts from "./IOCAlerts";
 import { Link } from 'react-router-dom';
 import { DeploymentsTable } from "../../components/deployments/DeploymentsTable";
 import { SimpleAccordion } from "../common/Accordion/SimpleAccordion";
+import { initRequestParams } from "../common/Helper";
 
 export function IOCManage({ ioc, getIOC, buttonDisabled }) {
   const [deployDialogOpen, setDeployDialogOpen] = useState(false);
   const [undeployDialogOpen, setUndeployDialogOpen] = useState(false);
   const [deployments, getDeployments] = useDeploymentListForIOC();
 
+  const [lazyParams, setLazyParams] = useState({
+    first: 0,
+    rows: 5,
+    page: 0
+  });
+  
+  const [columnSort, setColumnSort] = useState({
+    sortField: null,
+    sortOrder: null
+  });
+
   useEffect(() => 
     {
       if(ioc) {
-        getDeployments(`${ioc.id}`)
+        let requestParams = initRequestParams(lazyParams, null, columnSort);
+        
+        requestParams.iocId = ioc.id;
+        
+        if(columnSort.sortField === "start") {
+          requestParams.orderBy = "START_TIME";
+        }
+      
+        if(columnSort.sortField === "user") {
+          requestParams.orderBy = "CREATED_BY";
+        }
+      
+        if(columnSort.sortField === "ioc") {
+          requestParams.orderBy = "IOC_NAME";
+        }
+      
+        if(columnSort.sortField === "version") {
+          requestParams.orderBy = "GIT_REFERENCE";
+        }
+
+        getDeployments(requestParams);
       }
-    }, [ioc, getDeployments]);
+    }, [ioc, lazyParams, columnSort, getDeployments]);
 
   const closeDeployModal = () => {
     setDeployDialogOpen(false);
@@ -94,7 +126,8 @@ export function IOCManage({ ioc, getIOC, buttonDisabled }) {
           } 
         />
         <SimpleAccordion summary="Deployment log">
-          <DeploymentsTable deployments={deployments} rowsPerPage={5}/>
+          <DeploymentsTable deployments={deployments.deploymentList} totalCount={deployments.totalCount} 
+            lazyParams={lazyParams} setLazyParams={setLazyParams} columnSort={columnSort} setColumnSort={setColumnSort} />
         </SimpleAccordion>
         <SimpleModal open={deployDialogOpen} setOpen={setDeployDialogOpen}>
           <DeployIOC open={deployDialogOpen} setOpen={setDeployDialogOpen} submitCallback={closeDeployModal} init={formInit} hook={useUpdateAndDeployIoc.bind(null, ioc.id)}
diff --git a/src/components/IOC/IOCService.js b/src/components/IOC/IOCService.js
index 153b9a69..fc84341e 100644
--- a/src/components/IOC/IOCService.js
+++ b/src/components/IOC/IOCService.js
@@ -8,6 +8,7 @@ import { ConfirmationDialog } from "../dialog/ConfirmationDialog";
 import { notificationContext } from "../../components/common/notification/Notifications";
 import { Alert } from "@material-ui/lab";
 import { theme } from "../../Theme";
+import { initRequestParams } from "../common/Helper";
 
 const useStyles = makeStyles({
   startButton: {
@@ -36,7 +37,7 @@ const useStyles = makeStyles({
   },
 });
 
-export function IOCService({ ioc, ongoingCommand, getCommands, buttonDisabled, setOperationQueued }) {
+export function IOCService({ ioc, ongoingCommand, getCommands, buttonDisabled, setOperationQueued, commandLazyParams, commandColumnSort }) {
   const classes = useStyles(theme);
 
   function onError(message) {
@@ -96,7 +97,10 @@ export function IOCService({ ioc, ongoingCommand, getCommands, buttonDisabled, s
     setInProgress(true);
     setOperationQueued(true);
     await startIOC();
-    getCommands();
+    let requestParams = initRequestParams(commandLazyParams, null, commandColumnSort);
+
+    requestParams.deploymentId = ioc.activeDeployment?.id;
+    getCommands(requestParams);
   }
 
   const stop = async () => {
@@ -105,7 +109,11 @@ export function IOCService({ ioc, ongoingCommand, getCommands, buttonDisabled, s
     setInProgress(true);
     setOperationQueued(true);
     await stopIOC();
-    getCommands();
+
+    let requestParams = initRequestParams(commandLazyParams, null, commandColumnSort);
+
+    requestParams.deploymentId = ioc.activeDeployment?.id;
+    getCommands(requestParams);
   }
 
   const openStartModal = () => {
diff --git a/src/components/IOC/IOCTable.js b/src/components/IOC/IOCTable.js
index f887c20e..a4d7f360 100644
--- a/src/components/IOC/IOCTable.js
+++ b/src/components/IOC/IOCTable.js
@@ -8,24 +8,24 @@ import { IOCStatusIcon } from './IOCIcons';
 const ownIocsColumns = [
   { id: "status", label: 'Status', width: '8%' },
   { id: "namingName", label: 'IOC name', width: '20%', sortable: true },
-  { id: "host", label: 'Host', width: '15%', sortable: true },
-  { id: "network", label: 'Network', width: '15%', sortable: true },
+  { id: "host", label: 'Host', width: '15%', sortable: false },
+  { id: "network", label: 'Network', width: '15%', sortable: false },
   { id: "sourceVersion", label: 'Git reference', width: '42%', sortable: true },
 ]
 
 const exploreIocsColumns = [
   { id: "status", label: 'Status', width: '8%' },
   { id: "namingName", label: 'IOC name', width: '20%', sortable: true },
-  { id: "host", label: 'Host', width: '15%', sortable: true },
-  { id: "network", label: 'Network', width: '15%', sortable: true },
+  { id: "host", label: 'Host', width: '15%', sortable: false },
+  { id: "network", label: 'Network', width: '15%', sortable: false },
   { id: "owner", label: 'Owner', width: '10%', sortable: true },
   { id: "sourceVersion", label: 'Git reference', width: '32%', sortable: true },
 ]
 
 const hostDetailsColumns = [
   { id: "status", label: 'Status', width: '8%' },
-  { id: "name", label: 'Name', width: '30%', sortable: true },
-  { id: "sourceVersion", label: 'Git reference', width: '62%', sortable: true },
+  { id: "name", label: 'Name', width: '30%', sortable: false },
+  { id: "sourceVersion", label: 'Git reference', width: '62%', sortable: false },
 ]
 
 function createGitVersionField(version, shortVersion) {
@@ -94,7 +94,7 @@ function createTableRowForExploreIocs(ioc) {
   };
 }
 
-export function IOCTable({ iocs, rowType="own" }) {
+export function IOCTable({ iocs, rowType="own", totalCount, lazyParams, setLazyParams, columnSort, setColumnSort }) {
   const history = useHistory();
 
   const onRowClicked = (id) => {
@@ -105,17 +105,21 @@ export function IOCTable({ iocs, rowType="own" }) {
     <>
     {
       rowType === "host" ?
-      <CustomTable columns={hostDetailsColumns} rows={iocs.map(ioc => createTableRowForHostDetails(ioc))} handleRowClick={onRowClicked} />
+      <CustomTable columns={hostDetailsColumns} totalCount={totalCount} rows={iocs.map(ioc => createTableRowForHostDetails(ioc))} handleRowClick={onRowClicked} 
+      lazyParams={lazyParams} setLazyParams={setLazyParams} columnSort={columnSort} setColumnSort={setColumnSort} />
       : (rowType === "own" ?
-      <CustomTable columns={ownIocsColumns} rows={iocs.map(ioc => createTableRowForOwnIocs(ioc))} handleRowClick={onRowClicked} />
+      <CustomTable columns={ownIocsColumns} totalCount={totalCount} rows={iocs.map(ioc => createTableRowForOwnIocs(ioc))} handleRowClick={onRowClicked} 
+      lazyParams={lazyParams} setLazyParams={setLazyParams} columnSort={columnSort} setColumnSort={setColumnSort} />
       :
-      <CustomTable columns={exploreIocsColumns} rows={iocs.map(ioc => createTableRowForExploreIocs(ioc))} handleRowClick={onRowClicked} />)
+      <CustomTable columns={exploreIocsColumns} totalCount={totalCount} rows={iocs.map(ioc => createTableRowForExploreIocs(ioc))} handleRowClick={onRowClicked} 
+      lazyParams={lazyParams} setLazyParams={setLazyParams} columnSort={columnSort} setColumnSort={setColumnSort} />)
     }
     </>
   );
 }
 
-export function SearchableIOCTable({ iocs, setQuery, rowType }) {
+export function SearchableIOCTable({ iocs, totalCount, setQuery, rowType, lazyParams, setLazyParams,
+  columnSort, setColumnSort}) {
   const filter = (search) => {
     setQuery(search.toLowerCase());
     return (ioc) => {
@@ -123,7 +127,9 @@ export function SearchableIOCTable({ iocs, setQuery, rowType }) {
     }
   }
 
-  const renderFilteredIOCs = (filteredIOCs) => <IOCTable iocs={filteredIOCs} rowType={rowType}/>;
+  const renderFilteredIOCs = (filteredIOCs) => 
+    <IOCTable iocs={filteredIOCs} rowType={rowType} totalCount={totalCount} 
+    lazyParams={lazyParams} setLazyParams={setLazyParams} columnSort={columnSort} setColumnSort={setColumnSort}/>;
 
   return (
     <SearchBoxFilter items={iocs} filter={filter} render={renderFilteredIOCs} />
diff --git a/src/components/common/Helper.js b/src/components/common/Helper.js
index 6802980f..6789fda5 100644
--- a/src/components/common/Helper.js
+++ b/src/components/common/Helper.js
@@ -115,3 +115,23 @@ export function applicationSubTitle() {
 
   return '';
 }
+
+export function initRequestParams(lazyParams, filter, columnSort) {
+  let requestParams = {
+    page: lazyParams.page, 
+    limit: lazyParams.rows
+  }
+  if ((filter != null) && filter) {
+    requestParams.query = filter;
+  }
+
+  if(columnSort) {
+    if(columnSort.sortOrder === 1) {
+      requestParams.isAsc = true;
+    } else {
+      requestParams.isAsc = false;
+    }
+  }
+
+  return requestParams;
+}
diff --git a/src/components/common/table/CustomTable.js b/src/components/common/table/CustomTable.js
index 3833ee30..1e9188e2 100644
--- a/src/components/common/table/CustomTable.js
+++ b/src/components/common/table/CustomTable.js
@@ -10,8 +10,10 @@ import 'primeflex/primeflex.css';
 import './CustomTable.css';
 
 export function CustomTable(props) {
-  const {columns, rows, handleRowClick, rowsPerPage} = props;
+  const {columns, rows, handleRowClick, totalCount, lazyParams, setLazyParams, columnSort, setColumnSort} = props;
 
+//const [loading, setLoading] = useState(false);
+  
   const dynamicColumns = columns.map((col,i) => {
         return <Column key={col.id} field={col.id} header={col.label} style={{width: col.width}} body={col.body} sortable={col.sortable}/>;
     });
@@ -20,6 +22,14 @@ export function CustomTable(props) {
     handleRowClick(event.data.id);
   };
 
+  const onPage = (event) => {
+    setLazyParams(event);
+  }
+
+  const onSort = (event) => {
+    setColumnSort(event);
+  }
+
   const rowClassName = (rowData) => {
 
     var resultObject = {};
@@ -48,6 +58,12 @@ export function CustomTable(props) {
       <Paper>
         <DataTable
           className="p-ccce-custom-table"
+          lazy
+          first={lazyParams.first}
+          onPage={onPage}
+          onSort={onSort}
+          sortField={columnSort.sortField} 
+          sortOrder={columnSort.sortOrder}
           value={rows}
           stripedRows
           scrollable 
@@ -55,10 +71,11 @@ export function CustomTable(props) {
           columnResizeMode="fit"
           paginator
           paginatorTemplate="CurrentPageReport FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown"
-          currentPageReportTemplate="Showing {first} to {last} of {totalRecords}" rows={rowsPerPage ?? 10} rowsPerPageOptions={[5,10,20,50]}
+          currentPageReportTemplate="Showing {first} to {last} of {totalRecords}" rows={lazyParams.rows} rowsPerPageOptions={[5,10,20,50]}
           rowHover
           onRowClick={(event) => handleClick(event)}
           rowClassName={rowClassName}
+          totalRecords={totalCount}
         >
           {dynamicColumns}
         </DataTable>
diff --git a/src/components/deployments/DeploymentsTable.js b/src/components/deployments/DeploymentsTable.js
index ce372ce3..f6741f09 100644
--- a/src/components/deployments/DeploymentsTable.js
+++ b/src/components/deployments/DeploymentsTable.js
@@ -21,8 +21,8 @@ const columns = [
   { id: 'type', label: 'Type', width: '4%'},
   { id: 'status', label: 'Status', width: '5%'},
   { id: 'ioc', label: 'IOC Name', width: '14%', sortable: true },
-  { id: 'host', label: 'Host', width: '13%', sortable: true },
-  { id: 'network', label: 'Network', width: '11%', sortable: true },
+  { id: 'host', label: 'Host', width: '13%', sortable: false },
+  { id: 'network', label: 'Network', width: '11%', sortable: false },
   { id: 'user', label: 'User', width: '12%', sortable: true },
   { id: 'version', label: 'Git reference', width: '26%', sortable: true },
   { id: 'start', label: 'Start date', width: '15%', body: dateTemplate, sortable: true }
@@ -58,7 +58,7 @@ function createTableRow(deployment) {
   };
 }
 
-export function DeploymentsTable({deployments, rowsPerPage}) {
+export function DeploymentsTable({deployments, totalCount, lazyParams, setLazyParams, columnSort, setColumnSort}) {
   const history = useHistory();
 
   const onRowClicked = (id) => {
@@ -66,11 +66,12 @@ export function DeploymentsTable({deployments, rowsPerPage}) {
   };
 
   return (
-    <CustomTable columns={columns} rows={deployments.map(deployment => createTableRow(deployment))} handleRowClick={onRowClicked} rowsPerPage={rowsPerPage}/>
+    <CustomTable columns={columns} rows={deployments.map(deployment => createTableRow(deployment))} handleRowClick={onRowClicked}
+      totalCount={totalCount} lazyParams={lazyParams} setLazyParams={setLazyParams} columnSort={columnSort} setColumnSort={setColumnSort} />
   );
 }
 
-export function SearchableDeploymentsTable({ deployments, setQuery }) {
+export function SearchableDeploymentsTable({ deployments, setQuery, totalCount, lazyParams, setLazyParams, columnSort, setColumnSort}) {
   const filter = (search) => {
     setQuery(search.toLowerCase());
     return (item) => {
@@ -80,7 +81,8 @@ export function SearchableDeploymentsTable({ deployments, setQuery }) {
 
   const renderFilteredItems = (filteredDeployments) => {
     return (
-        <DeploymentsTable deployments={filteredDeployments}/>
+        <DeploymentsTable deployments={filteredDeployments} totalCount={totalCount} 
+          lazyParams={lazyParams} setLazyParams={setLazyParams} columnSort={columnSort} setColumnSort={setColumnSort}/>
       );
   }
 
diff --git a/src/components/host/HostTable.js b/src/components/host/HostTable.js
index 538dace7..092d0662 100644
--- a/src/components/host/HostTable.js
+++ b/src/components/host/HostTable.js
@@ -5,7 +5,6 @@ import { SearchBoxFilter } from "../common/SearchBoxFilter/SearchBoxFilter";
 import { useHistory } from 'react-router-dom';
 import { HostStatusIcon } from './HostIcons';
 
-
 const columns = [
     { id: 'bulb', label: 'Status', width: '6%' },
     { id: 'host', label: 'Host', width: '24%' },
@@ -44,8 +43,7 @@ export function createRow(hostContainer) {
 
 }
 
-
-export function HostsTable({ hosts }) {
+export function HostsTable({ hosts, totalCount, lazyParams, setLazyParams, columnSort, setColumnSort }) {
     const history = useHistory();
 
     console.log(hosts);
@@ -54,10 +52,11 @@ export function HostsTable({ hosts }) {
         history.push(`/hosts/${id}`);
     };
 
-    return <CustomTable columns={columns} rows={hosts.map(host => createRow(host))} handleRowClick={onRowClicked} />;
+    return <CustomTable columns={columns} rows={hosts.map(host => createRow(host))} handleRowClick={onRowClicked} totalCount={totalCount}
+        lazyParams={lazyParams} setLazyParams={setLazyParams} columnSort={columnSort} setColumnSort={setColumnSort} />;
 }
 
-export default function HostTable({ hosts, setQuery }) {
+export default function HostTable({ hosts, setQuery, totalCount, lazyParams, setLazyParams, columnSort, setColumnSort }) {
     const filter = (search) => {
         setQuery(search.toLowerCase());
         return (hostContainer) => {
@@ -65,7 +64,8 @@ export default function HostTable({ hosts, setQuery }) {
         }
     }
 
-    const renderFilteredHosts = (filteredHosts) => <HostsTable hosts={filteredHosts} />;
+    const renderFilteredHosts = (filteredHosts) => <HostsTable hosts={filteredHosts} totalCount={totalCount} 
+        lazyParams={lazyParams} setLazyParams={setLazyParams} columnSort={columnSort} setColumnSort={setColumnSort}/>;
 
     return (
         <SearchBoxFilter items={hosts} filter={filter} render={renderFilteredHosts} />
diff --git a/src/views/IOC/IOCDetailsView.js b/src/views/IOC/IOCDetailsView.js
index af24534f..9cb037ab 100644
--- a/src/views/IOC/IOCDetailsView.js
+++ b/src/views/IOC/IOCDetailsView.js
@@ -7,6 +7,7 @@ import { IOCManage } from "../../components/IOC/IOCManage";
 import { useHistory } from "react-router-dom";
 import IOCAdmin from "../../components/IOC/IOCAdmin";
 import AccessControl from "../../components/auth/AccessControl";
+import { initRequestParams } from "../../components/common/Helper";
 
 export function IOCDetailsView({ ioc, getIOC }) {
   console.log(ioc);
@@ -14,10 +15,21 @@ export function IOCDetailsView({ ioc, getIOC }) {
   const [firstTime, setFirstTime] = useState(true);
   const [buttonDisabled, setButtonDisabled] = useState(false);
   const history = useHistory();
-  const [commands, getCommands] = useCommandList(ioc.activeDeployment?.id);
+  const [commands, getCommands] = useCommandList();
   const [ongoingCommand, setOngoingCommand] = useState(null);
   const [operationQueued, setOperationQueued] = useState(false);
 
+  const [commandLazyParams, setCommandLazyParams] = useState({
+    first: 0,
+    rows: 5,
+    page: 0
+  });
+  
+  const [commandColumnSort, setCommandColumnSort] = useState({
+    sortField: null,
+    sortOrder: null
+  });
+
   useEffect(() => {
     if (commands && commands.length > 0 && !["successful", "failed"].includes(commands[0].status?.toLowerCase())) {
       setOngoingCommand(commands[0]);
@@ -64,6 +76,15 @@ export function IOCDetailsView({ ioc, getIOC }) {
     }
   }, [ioc, firstTime]);
 
+  useEffect(() => {
+    let requestParams = initRequestParams(commandLazyParams, null, commandColumnSort);
+
+    requestParams.deploymentId = ioc.activeDeployment?.id;
+
+    getCommands(requestParams);
+
+  }, [getCommands, commandLazyParams, commandColumnSort, ioc])
+
   const handleClick = () => {
     history.goBack();
   };
@@ -116,7 +137,8 @@ export function IOCDetailsView({ ioc, getIOC }) {
         </Grid>
         <Grid item xs={12} style={{ paddingBottom: 0 }}>
           {selectedTab === "Live Status" && <IOCLiveStatus ioc={ioc} getIOC={getIOC} ongoingCommand={ongoingCommand} commands={commands} getCommands={getCommands}
-              buttonDisabled={buttonDisabled} setOperationQueued={setOperationQueued} />}
+              buttonDisabled={buttonDisabled} setOperationQueued={setOperationQueued} 
+              commandLazyParams={commandLazyParams} setCommandLazyParams={setCommandLazyParams} commandColumnSort={commandColumnSort} setCommandColumnSort={setCommandColumnSort} />}
           {selectedTab === "Manage deployment" && <IOCManage ioc={ioc} getIOC={getIOC} buttonDisabled={buttonDisabled} />}
           {selectedTab === "IOC Admin" && <IOCAdmin ioc={ioc} getIOC={getIOC} resetTab={resetTab} buttonDisabled={buttonDisabled}/>}
         </Grid>
diff --git a/src/views/IOC/IOCListView.js b/src/views/IOC/IOCListView.js
index 39954d9e..877927c9 100644
--- a/src/views/IOC/IOCListView.js
+++ b/src/views/IOC/IOCListView.js
@@ -6,6 +6,7 @@ import { SearchableIOCList } from "../../components/IOC/IOCList";
 import { SearchableIOCTable } from "../../components/IOC/IOCTable";
 import { useIOCSearch } from "../../api/SwaggerApi";
 import { makeStyles } from '@material-ui/core/styles';
+import { initRequestParams } from "../../components/common/Helper";
 
 const useStyles = makeStyles((theme) => ({
   root: {
@@ -18,26 +19,50 @@ export function IOCListView() {
   const [query, setQuery] = useState();
   const classes = useStyles();
 
-  useEffect(() => getIocs(`${query}`), [query, getIocs]);
+  const [lazyParams, setLazyParams] = useState({
+    first: 0,
+    rows: 10,
+    page: 0
+  });
+  
+  const [columnSort, setColumnSort] = useState({
+    sortField: null,
+    sortOrder: null
+  });
 
+  
   console.log("rendering Explore IOCs")
 
+  useEffect(() => {
+    let requestParams = initRequestParams(lazyParams, query, columnSort);
+
+    if(columnSort.sortField === "owner") {
+      requestParams.orderBy = "OWNER";
+    }
+  
+    if(columnSort.sortField === "namingName") {
+      requestParams.orderBy = "IOC_NAME";
+    }
+  
+    if(columnSort.sortField === "sourceVersion") {
+      requestParams.orderBy = "GIT_REFERENCE";
+    }
+
+    getIocs(requestParams);
+
+  }, [getIocs, lazyParams, columnSort, query])
+
   const title = "Explore IOCs";
   useGlobalAppBar(title);
 
-  function preProcess(iocs) {
-    console.log(iocs);
-    const abcIOCs = iocs.sort((a, b) => a.namingName.localeCompare(b.namingName));
-    return abcIOCs;
-  }
-
   let content = (
     <>
       <Hidden smUp>
-        <SearchableIOCList iocs={preProcess(iocs)} setQuery={setQuery}/>
+        <SearchableIOCList iocs={iocs.iocList} setQuery={setQuery}/>
       </Hidden>
       <Hidden xsDown>
-        <SearchableIOCTable iocs={preProcess(iocs)} setQuery={setQuery} rowType="explore"/>
+        <SearchableIOCTable iocs={iocs.iocList} setQuery={setQuery} rowType="explore" 
+          lazyParams={lazyParams} setLazyParams={setLazyParams} columnSort={columnSort} setColumnSort={setColumnSort} totalCount={iocs.totalCount} />
       </Hidden>
     </>
   );
diff --git a/src/views/deployments/DeploymentsView.js b/src/views/deployments/DeploymentsView.js
index 4fe917e2..0b7971b0 100644
--- a/src/views/deployments/DeploymentsView.js
+++ b/src/views/deployments/DeploymentsView.js
@@ -1,4 +1,4 @@
-import React, { useContext, useState, useEffect } from 'react';
+import React, { useContext, useState } from 'react';
 import { makeStyles } from '@material-ui/core/styles';
 import { Paper, Grid, FormControlLabel, Switch, Hidden, Typography } from '@material-ui/core';
 import Tabs from '@material-ui/core/Tabs';
@@ -6,6 +6,8 @@ import Tab from '@material-ui/core/Tab';
 import { SearchableDeploymentsTable } from "../../components/deployments/DeploymentsTable";
 import { SearchableDeploymentsList } from "../../components/deployments/DeploymentsList";
 import { useDeploymentSearch, userContext } from '../../api/SwaggerApi';
+import { initRequestParams } from '../../components/common/Helper';
+import { useEffect } from 'react';
 
 const useStyles = makeStyles((theme) => ({
   root: {
@@ -27,29 +29,25 @@ export function DeploymentsView() {
   const [selectedTab, setSelectedTab] = useState(0);
   const [ownOnly, setOwnOnly] = useState(false);
   const {user} = useContext(userContext);
-
-  useEffect(() => getDeployments(`${query}`), [query, getDeployments]);
+  const [deploymentStatus, setDeploymentStatus] = useState(null);
 
   console.log(deployments);
-  
-  function performFilter(tab, own, deploymentList) {
-    const prefiltered = own ? deploymentList.filter(deployment => deployment.createdBy === user.loginName) : deployments;
+
+  const handleTabChange = (event, tab) => {
+    setSelectedTab(tab);
+
     if (tab === 0) {
-      return prefiltered;
+      setDeploymentStatus(null);
     }
     else if (tab === 1) {
-      return prefiltered.filter(deployment => deployment.status === "RUNNING");
+      setDeploymentStatus("RUNNING");
     }
     else if (tab === 2) {
-      return prefiltered.filter(deployment => deployment.status !== "RUNNING" && deployment.status !== "QUEUED");
+      setDeploymentStatus("FINISHED");
     }
     else if (tab === 3) {
-      return prefiltered.filter(deployment => deployment.status === "QUEUED");
+      setDeploymentStatus("QUEUED");
     }
-  }
-
-  const handleTabChange = (event, tab) => {
-    setSelectedTab(tab);
   };
 
   const handleChangeOwn = (event) => {
@@ -57,13 +55,59 @@ export function DeploymentsView() {
     setOwnOnly(own);
   };
 
+  const [lazyParams, setLazyParams] = useState({
+    first: 0,
+    rows: 10,
+    page: 0
+  });
+  
+  const [columnSort, setColumnSort] = useState({
+    sortField: null,
+    sortOrder: null
+  });
+
+
+  useEffect(() => {
+
+    let requestParams = initRequestParams(lazyParams, query, columnSort);
+
+    if(ownOnly) {
+      requestParams.user = user?.loginName;
+    }
+  
+    if(columnSort.sortField === "start") {
+      requestParams.orderBy = "START_TIME";
+    }
+  
+    if(columnSort.sortField === "user") {
+      requestParams.orderBy = "CREATED_BY";
+    }
+  
+    if(columnSort.sortField === "ioc") {
+      requestParams.orderBy = "IOC_NAME";
+    }
+  
+    if(columnSort.sortField === "version") {
+      requestParams.orderBy = "GIT_REFERENCE";
+    }
+  
+    if(deploymentStatus) {
+      requestParams.status = deploymentStatus;
+    }
+
+    getDeployments(requestParams);
+
+  }, [getDeployments, lazyParams, query, columnSort, user, deploymentStatus, ownOnly])
+
   const content = (
     <>
       <Hidden smUp>
-        <SearchableDeploymentsList deployments={performFilter(selectedTab, ownOnly, deployments)} setQuery={setQuery}/>
+        <SearchableDeploymentsList deployments={deployments.deploymentList} setQuery={setQuery}/>
       </Hidden>
       <Hidden xsDown>
-        <SearchableDeploymentsTable deployments={performFilter(selectedTab, ownOnly, deployments)} setQuery={setQuery}/>
+        <SearchableDeploymentsTable
+        deployments={deployments.deploymentList} setQuery={setQuery}
+          totalCount={deployments.totalCount} lazyParams={lazyParams} setLazyParams={setLazyParams} columnSort={columnSort} setColumnSort={setColumnSort}/>
       </Hidden>
     </>
   );
diff --git a/src/views/home/HomeView.js b/src/views/home/HomeView.js
index 25052d88..19c03c8c 100644
--- a/src/views/home/HomeView.js
+++ b/src/views/home/HomeView.js
@@ -7,6 +7,7 @@ import { SearchableIOCTable } from "../../components/IOC/IOCTable";
 import { SimpleModal } from "../../components/common/SimpleModal/SimpleModal";
 import { useCreateIOC, useIOCSearch, userContext } from "../../api/SwaggerApi";
 import { makeStyles } from '@material-ui/core/styles';
+import { initRequestParams } from "../../components/common/Helper";
 
 const useStyles = makeStyles((theme) => ({
   root: {
@@ -21,30 +22,56 @@ export function HomeView() {
   const {user} = useContext(userContext);
   const classes = useStyles();
 
-  useEffect(() => getIocs(`${query}`), [query, getIocs]);
-
   console.log("rendering Own IOCs")
 
   const title = "CCCE / Home";
   useGlobalAppBar(title);
 
+  const [lazyParams, setLazyParams] = useState({
+    first: 0,
+    rows: 10,
+    page: 0
+  });
+  
+  const [columnSort, setColumnSort] = useState({
+    sortField: null,
+    sortOrder: null
+  });
+
   const closeModal = () => {
     setIOCFormOpen(false);
   }  
 
-  function preFilter(iocs) {
-    console.log(iocs);
-    const abcIOCs = iocs.filter((ioc) => ioc.owner === user?.loginName).sort((a, b) => a.namingName.localeCompare(b.namingName));
-    return abcIOCs;
-  }
+
+  useEffect(() => {
+    let requestParams = initRequestParams(lazyParams, query, columnSort);
+
+    requestParams.owner = user?.loginName;
+
+    if(columnSort.sortField === "owner") {
+      requestParams.orderBy = "OWNER";
+    }
+
+    if(columnSort.sortField === "namingName") {
+      requestParams.orderBy = "IOC_NAME";
+    }
+
+    if(columnSort.sortField === "sourceVersion") {
+      requestParams.orderBy = "GIT_REFERENCE";
+    }
+
+    getIocs(requestParams);
+  }, [getIocs, user, lazyParams, query, columnSort])
+
 
   let content = (
       <>
       <Hidden smUp>
-          <SearchableIOCList iocs={preFilter(iocs)} setQuery={setQuery}/>
+          <SearchableIOCList iocs={iocs.iocList} setQuery={setQuery}/>
       </Hidden>
       <Hidden xsDown>
-          <SearchableIOCTable iocs={preFilter(iocs)} setQuery={setQuery} rowType="own"/>
+          <SearchableIOCTable iocs={iocs.iocList} setQuery={setQuery} rowType="own" iocQuery={getIocs} searchFilter={query} queryType="ioc" searchForOwn={true}
+            totalCount={iocs.totalCount} lazyParams={lazyParams} setLazyParams={setLazyParams} columnSort={columnSort} setColumnSort={setColumnSort}/>
       </Hidden>
       </>
   );
diff --git a/src/views/host/HostDetailsView.js b/src/views/host/HostDetailsView.js
index f29a1abc..e7be26c8 100644
--- a/src/views/host/HostDetailsView.js
+++ b/src/views/host/HostDetailsView.js
@@ -19,7 +19,7 @@ import { SearchableIOCTable } from '../../components/IOC/IOCTable';
 import { KeyValueTable } from '../../components/common/KeyValueTable/KeyValueTable';
 import { LokiPanel } from '../../components/common/Loki/LokiPanel';
 import { useHistory } from "react-router-dom";
-import { formatDate } from '../../components/common/Helper';
+import { formatDate, initRequestParams } from '../../components/common/Helper';
 
 const useStyles = makeStyles((theme) => ({
     secondItem: {
@@ -29,15 +29,33 @@ const useStyles = makeStyles((theme) => ({
 
 export function HostDetailsView({ id }) {
     const [host] = useHost(id);
-    const [iocs] = useHostIOCList(id);
+    const [iocs, getIocs] = useHostIOCList();
     const [query, setQuery] = useState();
     const [deployedIocs, setDeployedIocs] = useState([]);
     const history = useHistory();
     const classes = useStyles();
-    console.log({ ...iocs });
-    console.log({ ...host });
 
-    useEffect(() => setDeployedIocs((iocs?.deployed ?? []).filter(ioc => ioc.namingName.toLowerCase().includes(query) ||
+    const [lazyParams, setLazyParams] = useState({
+        first: 0,
+        rows: 10,
+        page: 0
+      });
+      
+      const [columnSort, setColumnSort] = useState({
+        sortField: null,
+        sortOrder: null
+      });
+
+
+    useEffect(() => {
+        let requestParams = initRequestParams(lazyParams, null, columnSort);
+
+        requestParams.hostCSEntryId = id;
+
+        getIocs(requestParams);
+    }, [getIocs, lazyParams, columnSort, id])
+
+    useEffect(() => setDeployedIocs((iocs?.deployedList ?? []).filter(ioc => ioc.namingName.toLowerCase().includes(query) ||
         (ioc.host && ioc.host.toLowerCase().includes(query)) ||
         ioc.git.toLowerCase().includes(query) ||
         ioc.version.toLowerCase().includes(query) ||
@@ -68,7 +86,8 @@ export function HostDetailsView({ id }) {
                     <SearchableIOCList iocs={deployedIocs} setQuery={setQuery} />
                 </Hidden>
                 <Hidden xsDown>
-                    <SearchableIOCTable iocs={deployedIocs} setQuery={setQuery} rowType="host" />
+                    <SearchableIOCTable iocs={deployedIocs} setQuery={setQuery} rowType="host" 
+                        totalCount={iocs.totalCount} lazyParams={lazyParams} setLazyParams={setLazyParams} columnSort={columnSort} setColumnSort={setColumnSort}/>
                 </Hidden>
             </SimpleAccordion>
             <SimpleAccordion summary="Syslog info" defaultExpanded>
diff --git a/src/views/host/HostListView.js b/src/views/host/HostListView.js
index 8a140f6c..0968d939 100644
--- a/src/views/host/HostListView.js
+++ b/src/views/host/HostListView.js
@@ -1,4 +1,4 @@
-import React, { useEffect, useState } from "react";
+import React, { useState, useEffect } from "react";
 import {
     Paper,
     Grid,
@@ -11,6 +11,7 @@ import HostTable from '../../components/host/HostTable';
 import { useCSEntrySearch } from "../../api/SwaggerApi";
 import { useGlobalAppBar } from '../../components/navigation/GlobalAppBar/GlobalAppBar';
 import { makeStyles } from '@material-ui/core/styles';
+import { initRequestParams } from "../../components/common/Helper";
 
 const useStyles = makeStyles((theme) => ({
   root: {
@@ -25,15 +26,32 @@ export function HostListView() {
     const [query, setQuery] = useState();
     const classes = useStyles();
 
-    useEffect(() => getHosts(`fqdn:"${query}"`), [query, getHosts]);    
+    const [lazyParams, setLazyParams] = useState({
+        first: 0,
+        rows: 10,
+        page: 0
+      });
+      
+      const [columnSort, setColumnSort] = useState({
+        sortField: null,
+        sortOrder: null
+      });
 
+    useEffect(() => {
+        
+        let requestParams = initRequestParams(lazyParams, query, columnSort);
+
+        getHosts(requestParams);
+    }, [getHosts, lazyParams, query, columnSort])
+   
     const content = (
         <>
             <Hidden smUp>
-                <HostList hosts={hosts} setQuery={setQuery}/>
+                <HostList hosts={hosts.hostList} setQuery={setQuery}/>
             </Hidden>
             <Hidden xsDown>
-                <HostTable hosts={hosts} setQuery={setQuery}/>
+                <HostTable hosts={hosts.hostList} setQuery={setQuery} 
+                    totalCount={hosts.totalCount} lazyParams={lazyParams} setLazyParams={setLazyParams} columnSort={columnSort} setColumnSort={setColumnSort}/>
             </Hidden>
         </>
     );
-- 
GitLab