From fa65bb5df8d8ec498a6c2db4c836c5e23552efbd Mon Sep 17 00:00:00 2001
From: Giuseppe Steduto <giuseppe@steduto.it>
Date: Mon, 12 Feb 2024 17:51:46 +0100
Subject: [PATCH] refactor(workflow-badges): centralise list and details
 components (#394)

Closes #151
Closes #395
---
 .../components/LauncherLabel.js               |   0
 reana-ui/src/components/WorkflowBadges.js     |  63 ++++++++++
 .../src/components/WorkflowBadges.module.scss |  23 ++++
 .../WorkflowInfo.js}                          |  10 +-
 .../WorkflowInfo.module.scss}                 |  27 +---
 .../components/WorkflowProgressCircleBar.js   |   2 +-
 .../WorkflowProgressCircleBar.module.scss     |   0
 .../__tests__/LauncherLabel.test.js           |   2 +-
 reana-ui/src/components/index.js              |   4 +
 .../pages/workflowDetails/WorkflowDetails.js  |  13 +-
 .../WorkflowDetails.module.scss               |  10 ++
 .../components/WorkflowInfo.js                | 119 ------------------
 .../components/WorkflowInfo.module.scss       |  68 ----------
 .../pages/workflowDetails/components/index.js |   4 +-
 .../src/pages/workflowList/WorkflowList.js    |   2 +-
 .../workflowList/components/WorkflowBadges.js |  75 -----------
 .../components/WorkflowBadges.module.scss     |  51 --------
 .../workflowList/components/WorkflowList.js   |  27 +++-
 .../components/WorkflowList.module.scss       |  27 +++-
 19 files changed, 170 insertions(+), 357 deletions(-)
 rename reana-ui/src/{pages/workflowDetails => }/components/LauncherLabel.js (100%)
 create mode 100644 reana-ui/src/components/WorkflowBadges.js
 create mode 100644 reana-ui/src/components/WorkflowBadges.module.scss
 rename reana-ui/src/{pages/workflowList/components/WorkflowDetails.js => components/WorkflowInfo.js} (89%)
 rename reana-ui/src/{pages/workflowList/components/WorkflowDetails.module.scss => components/WorkflowInfo.module.scss} (70%)
 rename reana-ui/src/{pages/workflowList => }/components/WorkflowProgressCircleBar.js (98%)
 rename reana-ui/src/{pages/workflowList => }/components/WorkflowProgressCircleBar.module.scss (100%)
 rename reana-ui/src/{pages/workflowDetails => }/components/__tests__/LauncherLabel.test.js (96%)
 create mode 100644 reana-ui/src/pages/workflowDetails/WorkflowDetails.module.scss
 delete mode 100644 reana-ui/src/pages/workflowDetails/components/WorkflowInfo.js
 delete mode 100644 reana-ui/src/pages/workflowDetails/components/WorkflowInfo.module.scss
 delete mode 100644 reana-ui/src/pages/workflowList/components/WorkflowBadges.js
 delete mode 100644 reana-ui/src/pages/workflowList/components/WorkflowBadges.module.scss

