diff --git a/src/components/IOC/CreateIOC/CreateIOC.js b/src/components/IOC/CreateIOC/CreateIOC.js
index 67b04503d9b2af994029ad3325acb9c69cd3f87d..150cef1a42b96708977367940b242d04699904c9 100644
--- a/src/components/IOC/CreateIOC/CreateIOC.js
+++ b/src/components/IOC/CreateIOC/CreateIOC.js
@@ -14,18 +14,7 @@ import {
 } from "@mui/material";
 import { useAPIMethod } from "@ess-ics/ce-ui-common";
 import { apiContext } from "../../../api/DeployApi";
-
-const renderErrorMessage = (error) => {
-  const { response, status: requestStatus, message: requestMessage } = error;
-  const {
-    body: { description },
-    status: httpStatus
-  } = response;
-
-  return `${httpStatus ?? requestStatus ?? "unknown"}: ${
-    description ?? requestMessage ?? "An unknown error has occurred"
-  }`;
-};
+import { getErrorMessage } from "../../common/Helper";
 
 const createRequestParams = (query) => {
   return {
@@ -211,7 +200,7 @@ export function CreateIOC() {
           autoSelect
         />
         {error ? (
-          <Alert severity="error">{renderErrorMessage(error)}</Alert>
+          <Alert severity="error">{getErrorMessage(error)}</Alert>
         ) : (
           <></>
         )}
diff --git a/src/components/Job/JobTable/JobTable.js b/src/components/Job/JobTable/JobTable.js
index 8674a56460655502696f52eb2250867ea7aa8c0d..546525a6ef11325568f84d2dcf4032582d115593 100644
--- a/src/components/Job/JobTable/JobTable.js
+++ b/src/components/Job/JobTable/JobTable.js
@@ -1,18 +1,19 @@
-import React from "react";
+import React, { useState, useEffect } from "react";
 import { Table } from "@ess-ics/ce-ui-common";
 import { JobStatusColumn } from "./JobStatusColumn";
 import { JobSummaryColumn } from "./JobSummaryColumn";
 import { UserAvatar } from "../../common/User/UserAvatar";
 import { JobHostColumn } from "./JobHostColumn";
 
-const jobLogColumns = [
+const defaultColumns = [
   {
     field: "status",
     headerName: "Status"
   },
   {
     field: "job",
-    headerName: "Job"
+    headerName: "Job",
+    width: "100%"
   },
   {
     field: "host",
@@ -26,46 +27,50 @@ const jobLogColumns = [
   }
 ];
 
-const userPageJobLogColumns = [
-  ...jobLogColumns.filter((it) => it.field !== "user")
-];
-
-function createTableRow(job, colorStyle) {
-  return {
-    id: job.id,
-    status: <JobStatusColumn {...{ job }} />,
-    job: <JobSummaryColumn {...{ job, colorStyle }} />,
-    host: <JobHostColumn {...{ job }} />,
-    user: <UserAvatar username={job.createdBy} />
-  };
-}
+const shapeColumns = (customColumns) => {
+  return customColumns.map((column) => {
+    const mappedCol = defaultColumns.find((col) => col.field === column.field);
+    return mappedCol ? { ...mappedCol, ...column } : null;
+  });
+};
 
-function createTableRowJobLog(job) {
-  return createTableRow(job, "black");
-}
+const createTableRow = (job, colorStyle) => ({
+  id: job.id,
+  status: <JobStatusColumn {...{ job }} />,
+  job: <JobSummaryColumn {...{ job, colorStyle }} />,
+  host: <JobHostColumn {...{ job }} />,
+  user: <UserAvatar username={job.createdBy} />
+});
 
-export function JobTable({
+export const JobTable = ({
   jobs,
-  rowType = "jobLog",
+  customColumns,
   pagination,
   onPage,
   loading
-}) {
-  const tableTypeSpecifics = {
-    jobLog: [jobLogColumns, createTableRowJobLog],
-    userPageJobLog: [userPageJobLogColumns, createTableRowJobLog]
-  };
+}) => {
+  const [columns, setColumns] = useState(null);
 
-  const [columns, createRow] = tableTypeSpecifics[rowType];
+  useEffect(() => {
+    if (customColumns) {
+      setColumns(shapeColumns(customColumns));
+    } else {
+      setColumns(defaultColumns);
+    }
+  }, [customColumns, setColumns]);
 
   return (
-    <Table
-      columns={columns}
-      rows={jobs?.map((job) => createRow(job))}
-      pagination={pagination}
-      onPage={onPage}
-      loading={loading}
-      rowHeight={90}
-    />
+    <>
+      {columns ? (
+        <Table
+          columns={columns}
+          rows={columns && jobs?.map((job) => createTableRow(job))}
+          pagination={pagination}
+          onPage={onPage}
+          loading={loading}
+          rowHeight={90}
+        />
+      ) : null}
+    </>
   );
-}
+};
diff --git a/src/components/common/Helper.js b/src/components/common/Helper.js
index feda071b423fc83d9853e636c6a9897d4be981b3..e075163ba03fb7edf1f6f45dedd606df09ac34cf 100644
--- a/src/components/common/Helper.js
+++ b/src/components/common/Helper.js
@@ -101,6 +101,21 @@ export function initRequestParams(lazyParams, filter, columnSort) {
   return requestParams;
 }
 
+export const getErrorMessage = (error) => {
+  const { response, status: requestStatus, message: requestMessage } = error;
+  if (response && response?.body) {
+    const {
+      body: { description },
+      status: httpStatus
+    } = response;
+
+    return `${httpStatus ?? requestStatus ?? "unknown"}: ${
+      description ?? requestMessage ?? "An unknown error has occurred"
+    }`;
+  }
+  return `${requestStatus}: ${requestMessage}`;
+};
+
 export const compareArrays = (a1, a2) =>
   a1.length === a2.length &&
   a1.every((element, index) => element === a2[index]);
diff --git a/src/components/common/User/UserOperationList.js b/src/components/common/User/UserOperationList.js
index 233cc9dd18a1b9744eaf5bb617cad4722e183349..c02c4a84fa14ee7807702235da4419e6186f1577 100644
--- a/src/components/common/User/UserOperationList.js
+++ b/src/components/common/User/UserOperationList.js
@@ -67,6 +67,11 @@ export function UserOperationList({ userName }) {
       />
       <JobTable
         jobs={operations?.operations}
+        customColumns={[
+          { field: "status" },
+          { field: "job" },
+          { field: "host" }
+        ]}
         loading={loading || !dataReady}
         pagination={pagination}
         onPage={onPage}
diff --git a/src/components/host/HostTable.js b/src/components/host/HostTable.js
index e569289bfe6a78224eb410e93843528b98f5b9af..e44ff6a35e7413f66a89cdcf958496b3be3d4a8b 100644
--- a/src/components/host/HostTable.js
+++ b/src/components/host/HostTable.js
@@ -45,7 +45,7 @@ export function HostTable({ hosts, pagination, onPage, loading }) {
   return (
     <Table
       columns={columns}
-      rows={hosts.map((host) => createRow(host))}
+      rows={hosts?.map((host) => createRow(host))}
       pagination={pagination}
       onPage={onPage}
       loading={loading}
diff --git a/src/views/host/HostListView.js b/src/views/host/HostListView.js
index 8803a63d0314043f3e57c8db3089770562d5a4f5..fb6828a5b95523212a95e7573b61048d1452732a 100644
--- a/src/views/host/HostListView.js
+++ b/src/views/host/HostListView.js
@@ -33,6 +33,7 @@ export function HostListView() {
   const {
     value: hosts,
     wrapper: getHosts,
+    dataReady,
     loading,
     abort
   } = useAPIMethod({
@@ -157,7 +158,7 @@ export function HostListView() {
       >
         <HostTable
           hosts={hosts?.netBoxHosts ?? []}
-          loading={loading}
+          loading={loading || !dataReady}
           pagination={pagination}
           onPage={onPage}
         />
diff --git a/src/views/host/details/HostDetailsView.js b/src/views/host/details/HostDetailsView.js
index a98a58bf6719550c8ca5b97df9b315fd9a3988ef..69abc38ec7637459c8479a5661fe420337bd87f3 100644
--- a/src/views/host/details/HostDetailsView.js
+++ b/src/views/host/details/HostDetailsView.js
@@ -1,4 +1,5 @@
-import React, { useEffect, useCallback, useContext, useMemo } from "react";
+import React, { useEffect, useContext } from "react";
+import useUrlState from "@ahooksjs/use-url-state";
 import { Box, IconButton, Typography, Stack } from "@mui/material";
 import ArrowBackIcon from "@mui/icons-material/ArrowBack";
 import { HostBadge } from "../../../components/host/HostBadge";
@@ -6,130 +7,54 @@ import {
   KeyValueTable,
   SimpleAccordion,
   GlobalAppBarContext,
-  useAPIMethod,
   AlertBannerList,
-  usePagination,
   ExternalLink
 } from "@ess-ics/ce-ui-common";
 import { LokiPanel } from "../../../components/common/Loki/LokiPanel";
 import { useNavigate } from "react-router-dom";
-import {
-  applicationTitle,
-  initRequestParams
-} from "../../../components/common/Helper";
+import { applicationTitle } from "../../../components/common/Helper";
 import AccessControl from "../../../components/auth/AccessControl";
-import useUrlState from "@ahooksjs/use-url-state";
 import {
   serialize,
   deserialize
 } from "../../../components/common/URLState/URLState";
-import { apiContext } from "../../../api/DeployApi";
-import IOCTable from "../../../components/IOC/IOCTable";
 import { HostDetailsTable } from "./HostDetailsTable";
+import { HostJobsSection } from "./HostJobsSection";
+import { HostIocSection } from "./HostIocSection";
 
 export function HostDetailsView({ hostId, host }) {
   const { setTitle } = useContext(GlobalAppBarContext);
+  const navigate = useNavigate();
+  const [urlState, setUrlState] = useUrlState();
+
   useEffect(() => {
     if (host && host.netBoxHost) {
       setTitle(applicationTitle("Host Details: " + host.netBoxHost.name));
     }
   }, [host, setTitle]);
 
-  const client = useContext(apiContext);
-
-  const {
-    value: iocs,
-    wrapper: getIocs,
-    loading,
-    dataReady,
-    abort: abortGetIocs
-  } = useAPIMethod({
-    fcn: client.apis.Hosts.findAssociatedIocsByHostId,
-    call: false
-  });
-
-  const [urlState, setUrlState] = useUrlState(
-    {
-      iocs_rows: "20",
-      iocs_page: "0",
-      iocs_open: "true",
-      syslog_open: "true",
-      details_open: "false"
-    },
-    { navigateMode: "replace" }
-  );
-
-  const navigate = useNavigate();
-
-  const urlPagination = useMemo(() => {
-    return {
-      rows: deserialize(urlState.iocs_rows),
-      page: deserialize(urlState.iocs_page)
-    };
-  }, [urlState]);
-
-  const setUrlPagination = useCallback(
-    ({ rows, page }) => {
-      setUrlState({
-        iocs_rows: serialize(rows),
-        iocs_page: serialize(page)
-      });
-    },
-    [setUrlState]
-  );
-
-  const rowsPerPage = [20, 50];
-
-  const { pagination, setPagination } = usePagination({
-    rowsPerPageOptions: rowsPerPage,
-    initLimit: urlPagination.iocs_rows ?? rowsPerPage[0],
-    initPage: urlPagination.iocs_page ?? 0
-  });
-
-  // update pagination whenever search result total pages change
-  useEffect(() => {
-    setPagination({ totalCount: iocs?.totalCount ?? 0 });
-  }, [setPagination, iocs?.totalCount]);
-
-  // whenever url state changes, update pagination
   useEffect(() => {
-    setPagination({ ...urlPagination });
-  }, [setPagination, urlPagination]);
-
-  // whenever table pagination internally changes (user clicks next page etc)
-  // update the row params
-  useEffect(() => {
-    setUrlPagination(pagination);
-  }, [pagination, setUrlPagination]);
-
-  // Invoked by Table on change to pagination
-  const onPage = (params) => {
-    setPagination(params);
-    abortGetIocs();
-  };
-
-  useEffect(() => {
-    let requestParams = initRequestParams(urlPagination, null);
-
-    requestParams.host_id = hostId;
-
-    getIocs(requestParams);
-
-    return () => {
-      abortGetIocs();
-    };
-  }, [getIocs, urlPagination, hostId, abortGetIocs]);
-
-  const handleClick = (event) => {
-    navigate(-1);
-  };
+    if (Object.keys(urlState).length === 0) {
+      setUrlState(
+        {
+          iocs_rows: 20,
+          iocs_page: 0,
+          details_open: false,
+          job_log_open: false,
+          job_log_rows: 20,
+          job_log_page: 0
+        },
+        { navigateMode: "replace" }
+      );
+    }
+  }, [setUrlState, urlState]);
 
   return (
     <Stack gap={2}>
       <Box>
         <IconButton
           color="inherit"
-          onClick={handleClick}
+          onClick={() => navigate(-1)}
           size="large"
         >
           <ArrowBackIcon />
@@ -137,80 +62,92 @@ export function HostDetailsView({ hostId, host }) {
       </Box>
       {host ? (
         <>
-          <AlertBannerList alerts={host?.alerts ?? []} />
+          <AlertBannerList alerts={host.alerts ?? []} />
           <HostBadge host={host} />
-        </>
-      ) : null}
-      <Stack gap={2}>
-        <Typography variant="h3">IOCs</Typography>
-        <IOCTable
-          iocs={iocs?.deployedIocs}
-          loading={loading || !dataReady}
-          rowType="host"
-          pagination={pagination}
-          onPage={onPage}
-        />
-      </Stack>
-      <AccessControl
-        allowedRoles={["DeploymentToolAdmin", "DeploymentToolIntegrator"]}
-        renderNoAccess={() => <></>}
-      >
-        {host ? (
-          <SimpleAccordion
-            summary="Host details"
-            expanded={deserialize(urlState.details_open)}
-            onChange={(event, expanded) =>
-              setUrlState({ details_open: serialize(expanded) })
-            }
-            sx={{ marginTop: "0 !important" }}
-          >
-            <HostDetailsTable host={host} />
-          </SimpleAccordion>
-        ) : null}
-      </AccessControl>
-      <AccessControl
-        allowedRoles={["DeploymentToolAdmin", "DeploymentToolIntegrator"]}
-        renderNoAccess={() => <></>}
-      >
-        <Stack gap={2}>
-          <Typography variant="h3">Host log stream</Typography>
-          {host ? (
-            <LokiPanel
-              host={host}
-              isSyslog
-              isDeployed
+          <Stack gap={2}>
+            <HostIocSection
+              hostId={hostId}
+              rows={deserialize(urlState.iocs_rows)}
+              page={deserialize(urlState.iocs_page)}
+              onUrlStateChange={(params) => setUrlState(params)}
             />
-          ) : null}
-        </Stack>
-      </AccessControl>
-      <KeyValueTable
-        obj={{
-          "Host Configuration": (
-            <ExternalLink
-              href={
-                host?.netBoxHost.vm
-                  ? `${window.NETBOX_ADDRESS}/virtualization/virtual-machines/${host?.netBoxHost.id}`
-                  : `${window.NETBOX_ADDRESS}/dcim/devices/${host?.netBoxHost.id}`
+          </Stack>
+          <HostJobsSection
+            hostId={hostId}
+            rows={deserialize(urlState.job_log_rows)}
+            page={deserialize(urlState.job_log_page)}
+            expanded={deserialize(urlState.job_log_open)}
+            onUrlStateChange={(params) => setUrlState(params)}
+          />
+
+          <AccessControl
+            allowedRoles={["DeploymentToolAdmin", "DeploymentToolIntegrator"]}
+            renderNoAccess={() => <></>}
+          >
+            <SimpleAccordion
+              summary={
+                <Typography
+                  variant="h3"
+                  component="h2"
+                >
+                  Host details
+                </Typography>
+              }
+              expanded={deserialize(urlState.details_open)}
+              onChange={(_, expanded) =>
+                setUrlState({ details_open: serialize(expanded) })
               }
-              aria-label="Host Configuration"
             >
-              {" "}
-              {host?.netBoxHost.vm
-                ? `${window.NETBOX_ADDRESS}/virtualization/virtual-machines/${host?.netBoxHost.id}`
-                : `${window.NETBOX_ADDRESS}/dcim/devices/${host?.netBoxHost.id}`}
-            </ExternalLink>
-          ),
-          "Host Metrics": (
-            <ExternalLink
-              href={`https://grafana.tn.esss.lu.se/d/5zJT23xWz/node-exporter-full?orgId=1&var-node=${host?.netBoxHost.fqdn}`}
-              aria-label="Host Metrics"
+              <HostDetailsTable host={host} />
+            </SimpleAccordion>
+
+            <Stack
+              gap={2}
+              sx={{ marginTop: "10px" }}
             >
-              {`https://grafana.tn.esss.lu.se/d/5zJT23xWz/node-exporter-full?orgId=1&var-node=${host?.netBoxHost.fqdn}`}
-            </ExternalLink>
-          )
-        }}
-        variant="overline"
-      />
+              <Typography
+                variant="h3"
+                component="h2"
+              >
+                Host log stream
+              </Typography>
+              <LokiPanel
+                host={host}
+                isSyslog
+                isDeployed
+              />
+            </Stack>
+          </AccessControl>
+          <KeyValueTable
+            obj={{
+              "Host Configuration": (
+                <ExternalLink
+                  href={
+                    host?.netBoxHost.vm
+                      ? `${window.NETBOX_ADDRESS}/virtualization/virtual-machines/${host?.netBoxHost.id}`
+                      : `${window.NETBOX_ADDRESS}/dcim/devices/${host?.netBoxHost.id}`
+                  }
+                  aria-label="Host Configuration"
+                >
+                  {" "}
+                  {host?.netBoxHost.vm
+                    ? `${window.NETBOX_ADDRESS}/virtualization/virtual-machines/${host?.netBoxHost.id}`
+                    : `${window.NETBOX_ADDRESS}/dcim/devices/${host?.netBoxHost.id}`}
+                </ExternalLink>
+              ),
+              "Host Metrics": (
+                <ExternalLink
+                  href={`https://grafana.tn.esss.lu.se/d/5zJT23xWz/node-exporter-full?orgId=1&var-node=${host?.netBoxHost.fqdn}`}
+                  aria-label="Host Metrics"
+                >
+                  {`https://grafana.tn.esss.lu.se/d/5zJT23xWz/node-exporter-full?orgId=1&var-node=${host?.netBoxHost.fqdn}`}
+                </ExternalLink>
+              )
+            }}
+            variant="overline"
+          />
+        </>
+      ) : null}
     </Stack>
   );
 }
diff --git a/src/views/host/details/HostIocSection.js b/src/views/host/details/HostIocSection.js
new file mode 100644
index 0000000000000000000000000000000000000000..5f70193cd49f7b6311dbabf29538191b32874dfd
--- /dev/null
+++ b/src/views/host/details/HostIocSection.js
@@ -0,0 +1,85 @@
+import React, { useEffect, useContext, useCallback } from "react";
+import IOCTable from "../../../components/IOC/IOCTable";
+import { string, number, func } from "prop-types";
+import { apiContext } from "../../../api/DeployApi";
+import { Typography } from "@mui/material";
+import { useAPIMethod, usePagination } from "@ess-ics/ce-ui-common";
+import { initRequestParams } from "../../../components/common/Helper";
+import { serialize } from "../../../components/common/URLState/URLState";
+
+const propTypes = {
+  hostId: string,
+  row: number,
+  page: number,
+  onUrlStateChange: func
+};
+
+export const HostIocSection = ({ hostId, rows, page, onUrlStateChange }) => {
+  const client = useContext(apiContext);
+  const { pagination, setPagination, setTotalCount } = usePagination({
+    initLimit: rows,
+    initPage: page
+  });
+
+  const {
+    value: iocs,
+    wrapper: callgetIocs,
+    loading,
+    dataReady,
+    abort: abortGetIocs
+  } = useAPIMethod({
+    fcn: client.apis.Hosts.findAssociatedIocsByHostId,
+    call: false
+  });
+
+  const onPage = useCallback(
+    (params) => {
+      setPagination(params);
+      abortGetIocs();
+      onUrlStateChange({
+        iocs_rows: serialize(params.limit),
+        iocs_page: serialize(params.page)
+      });
+    },
+    [setPagination, abortGetIocs, onUrlStateChange]
+  );
+
+  const getIocs = useCallback(() => {
+    let requestParams = initRequestParams({ page, rows }, null);
+    requestParams.host_id = hostId;
+    callgetIocs(requestParams);
+  }, [callgetIocs, hostId, page, rows]);
+
+  // update pagination whenever search result total pages change
+  useEffect(() => {
+    setTotalCount(iocs?.totalCount ?? 0);
+  }, [setTotalCount, iocs?.totalCount]);
+
+  useEffect(() => {
+    getIocs();
+
+    return () => {
+      abortGetIocs();
+    };
+  }, [rows, page, abortGetIocs, getIocs]);
+
+  return (
+    <>
+      <Typography
+        variant="h3"
+        component="h2"
+      >
+        IOCs
+      </Typography>
+      <IOCTable
+        iocs={iocs?.deployedIocs}
+        loading={loading || !dataReady}
+        rowType="host"
+        pagination={pagination}
+        onPage={onPage}
+      />
+    </>
+  );
+};
+
+HostIocSection.propTypes = propTypes;
diff --git a/src/views/host/details/HostJobsSection.js b/src/views/host/details/HostJobsSection.js
new file mode 100644
index 0000000000000000000000000000000000000000..277f96728d3355be272992be92818b34013a7839
--- /dev/null
+++ b/src/views/host/details/HostJobsSection.js
@@ -0,0 +1,115 @@
+import React, { useContext, useEffect, useMemo, useCallback } from "react";
+import { string, number, boolean, func } from "prop-types";
+import { serialize } from "../../../components/common/URLState/URLState";
+import { getErrorMessage } from "../../../components/common/Helper";
+import { apiContext } from "../../../api/DeployApi";
+import {
+  SimpleAccordion,
+  useAPIMethod,
+  usePagination
+} from "@ess-ics/ce-ui-common";
+import { JobTable } from "../../../components/Job";
+import { Alert, Typography } from "@mui/material";
+
+const propTypes = {
+  hostId: string.isRequired,
+  rows: number,
+  page: number,
+  expanded: boolean,
+  onUrlStateChange: func
+};
+
+const rowsPerPage = [20, 50];
+
+export const HostJobsSection = ({
+  hostId,
+  rows,
+  page,
+  expanded,
+  onUrlStateChange
+}) => {
+  const client = useContext(apiContext);
+
+  const { pagination, setPagination } = usePagination({
+    rowsPerPageOptions: rowsPerPage,
+    initLimit: rows,
+    initPage: page
+  });
+
+  const {
+    value: hostLog,
+    wrapper: getHostLog,
+    dataReady,
+    error,
+    loading,
+    abort: abortGetHostLog
+  } = useAPIMethod({
+    fcn: client.apis.Deployments.listOperations,
+    call: false,
+    params: useMemo(
+      () => ({ host_id: hostId, ...pagination }),
+      [hostId, pagination]
+    )
+  });
+
+  const onPage = useCallback(
+    (params) => {
+      setPagination(params);
+      abortGetHostLog();
+      onUrlStateChange({
+        job_log_rows: serialize(params.limit),
+        job_log_page: serialize(params.page)
+      });
+    },
+    [setPagination, abortGetHostLog, onUrlStateChange]
+  );
+
+  useEffect(() => {
+    setPagination({ totalCount: hostLog?.totalCount ?? 0 });
+  }, [setPagination, hostLog]);
+
+  useEffect(() => {
+    if (expanded) {
+      getHostLog();
+    }
+  }, [expanded, pagination, getHostLog]);
+
+  useEffect(() => {
+    return () => {
+      abortGetHostLog();
+    };
+  }, [abortGetHostLog]);
+
+  return (
+    <SimpleAccordion
+      summary={
+        <Typography
+          variant="h3"
+          component="h2"
+        >
+          Job log
+        </Typography>
+      }
+      onChange={(_, isExpanded) =>
+        onUrlStateChange({ job_log_open: serialize(isExpanded) })
+      }
+    >
+      {error ? <Alert severity="error">{getErrorMessage(error)}</Alert> : null}
+      {hostLog ? (
+        <JobTable
+          jobs={!error && hostLog ? hostLog?.operations : null}
+          customColumns={[
+            { field: "status" },
+            { field: "job" },
+            { field: "user" }
+          ]}
+          loading={loading || !dataReady}
+          pagination={pagination}
+          onPage={onPage}
+        />
+      ) : null}
+    </SimpleAccordion>
+  );
+};
+
+HostJobsSection.propTypes = propTypes;