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 ( + <> +
+ {workflow.duration && ( +
+ + ); +} 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 ( - + +
+ +
+ +
+
-
-
- -
- {name} - #{run} - {isSessionOpen && ( - e.stopPropagation()} - className={styles.notebook} - > - - - )} - - - - - {friendlyFinished - ? `Finished ${friendlyFinished}` - : friendlyStarted - ? `Started ${friendlyStarted}` - : `Created ${friendlyCreated}`} -
- } - content={ - friendlyFinished - ? finishedDate - : friendlyStarted - ? startedDate - : createdDate - } - /> -
- -
-
-
- - {status} - {" "} - {statusMapping[status].preposition} {duration} - {NON_FINISHED_STATUSES.includes(status) && ( - window.location.reload()} - /> - )} -
-
- step {completed}/{total} -
-
- -
-
- - - ); -} - -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 ( -
+
<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 {