diff --git a/reana-ui/src/pages/workflowDetails/components/LauncherLabel.js b/reana-ui/src/components/LauncherLabel.js
similarity index 100%
rename from reana-ui/src/pages/workflowDetails/components/LauncherLabel.js
rename to reana-ui/src/components/LauncherLabel.js
diff --git a/reana-ui/src/components/WorkflowBadges.js b/reana-ui/src/components/WorkflowBadges.js
new file mode 100644
index 00000000..5206edeb
--- /dev/null
+++ b/reana-ui/src/components/WorkflowBadges.js
@@ -0,0 +1,63 @@
+import styles from "./WorkflowBadges.module.scss";
+import { Label } from "semantic-ui-react";
+import { JupyterNotebookIcon } from "~/components";
+import { INTERACTIVE_SESSION_URL } from "~/client";
+import { LauncherLabel } from "~/components";
+import { getReanaToken } from "~/selectors";
+import { useSelector } from "react-redux";
+import { statusMapping } from "~/util";
+
+export default function WorkflowBadges({ workflow }) {
+  const reanaToken = useSelector(getReanaToken);
+  const {
+    id,
+    size,
+    launcherURL,
+    session_uri: sessionUri,
+    session_status: sessionStatus,
+  } = workflow;
+  const hasDiskUsage = size.raw > 0;
+  const isSessionOpen = sessionStatus === "created";
+
+  return (
+    <>
+      <div className={styles.badgesContainer}>
+        {workflow.duration && (
+          <Label
+            size="tiny"
+            content={workflow.duration}
+            icon="clock"
+            rel="noopener noreferrer"
+            color={statusMapping[workflow.status].color}
+            onClick={(e) => e.stopPropagation()}
+          />
+        )}
+        {hasDiskUsage && (
+          <Label
+            size="tiny"
+            content={size.human_readable}
+            icon="hdd"
+            as="a"
+            href={"/details/" + id}
+            target="_blank"
+            rel="noopener noreferrer"
+            onClick={(e) => e.stopPropagation()}
+          />
+        )}
+        {isSessionOpen && (
+          <Label
+            size="tiny"
+            content={"Notebook"}
+            icon={<JupyterNotebookIcon size={12} />}
+            as="a"
+            href={INTERACTIVE_SESSION_URL(sessionUri, reanaToken)}
+            target="_blank"
+            rel="noopener noreferrer"
+            onClick={(e) => e.stopPropagation()}
+          />
+        )}
+        <LauncherLabel url={launcherURL} />
+      </div>
+    </>
+  );
+}
diff --git a/reana-ui/src/components/WorkflowBadges.module.scss b/reana-ui/src/components/WorkflowBadges.module.scss
new file mode 100644
index 00000000..91cacb1e
--- /dev/null
+++ b/reana-ui/src/components/WorkflowBadges.module.scss
@@ -0,0 +1,23 @@
+/*
+  -*- coding: utf-8 -*-
+
+  This file is part of REANA.
+  Copyright (C) 2023 CERN.
+
+  REANA is free software; you can redistribute it and/or modify it
+  under the terms of the MIT License; see LICENSE file for more details.
+*/
+
+.badgesContainer {
+  display: flex;
+
+  a:global(.label) {
+    margin-left: 15px;
+    gap: 10px;
+
+    &:hover {
+      cursor: pointer;
+      filter: opacity(0.8);
+    }
+  }
+}
diff --git a/reana-ui/src/pages/workflowList/components/WorkflowDetails.js b/reana-ui/src/components/WorkflowInfo.js
similarity index 89%
rename from reana-ui/src/pages/workflowList/components/WorkflowDetails.js
rename to reana-ui/src/components/WorkflowInfo.js
index 50b664a8..2f1eec95 100644
--- a/reana-ui/src/pages/workflowList/components/WorkflowDetails.js
+++ b/reana-ui/src/components/WorkflowInfo.js
@@ -2,7 +2,7 @@
   -*- coding: utf-8 -*-
 
   This file is part of REANA.
-  Copyright (C) 2023 CERN.
+  Copyright (C) 2023, 2024 CERN.
 
   REANA is free software; you can redistribute it and/or modify it
   under the terms of the MIT License; see LICENSE file for more details.
@@ -13,10 +13,10 @@ import PropTypes from "prop-types";
 
 import { statusMapping } from "~/util";
 
-import styles from "./WorkflowDetails.module.scss";
-import WorkflowProgressCircleBar from "~/pages/workflowList/components/WorkflowProgressCircleBar";
+import styles from "./WorkflowInfo.module.scss";
+import { WorkflowProgressCircleBar } from "~/components";
 
