From ab8baf71ca742c2dc90263f907bc08bb10e6beb9 Mon Sep 17 00:00:00 2001
From: Chandrasekharan M <chandrasekharan@zipstack.com>
Date: Wed, 28 Jan 2026 08:57:17 +0530
Subject: [PATCH 1/7] Add copy-to-clipboard button for file execution ID in
 LogModal

Adds a copy icon button next to the file execution ID in the Execution Log Details modal, allowing users to quickly copy the ID to clipboard similar to the main execution ID functionality.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---
 .../components/logging/log-modal/LogModal.css | 25 +++++++++--
 .../components/logging/log-modal/LogModal.jsx | 45 ++++++++++++++++++-
 2 files changed, 65 insertions(+), 5 deletions(-)

diff --git a/frontend/src/components/logging/log-modal/LogModal.css b/frontend/src/components/logging/log-modal/LogModal.css
index b2ed5754b8..f363408be3 100644
--- a/frontend/src/components/logging/log-modal/LogModal.css
+++ b/frontend/src/components/logging/log-modal/LogModal.css
@@ -1,4 +1,23 @@
-.clear-button{
-    margin-left: 50px;
-    margin-top: 10px;
+.clear-button {
+  margin-left: 50px;
+  margin-top: 10px;
+}
+
+.log-modal-title {
+  display: inline-flex;
+  align-items: center;
+}
+
+.log-modal-title .copy-btn-outlined {
+  border: 1px solid #d9d9d9;
+  background: #fff;
+  color: rgba(0, 0, 0, 0.65);
+  margin-left: 8px;
+  height: auto;
+  min-width: auto;
+}
+
+.log-modal-title .copy-btn-outlined:hover {
+  border-color: #1677ff;
+  color: #1677ff;
 }
diff --git a/frontend/src/components/logging/log-modal/LogModal.jsx b/frontend/src/components/logging/log-modal/LogModal.jsx
index 61e5aed121..47a6345622 100644
--- a/frontend/src/components/logging/log-modal/LogModal.jsx
+++ b/frontend/src/components/logging/log-modal/LogModal.jsx
@@ -1,6 +1,7 @@
-import { Modal, Table, Tooltip } from "antd";
+import { Button, Modal, Table, Tooltip } from "antd";
 import { useEffect, useState } from "react";
 import PropTypes from "prop-types";
+import { CopyOutlined } from "@ant-design/icons";
 
 import "./LogModal.css";
 import { useExceptionHandler } from "../../../hooks/useExceptionHandler";
@@ -29,6 +30,32 @@ function LogModal({
   const [loading, setLoading] = useState(false);
   const [selectedLogLevel, setSelectedLogLevel] = useState(null);
   const [ordering, setOrdering] = useState(null);
+  const displayId = fileId || executionId;
+
+  const handleCopyToClipboard = (text, label = "Text") => {
+    if (!navigator.clipboard) {
+      setAlertDetails({
+        type: "error",
+        content: "Clipboard not available in this browser",
+      });
+      return;
+    }
+    navigator.clipboard.writeText(text).then(
+      () => {
+        setAlertDetails({
+          type: "success",
+          content: `${label} copied to clipboard`,
+        });
+      },
+      (err) => {
+        setAlertDetails({
+          type: "error",
+          content: `Failed to copy: ${err.message || "Unknown error"}`,
+        });
+      },
+    );
+  };
+
   const [pagination, setPagination] = useState({
     current: 1,
     pageSize: 10,
@@ -150,7 +177,21 @@ function LogModal({
   }, [logDescModalOpen, pagination.current, selectedLogLevel, ordering]);
   return (
     <Modal
-      title={`Execution Log Details - ${fileId || executionId}`}
+      title={
+        <span className="log-modal-title">
+          Execution Log Details - {displayId}
+          <Button
+            className="copy-btn-outlined"
+            icon={<CopyOutlined />}
+            onClick={() =>
+              handleCopyToClipboard(
+                displayId,
+                fileId ? "File Execution ID" : "Execution ID",
+              )
+            }
+          />
+        </span>
+      }
       centered
       open={logDescModalOpen}
       onCancel={handleClose}

From b2dfe139a8b5553724f9f4ad87e697e2fd64daf1 Mon Sep 17 00:00:00 2001
From: Chandrasekharan M <chandrasekharan@zipstack.com>
Date: Wed, 28 Jan 2026 09:22:33 +0530
Subject: [PATCH 2/7] Fix copy button: add aria-label, guard empty displayId,
 remove dash

- Only render copy button when displayId is truthy
- Add aria-label for accessibility
- Remove dash separator from title

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---
 .../components/logging/log-modal/LogModal.jsx | 25 +++++++++++--------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/frontend/src/components/logging/log-modal/LogModal.jsx b/frontend/src/components/logging/log-modal/LogModal.jsx
index 47a6345622..0b1970544d 100644
--- a/frontend/src/components/logging/log-modal/LogModal.jsx
+++ b/frontend/src/components/logging/log-modal/LogModal.jsx
@@ -179,17 +179,20 @@ function LogModal({
     <Modal
       title={
         <span className="log-modal-title">
-          Execution Log Details - {displayId}
-          <Button
-            className="copy-btn-outlined"
-            icon={<CopyOutlined />}
-            onClick={() =>
-              handleCopyToClipboard(
-                displayId,
-                fileId ? "File Execution ID" : "Execution ID",
-              )
-            }
-          />
+          Execution Log Details {displayId}
+          {displayId && (
+            <Button
+              className="copy-btn-outlined"
+              icon={<CopyOutlined />}
+              aria-label="Copy execution ID"
+              onClick={() =>
+                handleCopyToClipboard(
+                  displayId,
+                  fileId ? "File Execution ID" : "Execution ID",
+                )
+              }
+            />
+          )}
         </span>
       }
       centered

From e63441c427351703ca011faff149c4c28473fbea Mon Sep 17 00:00:00 2001
From: Chandrasekharan M
 <117059509+chandrasekharan-zipstack@users.noreply.github.com>
Date: Wed, 28 Jan 2026 09:25:27 +0530
Subject: [PATCH 3/7] Update
 frontend/src/components/logging/log-modal/LogModal.jsx

Signed-off-by: Chandrasekharan M <117059509+chandrasekharan-zipstack@users.noreply.github.com>
---
 frontend/src/components/logging/log-modal/LogModal.jsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/frontend/src/components/logging/log-modal/LogModal.jsx b/frontend/src/components/logging/log-modal/LogModal.jsx
index 0b1970544d..399aeb5119 100644
--- a/frontend/src/components/logging/log-modal/LogModal.jsx
+++ b/frontend/src/components/logging/log-modal/LogModal.jsx
@@ -179,7 +179,7 @@ function LogModal({
     <Modal
       title={
         <span className="log-modal-title">
-          Execution Log Details {displayId}
+          File Execution ID {displayId}
           {displayId && (
             <Button
               className="copy-btn-outlined"

From dbf4b16b9f09cc1986b09968b65b41e639c6c81d Mon Sep 17 00:00:00 2001
From: Chandrasekharan M <chandrasekharan@zipstack.com>
Date: Wed, 28 Jan 2026 09:36:27 +0530
Subject: [PATCH 4/7] Fix prettier trailing comma errors

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---
 frontend/src/components/logging/log-modal/LogModal.jsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/frontend/src/components/logging/log-modal/LogModal.jsx b/frontend/src/components/logging/log-modal/LogModal.jsx
index 399aeb5119..8470b782ef 100644
--- a/frontend/src/components/logging/log-modal/LogModal.jsx
+++ b/frontend/src/components/logging/log-modal/LogModal.jsx
@@ -52,7 +52,7 @@ function LogModal({
           type: "error",
           content: `Failed to copy: ${err.message || "Unknown error"}`,
         });
-      },
+      }
     );
   };
 
@@ -188,7 +188,7 @@ function LogModal({
               onClick={() =>
                 handleCopyToClipboard(
                   displayId,
-                  fileId ? "File Execution ID" : "Execution ID",
+                  fileId ? "File Execution ID" : "Execution ID"
                 )
               }
             />

From 7e994636a9d6be0f871d047f364049f3f23eee42 Mon Sep 17 00:00:00 2001
From: Chandrasekharan M <chandrasekharan@zipstack.com>
Date: Wed, 28 Jan 2026 09:53:39 +0530
Subject: [PATCH 5/7] Refactor: extract clipboard logic into useCopyToClipboard
 hook

- Create reusable useCopyToClipboard hook to avoid code duplication
- Update LogModal.jsx to use the shared hook
- Update DetailedLogs.jsx to use the shared hook

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---
 .../logging/detailed-logs/DetailedLogs.jsx    | 32 +++---------------
 .../components/logging/log-modal/LogModal.jsx | 33 +++----------------
 frontend/src/hooks/useCopyToClipboard.js      | 33 +++++++++++++++++++
 3 files changed, 43 insertions(+), 55 deletions(-)
 create mode 100644 frontend/src/hooks/useCopyToClipboard.js

diff --git a/frontend/src/components/logging/detailed-logs/DetailedLogs.jsx b/frontend/src/components/logging/detailed-logs/DetailedLogs.jsx
index 0c89b2afeb..4797fdce35 100644
--- a/frontend/src/components/logging/detailed-logs/DetailedLogs.jsx
+++ b/frontend/src/components/logging/detailed-logs/DetailedLogs.jsx
@@ -39,6 +39,7 @@ import { LogModal } from "../log-modal/LogModal";
 import { FilterIcon } from "../filter-dropdown/FilterDropdown";
 import { LogsRefreshControls } from "../logs-refresh-controls/LogsRefreshControls";
 import useRequestUrl from "../../../hooks/useRequestUrl";
+import { useCopyToClipboard } from "../../../hooks/useCopyToClipboard";
 
 // Component for status message with conditional tooltip (only when truncated)
 const StatusMessageCell = ({ text }) => {
@@ -49,7 +50,7 @@ const StatusMessageCell = ({ text }) => {
     const checkOverflow = () => {
       if (textRef.current) {
         setIsOverflowing(
-          textRef.current.scrollWidth > textRef.current.clientWidth
+          textRef.current.scrollWidth > textRef.current.clientWidth,
         );
       }
     };
@@ -95,6 +96,7 @@ const DetailedLogs = () => {
   const handleException = useExceptionHandler();
   const navigate = useNavigate();
   const { getUrl } = useRequestUrl();
+  const copyToClipboard = useCopyToClipboard();
 
   const [executionDetails, setExecutionDetails] = useState();
   const [executionFiles, setExecutionFiles] = useState();
@@ -122,30 +124,6 @@ const DetailedLogs = () => {
     executionDetails?.status &&
     TERMINAL_STATES.includes(executionDetails.status.toUpperCase());
 
-  const handleCopyToClipboard = (text, label = "Text") => {
-    if (!navigator.clipboard) {
-      setAlertDetails({
-        type: "error",
-        content: "Clipboard not available in this browser",
-      });
-      return;
-    }
-    navigator.clipboard.writeText(text).then(
-      () => {
-        setAlertDetails({
-          type: "success",
-          content: `${label} copied to clipboard`,
-        });
-      },
-      (err) => {
-        setAlertDetails({
-          type: "error",
-          content: `Failed to copy: ${err.message || "Unknown error"}`,
-        });
-      }
-    );
-  };
-
   const fetchExecutionDetails = async (id) => {
     try {
       const url = getUrl(`/execution/${id}/`);
@@ -224,7 +202,7 @@ const DetailedLogs = () => {
       }
 
       const response = await axiosPrivate.get(
-        `${url}?${searchParams.toString()}`
+        `${url}?${searchParams.toString()}`,
       );
       setPagination({
         current: page,
@@ -490,7 +468,7 @@ const DetailedLogs = () => {
           <Button
             className="copy-btn-outlined"
             icon={<CopyOutlined />}
-            onClick={() => handleCopyToClipboard(id, "Execution ID")}
+            onClick={() => copyToClipboard(id, "Execution ID")}
           />
         </Typography.Title>
         <LogsRefreshControls
diff --git a/frontend/src/components/logging/log-modal/LogModal.jsx b/frontend/src/components/logging/log-modal/LogModal.jsx
index 8470b782ef..4c6039e127 100644
--- a/frontend/src/components/logging/log-modal/LogModal.jsx
+++ b/frontend/src/components/logging/log-modal/LogModal.jsx
@@ -13,6 +13,7 @@ import {
 } from "../../../helpers/GetStaticData";
 import { FilterDropdown, FilterIcon } from "../filter-dropdown/FilterDropdown";
 import useRequestUrl from "../../../hooks/useRequestUrl";
+import { useCopyToClipboard } from "../../../hooks/useCopyToClipboard";
 
 function LogModal({
   executionId,
@@ -25,37 +26,13 @@ function LogModal({
   const { setAlertDetails } = useAlertStore();
   const handleException = useExceptionHandler();
   const { getUrl } = useRequestUrl();
+  const copyToClipboard = useCopyToClipboard();
+  const displayId = fileId || executionId;
 
   const [executionLogs, setExecutionLogs] = useState([]);
   const [loading, setLoading] = useState(false);
   const [selectedLogLevel, setSelectedLogLevel] = useState(null);
   const [ordering, setOrdering] = useState(null);
-  const displayId = fileId || executionId;
-
-  const handleCopyToClipboard = (text, label = "Text") => {
-    if (!navigator.clipboard) {
-      setAlertDetails({
-        type: "error",
-        content: "Clipboard not available in this browser",
-      });
-      return;
-    }
-    navigator.clipboard.writeText(text).then(
-      () => {
-        setAlertDetails({
-          type: "success",
-          content: `${label} copied to clipboard`,
-        });
-      },
-      (err) => {
-        setAlertDetails({
-          type: "error",
-          content: `Failed to copy: ${err.message || "Unknown error"}`,
-        });
-      }
-    );
-  };
-
   const [pagination, setPagination] = useState({
     current: 1,
     pageSize: 10,
@@ -186,9 +163,9 @@ function LogModal({
               icon={<CopyOutlined />}
               aria-label="Copy execution ID"
               onClick={() =>
-                handleCopyToClipboard(
+                copyToClipboard(
                   displayId,
-                  fileId ? "File Execution ID" : "Execution ID"
+                  fileId ? "File Execution ID" : "Execution ID",
                 )
               }
             />
diff --git a/frontend/src/hooks/useCopyToClipboard.js b/frontend/src/hooks/useCopyToClipboard.js
new file mode 100644
index 0000000000..e7b6c63311
--- /dev/null
+++ b/frontend/src/hooks/useCopyToClipboard.js
@@ -0,0 +1,33 @@
+import { useAlertStore } from "../store/alert-store";
+
+function useCopyToClipboard() {
+  const { setAlertDetails } = useAlertStore();
+
+  const copyToClipboard = (text, label = "Text") => {
+    if (!navigator.clipboard) {
+      setAlertDetails({
+        type: "error",
+        content: "Clipboard not available in this browser",
+      });
+      return;
+    }
+    navigator.clipboard.writeText(text).then(
+      () => {
+        setAlertDetails({
+          type: "success",
+          content: `${label} copied to clipboard`,
+        });
+      },
+      (err) => {
+        setAlertDetails({
+          type: "error",
+          content: `Failed to copy: ${err.message || "Unknown error"}`,
+        });
+      },
+    );
+  };
+
+  return copyToClipboard;
+}
+
+export { useCopyToClipboard };

From 99229827f6817a1fb5383f004603f63b3e84dc67 Mon Sep 17 00:00:00 2001
From: Chandrasekharan M <chandrasekharan@zipstack.com>
Date: Wed, 28 Jan 2026 10:07:55 +0530
Subject: [PATCH 6/7] Corrected clipboard copy label

---
 frontend/src/components/logging/log-modal/LogModal.jsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/frontend/src/components/logging/log-modal/LogModal.jsx b/frontend/src/components/logging/log-modal/LogModal.jsx
index 4c6039e127..f2254152d3 100644
--- a/frontend/src/components/logging/log-modal/LogModal.jsx
+++ b/frontend/src/components/logging/log-modal/LogModal.jsx
@@ -165,7 +165,7 @@ function LogModal({
               onClick={() =>
                 copyToClipboard(
                   displayId,
-                  fileId ? "File Execution ID" : "Execution ID",
+                  "File Execution ID"
                 )
               }
             />

From dc18941ca1518e567b292b75e58ec387c598c6f6 Mon Sep 17 00:00:00 2001
From: Chandrasekharan M <chandrasekharan@zipstack.com>
Date: Wed, 28 Jan 2026 10:19:30 +0530
Subject: [PATCH 7/7] Fix prettier trailing comma errors

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---
 .../src/components/logging/detailed-logs/DetailedLogs.jsx  | 4 ++--
 frontend/src/components/logging/log-modal/LogModal.jsx     | 7 +------
 frontend/src/hooks/useCopyToClipboard.js                   | 2 +-
 3 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/frontend/src/components/logging/detailed-logs/DetailedLogs.jsx b/frontend/src/components/logging/detailed-logs/DetailedLogs.jsx
index 4797fdce35..3a59f84558 100644
--- a/frontend/src/components/logging/detailed-logs/DetailedLogs.jsx
+++ b/frontend/src/components/logging/detailed-logs/DetailedLogs.jsx
@@ -50,7 +50,7 @@ const StatusMessageCell = ({ text }) => {
     const checkOverflow = () => {
       if (textRef.current) {
         setIsOverflowing(
-          textRef.current.scrollWidth > textRef.current.clientWidth,
+          textRef.current.scrollWidth > textRef.current.clientWidth
         );
       }
     };
@@ -202,7 +202,7 @@ const DetailedLogs = () => {
       }
 
       const response = await axiosPrivate.get(
-        `${url}?${searchParams.toString()}`,
+        `${url}?${searchParams.toString()}`
       );
       setPagination({
         current: page,
diff --git a/frontend/src/components/logging/log-modal/LogModal.jsx b/frontend/src/components/logging/log-modal/LogModal.jsx
index f2254152d3..18de897bc6 100644
--- a/frontend/src/components/logging/log-modal/LogModal.jsx
+++ b/frontend/src/components/logging/log-modal/LogModal.jsx
@@ -162,12 +162,7 @@ function LogModal({
               className="copy-btn-outlined"
               icon={<CopyOutlined />}
               aria-label="Copy execution ID"
-              onClick={() =>
-                copyToClipboard(
-                  displayId,
-                  "File Execution ID"
-                )
-              }
+              onClick={() => copyToClipboard(displayId, "File Execution ID")}
             />
           )}
         </span>
diff --git a/frontend/src/hooks/useCopyToClipboard.js b/frontend/src/hooks/useCopyToClipboard.js
index e7b6c63311..8c68e3954d 100644
--- a/frontend/src/hooks/useCopyToClipboard.js
+++ b/frontend/src/hooks/useCopyToClipboard.js
@@ -23,7 +23,7 @@ function useCopyToClipboard() {
           type: "error",
           content: `Failed to copy: ${err.message || "Unknown error"}`,
         });
-      },
+      }
     );
   };
 