-export default function WorkflowDetails({ workflow }) {
+export default function WorkflowInfo({ workflow }) {
   const {
     name,
     run,
@@ -87,6 +87,6 @@ export default function WorkflowDetails({ workflow }) {
   );
 }
 
-WorkflowDetails.propTypes = {
+WorkflowInfo.propTypes = {
   workflow: PropTypes.object.isRequired,
 };
diff --git a/reana-ui/src/pages/workflowList/components/WorkflowDetails.module.scss b/reana-ui/src/components/WorkflowInfo.module.scss
similarity index 70%
rename from reana-ui/src/pages/workflowList/components/WorkflowDetails.module.scss
rename to reana-ui/src/components/WorkflowInfo.module.scss
index 41f51057..a57b13cd 100644
--- a/reana-ui/src/pages/workflowList/components/WorkflowDetails.module.scss
+++ b/reana-ui/src/components/WorkflowInfo.module.scss
@@ -17,13 +17,7 @@
 
 .workflow {
   color: $raven;
-
-  /**FIXME visibility on hover is missing!*/
-  &.hover {
-    .actions {
-      visibility: visible !important;
-    }
-  }
+  font-size: 1.15rem;
 
   &.deleted {
     opacity: 0.5;
@@ -47,16 +41,6 @@
     .run {
       padding-left: 0.8em;
     }
-
-    .size {
-      color: $light-gray;
-      font-size: 0.75em;
-      margin-right: 0.75em;
-
-      &.highlight {
-        color: $sui-red;
-      }
-    }
   }
 
   .name,
@@ -73,17 +57,12 @@
     width: 210px;
     flex-shrink: 0;
     display: flex;
-    justify-content: end;
+    justify-content: flex-end;
     text-align: right;
   }
 
   .progressbar-container {
     width: 80px;
-    padding: 10px;
-    padding-top: 0;
-  }
-
-  .notebook {
-    font-size: 0.85em;
+    padding: 0 10px;
   }
 }
diff --git a/reana-ui/src/pages/workflowList/components/WorkflowProgressCircleBar.js b/reana-ui/src/components/WorkflowProgressCircleBar.js
similarity index 98%
rename from reana-ui/src/pages/workflowList/components/WorkflowProgressCircleBar.js
rename to reana-ui/src/components/WorkflowProgressCircleBar.js
index e894174a..67d2e2a5 100644
--- a/reana-ui/src/pages/workflowList/components/WorkflowProgressCircleBar.js
+++ b/reana-ui/src/components/WorkflowProgressCircleBar.js
@@ -16,7 +16,7 @@ export default function WorkflowProgressCircleBar({ workflow }) {
 
   const size = 80;
   const strokeWidth = 10;
-  const radius = size / 2 - strokeWidth;
+  const radius = (size - strokeWidth) / 2;
   const circumference = 2 * Math.PI * radius;
 
   let lengthFinishedArc = (completed / total) * circumference;
diff --git a/reana-ui/src/pages/workflowList/components/WorkflowProgressCircleBar.module.scss b/reana-ui/src/components/WorkflowProgressCircleBar.module.scss
similarity index 100%
rename from reana-ui/src/pages/workflowList/components/WorkflowProgressCircleBar.module.scss
rename to reana-ui/src/components/WorkflowProgressCircleBar.module.scss
diff --git a/reana-ui/src/pages/workflowDetails/components/__tests__/LauncherLabel.test.js b/reana-ui/src/components/__tests__/LauncherLabel.test.js
similarity index 96%
rename from reana-ui/src/pages/workflowDetails/components/__tests__/LauncherLabel.test.js
rename to reana-ui/src/components/__tests__/LauncherLabel.test.js
index 0b8480ea..31bc7a3e 100644
--- a/reana-ui/src/pages/workflowDetails/components/__tests__/LauncherLabel.test.js
+++ b/reana-ui/src/components/__tests__/LauncherLabel.test.js
@@ -1,6 +1,6 @@
 /*
   This file is part of REANA.
-  Copyright (C) 2022 CERN.
+  Copyright (C) 2022, 2023, 2024 CERN.
 
   REANA is free software; you can redistribute it and/or modify it
   under the terms of the MIT License; see LICENSE file for more details.
diff --git a/reana-ui/src/components/index.js b/reana-ui/src/components/index.js
index a66f2b4b..74e0fc43 100644
--- a/reana-ui/src/components/index.js
+++ b/reana-ui/src/components/index.js
@@ -16,10 +16,14 @@ export { default as Pagination } from "./Pagination";
 export { default as Title } from "./Title";
 export { default as TopHeader } from "./TopHeader";
 export { default as TooltipIfTruncated } from "./TooltipIfTruncated";
+export { default as LauncherLabel } from "./LauncherLabel";
 export { default as JupyterNotebookIcon } from "./JupyterNotebookIcon";
 export { default as WorkflowDeleteModal } from "./WorkflowDeleteModal";
+export { default as WorkflowInfo } from "./WorkflowInfo";
+export { default as WorkflowBadges } from "./WorkflowBadges";
 export { default as WorkflowStopModal } from "./WorkflowStopModal";
 export { default as WorkflowActionsPopup } from "./WorkflowActionsPopup";
+export { default as WorkflowProgressCircleBar } from "./WorkflowProgressCircleBar";
 export { default as PieChart } from "./PieChart";
 export { default as Search } from "./Search";
 export { default as Box } from "./Box";
diff --git a/reana-ui/src/pages/workflowDetails/WorkflowDetails.js b/reana-ui/src/pages/workflowDetails/WorkflowDetails.js
index e1591fe4..1f26dd8c 100644
--- a/reana-ui/src/pages/workflowDetails/WorkflowDetails.js
+++ b/reana-ui/src/pages/workflowDetails/WorkflowDetails.js
@@ -25,15 +25,18 @@ import BasePage from "../BasePage";
 import {
   InteractiveSessionModal,
   Notification,
+  WorkflowInfo,
+  WorkflowActionsPopup,
+  WorkflowBadges,
   WorkflowDeleteModal,
   WorkflowStopModal,
 } from "~/components";
 import {
-  WorkflowInfo,
   WorkflowLogs,
   WorkflowFiles,
   WorkflowSpecification,
 } from "./components";
+import styles from "./WorkflowDetails.module.scss";
 
 const FINISHED_STATUSES = ["finished", "failed", "stopped", "deleted"];
 
@@ -140,8 +143,14 @@ export default function WorkflowDetails() {
 
   return (
     <BasePage title={pageTitle}>
-      <Container>
+      <Container className={styles["workflow-details-container"]}>
         <WorkflowInfo workflow={workflow} />
+        <div className={styles["badges-and-actions"]}>
+          <WorkflowBadges workflow={workflow} withDivider={false} />
+          <div className={styles.actionsContainer}>
+            <WorkflowActionsPopup workflow={workflow} />
+          </div>
+        </div>
         <Tab
           menu={{ secondary: true, pointing: true }}
           panes={panes}
diff --git a/reana-ui/src/pages/workflowDetails/WorkflowDetails.module.scss b/reana-ui/src/pages/workflowDetails/WorkflowDetails.module.scss
new file mode 100644
index 00000000..7f61cd80
--- /dev/null
+++ b/reana-ui/src/pages/workflowDetails/WorkflowDetails.module.scss
@@ -0,0 +1,10 @@
+.workflow-details-container {
+  padding-top: 2rem;
+}
+
+.badges-and-actions {
+  display: flex;
+  justify-content: space-between;
+  width: 100%;
+  padding: 0 0.75rem 1rem 1rem;
+}
diff --git a/reana-ui/src/pages/workflowDetails/components/WorkflowInfo.js b/reana-ui/src/pages/workflowDetails/components/WorkflowInfo.js
deleted file mode 100644
index ec50a517..00000000
--- a/reana-ui/src/pages/workflowDetails/components/WorkflowInfo.js
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
-  -*- coding: utf-8 -*-
-
-  This file is part of REANA.
-  Copyright (C) 2020, 2022 CERN.
-
-  REANA is free software; you can redistribute it and/or modify it
-  under the terms of the MIT License; see LICENSE file for more details.
-*/
-
-import { useSelector } from "react-redux";
-import PropTypes from "prop-types";
-import { Icon, Popup } from "semantic-ui-react";
-
-import { INTERACTIVE_SESSION_URL } from "~/client";
-import { NON_FINISHED_STATUSES } from "~/config";
-import { getReanaToken } from "~/selectors";
-import { statusMapping } from "~/util";
-import { LauncherLabel, WorkflowProgress } from "../components";
-import { JupyterNotebookIcon, WorkflowActionsPopup } from "~/components";
-import styles from "./WorkflowInfo.module.scss";
-
-export default function WorkflowInfo({ workflow }) {
-  const {
-    name,
-    run,
-    createdDate,
-    startedDate,
-    finishedDate,
-    friendlyCreated,
-    friendlyStarted,
-    friendlyFinished,
-    duration,
-    completed,
-    total,
-    status,
-    launcherURL,
-    session_uri: sessionUri,
-    session_status: sessionStatus,
-  } = workflow;
-  const reanaToken = useSelector(getReanaToken);
-  const isSessionOpen = sessionStatus === "created";
-  return (
-    <div className={styles.workflow}>
-      <section className={styles.info}>
-        <div className={styles["details-box"]}>
-          <Icon
-            name={statusMapping[status].icon}
-            color={statusMapping[status].color}
-          />
-          <div>
-            <span className={styles["name"]}>{name}</span>
-            <span className={styles["run"]}>#{run}</span>
-            {isSessionOpen && (
-              <a
-                href={INTERACTIVE_SESSION_URL(sessionUri, reanaToken)}
-                target="_blank"
-                rel="noopener noreferrer"
-                onClick={(e) => e.stopPropagation()}
-                className={styles.notebook}
-              >
-                <JupyterNotebookIcon />
-              </a>
-            )}
-            <span className={styles["launcher-label"]}>
-              <LauncherLabel url={launcherURL} />
-            </span>
-            <Popup
-              trigger={
-                <div>
-                  {friendlyFinished
-                    ? `Finished ${friendlyFinished}`
-                    : friendlyStarted
-                      ? `Started ${friendlyStarted}`
-                      : `Created ${friendlyCreated}`}
-                </div>
-              }
-              content={
-                friendlyFinished
-                  ? finishedDate
-                  : friendlyStarted
-                    ? startedDate
-                    : createdDate
-              }
-            />
-          </div>
-        </div>
-        <div className={styles.info}>
-          <div>
-            <div className={styles["first-row"]}>
-              <span
-                className={`${styles["status"]} sui-${statusMapping[status].color}`}
-              >
-                {status}
-              </span>{" "}
-              {statusMapping[status].preposition} {duration}
-              {NON_FINISHED_STATUSES.includes(status) && (
-                <Icon
-                  name="refresh"
-                  className={styles.refresh}
-                  onClick={() => window.location.reload()}
-                />
-              )}
-            </div>
-            <div>
-              step {completed}/{total}
-            </div>
-          </div>
-          <WorkflowActionsPopup workflow={workflow} />
-        </div>
-      </section>
-      <WorkflowProgress workflow={workflow} />
-    </div>
-  );
-}
-
-WorkflowInfo.propTypes = {
-  workflow: PropTypes.object.isRequired,
-};
diff --git a/reana-ui/src/pages/workflowDetails/components/WorkflowInfo.module.scss b/reana-ui/src/pages/workflowDetails/components/WorkflowInfo.module.scss
deleted file mode 100644
index 26436375..00000000
--- a/reana-ui/src/pages/workflowDetails/components/WorkflowInfo.module.scss
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-  -*- coding: utf-8 -*-
-
-  This file is part of REANA.
-  Copyright (C) 2020, 2022 CERN.
-
-  REANA is free software; you can redistribute it and/or modify it
-  under the terms of the MIT License; see LICENSE file for more details.
-*/
-
-@import "@palette";
-
-.workflow {
-  color: $raven;
-  margin: 2rem 0;
-  font-size: 16px;
-
-  .info {
-    display: flex;
-    justify-content: space-between;
-    padding-bottom: 1em;
-    flex-shrink: 0;
-
-    .details-box {
-      display: flex;
-      align-items: baseline;
-    }
-  }
-
-  .name,
-  .status {
-    font-weight: bold;
-  }
-
-  .name {
-    font-size: 1.3em;
-  }
-
-  .status,
-  .run {
-    font-size: 1.2em;
-  }
-
-  .run {
-    padding: 0 0.8em;
-  }
-
-  .refresh {
-    color: $gray;
-    cursor: pointer;
-    margin-left: 1em;
-    position: relative;
-    top: 10px;
-
-    &:hover {
-      color: $dark-gray;
-    }
-  }
-
-  .notebook {
-    margin-left: 1em;
-    margin: 0.7em;
-  }
-
-  .launcher-label {
-    vertical-align: bottom;
-  }
-}
diff --git a/reana-ui/src/pages/workflowDetails/components/index.js b/reana-ui/src/pages/workflowDetails/components/index.js
index 01dba896..5091c388 100644
--- a/reana-ui/src/pages/workflowDetails/components/index.js
+++ b/reana-ui/src/pages/workflowDetails/components/index.js
@@ -2,16 +2,14 @@
   -*- coding: utf-8 -*-
 
   This file is part of REANA.
-  Copyright (C) 2020, 2022 CERN.
+  Copyright (C) 2020, 2022, 2023, 2024 CERN.
 
   REANA is free software; you can redistribute it and/or modify it
   under the terms of the MIT License; see LICENSE file for more details.
 */
 
 export { default as WorkflowLogs } from "./WorkflowLogs";
-export { default as WorkflowInfo } from "./WorkflowInfo";
 export { default as WorkflowFiles } from "./WorkflowFiles";
 export { default as WorkflowProgress } from "./WorkflowProgress";
 export { default as WorkflowRetentionRules } from "./WorkflowRetentionRules";
 export { default as WorkflowSpecification } from "./WorkflowSpecification";
-export { default as LauncherLabel } from "./LauncherLabel";
diff --git a/reana-ui/src/pages/workflowList/WorkflowList.js b/reana-ui/src/pages/workflowList/WorkflowList.js
index 55691aa3..a442e426 100644
--- a/reana-ui/src/pages/workflowList/WorkflowList.js
+++ b/reana-ui/src/pages/workflowList/WorkflowList.js
@@ -132,7 +132,7 @@ function Workflows() {
   );
 
   return (
-    <div className={`${styles.container} ${styles["workflow-list-container"]}`}>
+    <div className={styles.container}>
       <Container text>
         <Title className={styles.title}>
           <span>Your workflows</span>
diff --git a/reana-ui/src/pages/workflowList/components/WorkflowBadges.js b/reana-ui/src/pages/workflowList/components/WorkflowBadges.js
deleted file mode 100644
index 3bd4b2d8..00000000
--- a/reana-ui/src/pages/workflowList/components/WorkflowBadges.js
+++ /dev/null
@@ -1,75 +0,0 @@
-import styles from "~/pages/workflowList/components/WorkflowBadges.module.scss";
-import { Divider, Label } from "semantic-ui-react";
-import { JupyterNotebookIcon, WorkflowActionsPopup } from "~/components";
-import { INTERACTIVE_SESSION_URL } from "~/client";
-import { LauncherLabel } from "~/pages/workflowDetails/components";
-import { getReanaToken } from "~/selectors";
-import { useSelector } from "react-redux";
-import { statusMapping } from "~/util";
-
-export default function WorkflowBadges({ workflow, withDivider = true }) {
-  const reanaToken = useSelector(getReanaToken);
-  const {
-    id,
-    size,
-    launcherURL,
-    session_uri: sessionUri,
-    session_status: sessionStatus,
-  } = workflow;
-  const hasDiskUsage = size.raw > 0;
-  const isSessionOpen = sessionStatus === "created";
-
-  return (
-    <>
-      <Divider className={styles.divider}></Divider>
-      <div className={styles["badges-and-actions"]}>
-        <div className={styles.badgesContainer}>
-          {workflow.duration && (
-            <Label
-              size="tiny"
-              content={workflow.duration}
-              icon="clock"
-              as="a"
-              href={"/details/" + id}
-              target="_blank"
-              rel="noopener noreferrer"
-              color={statusMapping[workflow.status].color}
-              onClick={(e) => e.stopPropagation()}
-            />
-          )}
-          {hasDiskUsage && (
-            <Label
-              size="tiny"
-              content={size.human_readable}
-              icon="hdd"
-              as="a"
-              href={"/details/" + id}
-              target="_blank"
-              rel="noopener noreferrer"
-              onClick={(e) => e.stopPropagation()}
-            />
-          )}
-          {isSessionOpen && (
-            <Label
-              size="tiny"
-              content={" Notebook"}
-              icon={<JupyterNotebookIcon size={12} />}
-              as="a"
-              href={INTERACTIVE_SESSION_URL(sessionUri, reanaToken)}
-              target="_blank"
-              rel="noopener noreferrer"
-              onClick={(e) => e.stopPropagation()}
-            />
-          )}
-          <LauncherLabel url={launcherURL} />
-        </div>
-        <div className={styles.actionsContainer}>
-          <WorkflowActionsPopup
-            workflow={workflow}
-            className={`${styles.actions} ${styles["always-visible"]}`}
-          />
-        </div>
-      </div>
-    </>
-  );
-}
diff --git a/reana-ui/src/pages/workflowList/components/WorkflowBadges.module.scss b/reana-ui/src/pages/workflowList/components/WorkflowBadges.module.scss
deleted file mode 100644
index 538886f7..00000000
--- a/reana-ui/src/pages/workflowList/components/WorkflowBadges.module.scss
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-  -*- coding: utf-8 -*-
-
-  This file is part of REANA.
-  Copyright (C) 2023 CERN.
-
-  REANA is free software; you can redistribute it and/or modify it
-  under the terms of the MIT License; see LICENSE file for more details.
-*/
-
-.divider {
-  margin: 0 !important;
-  border-color: #f8f8f8 !important;
-}
-
-.badges-and-actions {
-  display: flex;
-  justify-content: space-between;
-  width: 100%;
-  padding: 0.75em 1em;
-
-  .actions {
-    min-width: 22px;
-
-    &:hover {
-      color: #d1d1d1;
-    }
-
-    &.always-visible {
-      visibility: visible;
-    }
-  }
-}
-
-.badgesContainer {
-  display: flex;
-
-  a.label {
-    background-color: transparent;
-    margin-left: 15px;
-
-    &:hover {
-      cursor: pointer;
-      filter: opacity(0.8);
-    }
-
-    &:not(:first-child) {
-      margin-left: 15px;
-    }
-  }
-}
diff --git a/reana-ui/src/pages/workflowList/components/WorkflowList.js b/reana-ui/src/pages/workflowList/components/WorkflowList.js
index 43d181e5..f8bc70f4 100644
--- a/reana-ui/src/pages/workflowList/components/WorkflowList.js
+++ b/reana-ui/src/pages/workflowList/components/WorkflowList.js
@@ -8,15 +8,21 @@
   under the terms of the MIT License; see LICENSE file for more details.
 */
 
-import { Loader, Message } from "semantic-ui-react";
+import { Loader, Message, Divider } from "semantic-ui-react";
 import PropTypes from "prop-types";
 import { Link } from "react-router-dom";
 
-import { Box, WorkflowDeleteModal, WorkflowStopModal, InteractiveSessionModal } from "~/components";
+import {
+  Box,
+  WorkflowBadges,
+  WorkflowInfo,
+  WorkflowDeleteModal,
+  WorkflowStopModal,
+  WorkflowActionsPopup,
+  InteractiveSessionModal,
+} from "~/components";
 
 import styles from "./WorkflowList.module.scss";
-import WorkflowDetails from "~/pages/workflowList/components/WorkflowDetails";
-import WorkflowBadges from "~/pages/workflowList/components/WorkflowBadges";
 
 export default function WorkflowList({ workflows, loading }) {
   if (loading) return <Loader active />;
@@ -30,10 +36,19 @@ export default function WorkflowList({ workflows, loading }) {
           <Box padding={false} flex={false}>
             <Link key={workflow.id} to={`/details/${workflow.id}`}>
               <div className={styles["workflow-details-container"]}>
-                <WorkflowDetails workflow={workflow} actionsOnHover={true} />
+                <WorkflowInfo workflow={workflow} actionsOnHover={true} />
               </div>
             </Link>
-            <WorkflowBadges workflow={workflow} />
+            <Divider className={styles.divider}></Divider>
+            <div className={styles["badges-and-actions"]}>
+              <WorkflowBadges workflow={workflow} />
+              <div className={styles.actionsContainer}>
+                <WorkflowActionsPopup
+                  workflow={workflow}
+                  className={`${styles.actions} ${styles["always-visible"]}`}
+                />
+              </div>
+            </div>
           </Box>
         );
       })}
diff --git a/reana-ui/src/pages/workflowList/components/WorkflowList.module.scss b/reana-ui/src/pages/workflowList/components/WorkflowList.module.scss
index defe5a2e..ad8b5ddf 100644
--- a/reana-ui/src/pages/workflowList/components/WorkflowList.module.scss
+++ b/reana-ui/src/pages/workflowList/components/WorkflowList.module.scss
@@ -2,7 +2,7 @@
   -*- coding: utf-8 -*-
 
   This file is part of REANA.
-  Copyright (C) 2020, 2021, 2022, 2023 CERN.
+  Copyright (C) 2020, 2021, 2022, 2023, 2024 CERN.
 
   REANA is free software; you can redistribute it and/or modify it
   under the terms of the MIT License; see LICENSE file for more details.
@@ -15,6 +15,31 @@
   justify-content: space-between;
 }
 
+.divider {
+  margin: 0 !important;
+  border-color: #f8f8f8 !important;
+}
+
+.badges-and-actions {
+  display: flex;
+  justify-content: space-between;
+  width: 100%;
+  padding: 0.75em 1em;
+
+  .actions {
+    min-width: 22px;
+    cursor: pointer;
+
+    &:hover {
+      color: #d1d1d1;
+    }
+
+    &.always-visible {
+      visibility: visible;
+    }
+  }
+}
+
 .workflow-details-container {
   padding: 1em;
   &:hover {