From 537c8ae04d88a7269ae507479d5c3f5bd2473d17 Mon Sep 17 00:00:00 2001 From: Marco Donadoni Date: Mon, 22 Apr 2024 15:26:30 +0200 Subject: [PATCH] chore: rebase and make final changes to badge redesign (#394) - Make non-clickable badges more subtle. - Make progress bar smaller and place it close to the step counter. - Fix alignment and spacing of some elements. --- reana-ui/src/components/Box.js | 2 +- reana-ui/src/components/Box.module.scss | 7 +- reana-ui/src/components/LauncherLabel.js | 2 +- .../src/components/WorkflowActionsPopup.js | 9 +- .../WorkflowActionsPopup.module.scss | 20 +-- reana-ui/src/components/WorkflowBadges.js | 85 +++++++------ .../src/components/WorkflowBadges.module.scss | 14 +-- reana-ui/src/components/WorkflowInfo.js | 86 ++++++------- .../src/components/WorkflowInfo.module.scss | 25 ++-- .../components/WorkflowProgressCircleBar.js | 119 ++++++++++-------- .../WorkflowProgressCircleBar.module.scss | 55 +++++--- .../src/pages/launchOnReana/LaunchOnReana.js | 4 +- .../pages/workflowDetails/WorkflowDetails.js | 21 +++- .../WorkflowDetails.module.scss | 34 ++++- .../workflowList/components/WorkflowList.js | 14 +-- .../components/WorkflowList.module.scss | 22 +--- 16 files changed, 264 insertions(+), 255 deletions(-) diff --git a/reana-ui/src/components/Box.js b/reana-ui/src/components/Box.js index f4302f68..64d7a602 100644 --- a/reana-ui/src/components/Box.js +++ b/reana-ui/src/components/Box.js @@ -1,6 +1,6 @@ /* This file is part of REANA. - Copyright (C) 2022 CERN. + Copyright (C) 2022, 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/Box.module.scss b/reana-ui/src/components/Box.module.scss index 82e9b035..c11f5aae 100644 --- a/reana-ui/src/components/Box.module.scss +++ b/reana-ui/src/components/Box.module.scss @@ -1,6 +1,6 @@ /* This file is part of REANA. - Copyright (C) 2022 CERN. + Copyright (C) 2022, 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. @@ -12,7 +12,6 @@ color: $raven; border: 5px solid $sepia; margin: 1rem 0; - padding: 0; &.padding { padding: 1em 1em; @@ -22,8 +21,4 @@ display: flex; justify-content: space-between; } - - &.wrap { - flex-wrap: wrap; - } } diff --git a/reana-ui/src/components/LauncherLabel.js b/reana-ui/src/components/LauncherLabel.js index 85415dae..3d8567d1 100644 --- a/reana-ui/src/components/LauncherLabel.js +++ b/reana-ui/src/components/LauncherLabel.js @@ -1,6 +1,6 @@ /* This file is part of REANA. - Copyright (C) 2022 CERN. + Copyright (C) 2022, 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/WorkflowActionsPopup.js b/reana-ui/src/components/WorkflowActionsPopup.js index 2e056d73..05653438 100644 --- a/reana-ui/src/components/WorkflowActionsPopup.js +++ b/reana-ui/src/components/WorkflowActionsPopup.js @@ -47,7 +47,6 @@ export default function WorkflowActionsPopup({ workflow, className }) { onClick: (e) => { dispatch(openInteractiveSessionModal(workflow)); setOpen(false); - e.stopPropagation(); }, }); } @@ -60,7 +59,6 @@ export default function WorkflowActionsPopup({ workflow, className }) { onClick: (e) => { dispatch(closeInteractiveSession(id)); setOpen(false); - e.stopPropagation(); }, }); } @@ -73,7 +71,6 @@ export default function WorkflowActionsPopup({ workflow, className }) { onClick: (e) => { dispatch(openStopWorkflowModal(workflow)); setOpen(false); - e.stopPropagation(); }, }); } @@ -86,7 +83,6 @@ export default function WorkflowActionsPopup({ workflow, className }) { onClick: (e) => { dispatch(openDeleteWorkflowModal(workflow)); setOpen(false); - e.stopPropagation(); }, }); } @@ -99,23 +95,22 @@ export default function WorkflowActionsPopup({ workflow, className }) { onClick: (e) => { dispatch(deleteWorkflow(id)); setOpen(false); - e.stopPropagation(); }, }); } return ( -
+
{menuItems.length > 0 && ( { setOpen(true); - e.preventDefault(); }} /> } diff --git a/reana-ui/src/components/WorkflowActionsPopup.module.scss b/reana-ui/src/components/WorkflowActionsPopup.module.scss index c772e469..0ce8f344 100644 --- a/reana-ui/src/components/WorkflowActionsPopup.module.scss +++ b/reana-ui/src/components/WorkflowActionsPopup.module.scss @@ -2,7 +2,7 @@ -*- coding: utf-8 -*- This file is part of REANA. - Copyright (C) 2020, 2022 CERN. + Copyright (C) 2020, 2022, 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. @@ -10,24 +10,6 @@ @import "@palette"; -:global(.icon).icon { - display: flex; - align-items: center; - justify-content: center; - height: 100%; - color: $gray; - - &:hover { - color: $dark-gray; - } -} - -.container { - cursor: pointer; - min-width: 22px; - margin-left: 2em; -} - .jupyter-icon { width: 1.18em; float: right; diff --git a/reana-ui/src/components/WorkflowBadges.js b/reana-ui/src/components/WorkflowBadges.js index 5206edeb..5bf13a46 100644 --- a/reana-ui/src/components/WorkflowBadges.js +++ b/reana-ui/src/components/WorkflowBadges.js @@ -1,3 +1,13 @@ +/* + -*- coding: utf-8 -*- + + This file is part of REANA. + 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. +*/ + import styles from "./WorkflowBadges.module.scss"; import { Label } from "semantic-ui-react"; import { JupyterNotebookIcon } from "~/components"; @@ -5,12 +15,10 @@ 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, @@ -20,44 +28,39 @@ export default function WorkflowBadges({ workflow }) { const isSessionOpen = sessionStatus === "created"; return ( - <> -
- {workflow.duration && ( -
- +
+ {workflow.duration && ( +
); } diff --git a/reana-ui/src/components/WorkflowBadges.module.scss b/reana-ui/src/components/WorkflowBadges.module.scss index 91cacb1e..764597dc 100644 --- a/reana-ui/src/components/WorkflowBadges.module.scss +++ b/reana-ui/src/components/WorkflowBadges.module.scss @@ -2,22 +2,18 @@ -*- 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. */ +@import "@palette"; .badgesContainer { display: flex; + gap: 5px; - a:global(.label) { - margin-left: 15px; - gap: 10px; - - &:hover { - cursor: pointer; - filter: opacity(0.8); - } + :global(.ui.basic.label) { + color: $raven; } } diff --git a/reana-ui/src/components/WorkflowInfo.js b/reana-ui/src/components/WorkflowInfo.js index 2f1eec95..2fd83380 100644 --- a/reana-ui/src/components/WorkflowInfo.js +++ b/reana-ui/src/components/WorkflowInfo.js @@ -32,55 +32,47 @@ export default function WorkflowInfo({ workflow }) { } = workflow; return ( -
-
-
- -
- {name} - #{run} - - {friendlyFinished - ? `Finished ${friendlyFinished}` - : friendlyStarted - ? `Started ${friendlyStarted}` - : `Created ${friendlyCreated}`} -
- } - content={ - friendlyFinished - ? finishedDate +
+
+ +
+ {name} + #{run} + + {friendlyFinished + ? `Finished ${friendlyFinished}` : friendlyStarted - ? startedDate - : createdDate - } - /> -
+ ? `Started ${friendlyStarted}` + : `Created ${friendlyCreated}`} +
+ } + content={ + friendlyFinished + ? finishedDate + : friendlyStarted + ? startedDate + : createdDate + } + />
-
-
- - {status} - {" "} -
- step {completed}/{total} -
-
-
- -
+
+
+ + {status} + +
+ + step {completed}/{total} + +
diff --git a/reana-ui/src/components/WorkflowInfo.module.scss b/reana-ui/src/components/WorkflowInfo.module.scss index a57b13cd..d7f9e204 100644 --- a/reana-ui/src/components/WorkflowInfo.module.scss +++ b/reana-ui/src/components/WorkflowInfo.module.scss @@ -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. @@ -10,19 +10,12 @@ @import "@palette"; -.flexbox { +.workflow-info { display: flex; justify-content: space-between; -} - -.workflow { color: $raven; font-size: 1.15rem; - &.deleted { - opacity: 0.5; - } - .details-box { display: flex; align-items: baseline; @@ -31,7 +24,7 @@ word-wrap: anywhere; .status-icon { - padding-right: 20px; + margin-right: 5px; } .name { @@ -39,7 +32,7 @@ } .run { - padding-left: 0.8em; + margin-left: 0.8em; } } @@ -54,15 +47,13 @@ } .status-box { - width: 210px; flex-shrink: 0; - display: flex; - justify-content: flex-end; text-align: right; } - .progressbar-container { - width: 80px; - padding: 0 10px; + .progress-box { + display: flex; + align-items: center; + gap: 0.4em; } } diff --git a/reana-ui/src/components/WorkflowProgressCircleBar.js b/reana-ui/src/components/WorkflowProgressCircleBar.js index 67d2e2a5..0baa2e54 100644 --- a/reana-ui/src/components/WorkflowProgressCircleBar.js +++ b/reana-ui/src/components/WorkflowProgressCircleBar.js @@ -11,89 +11,98 @@ import PropTypes from "prop-types"; import styles from "./WorkflowProgressCircleBar.module.scss"; -export default function WorkflowProgressCircleBar({ workflow }) { - const { completed, failed, running, total, status } = workflow; +export default function WorkflowProgressCircleBar({ + workflow, + strokeWidth = 22, + size = "1em", +}) { + const { completed, failed, running: started, total, status } = workflow; - const size = 80; - const strokeWidth = 10; - const radius = (size - strokeWidth) / 2; - const circumference = 2 * Math.PI * radius; + // running also includes the completed and failed steps + const running = started - completed - failed; - let lengthFinishedArc = (completed / total) * circumference; - let lengthRunningArc = (running / total) * circumference; - let lengthFailedArc = (failed / total) * circumference; - // Explicitly set the size of the progress bar for workflows that - // are not running to avoid dealing with undefined number of steps - const TERMINAL_STATUSES = ["finished", "failed", "stopped"]; - const PREPARING_STATUSES = ["created", "queued", "pending"]; - if (TERMINAL_STATUSES.includes(status)) { - lengthRunningArc = 0; - } - if (PREPARING_STATUSES.includes(status)) { - lengthFinishedArc = 0; - lengthRunningArc = 0; - lengthFailedArc = 0; - } + const viewBoxSize = 100; + const radius = (viewBoxSize - strokeWidth) / 2; + + // length of the arcs, as fractions of the total number of steps + let lengthFinishedArc = total ? (completed ?? 0) / total : 0; + let lengthFailedArc = total ? (failed ?? 0) / total : 0; + let lengthRunningArc = total ? (running ?? 0) / total : 0; // The workflow could be completely restored from the cache, in which case // the total number of steps would be 0. If the workflow is finished, we // want to show the full progress bar as finished even in this case. if (status === "finished") { - lengthFinishedArc = circumference; - lengthRunningArc = 0; + lengthFinishedArc = 1; lengthFailedArc = 0; + lengthRunningArc = 0; } + const calculateArcPath = (length, offset) => { + if (length >= 1) { + // cannot use 1 as otherwise the full circle would not be drawn + length = 0.9999; + } + + // start end end angles of the arc, in radians + // an arc with zero offset starts from the top (pi/2 radians) + const start_rad = Math.PI / 2 - offset * Math.PI * 2; + const end_rad = Math.PI / 2 - (offset + length) * Math.PI * 2; + + // y coordinates are subtracted and not added because the y axis points downwards + const start_x = viewBoxSize / 2 + radius * Math.cos(start_rad); + const start_y = viewBoxSize / 2 - radius * Math.sin(start_rad); + const end_x = viewBoxSize / 2 + radius * Math.cos(end_rad); + const end_y = viewBoxSize / 2 - radius * Math.sin(end_rad); + + // move to the center and draw the arc + return `M ${start_x} ${start_y} + A ${radius} ${radius} 0 ${length > 0.5 ? 1 : 0} 1 ${end_x} ${end_y} `; + }; + return ( -
+ - - - -
+ ); } diff --git a/reana-ui/src/components/WorkflowProgressCircleBar.module.scss b/reana-ui/src/components/WorkflowProgressCircleBar.module.scss index 4236806b..f39e7479 100644 --- a/reana-ui/src/components/WorkflowProgressCircleBar.module.scss +++ b/reana-ui/src/components/WorkflowProgressCircleBar.module.scss @@ -1,27 +1,26 @@ +/* + -*- coding: utf-8 -*- + + This file is part of REANA. + Copyright (C) 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. +*/ + @import "@palette"; .progress-bar-container { - svg { - width: 100%; - height: 100%; - transform: rotate(-90deg); - } + // inline-flex fixes the vertical alignment of svg images + display: inline-flex; circle { fill: none; transition: stroke-dasharray 0.35s ease; } - .progress-bar-running { - stroke: $sui-blue; - } - - .progress-bar-finished { - stroke: $sui-green; - } - - .progress-bar-failed { - stroke: $sui-red; + path { + fill: none; } .progress-bar-background, @@ -36,6 +35,30 @@ } .progress-bar-workflow-status-stopped { - stroke: $sui-yellow !important; + stroke: $sui-yellow; + + &.progress-bar-running { + stroke-dasharray: 10 8; + } + } + + .progress-bar-workflow-status-running { + stroke: $sui-blue; + + &.progress-bar-running { + stroke-dasharray: 10 8; + } + } + + .progress-bar-workflow-status-finished { + stroke: $sui-green; + } + + .progress-bar-workflow-status-failed { + stroke: $sui-red; + + &.progress-bar-failed { + stroke-dasharray: 10 8; + } } } diff --git a/reana-ui/src/pages/launchOnReana/LaunchOnReana.js b/reana-ui/src/pages/launchOnReana/LaunchOnReana.js index 4b867ec9..e391d861 100644 --- a/reana-ui/src/pages/launchOnReana/LaunchOnReana.js +++ b/reana-ui/src/pages/launchOnReana/LaunchOnReana.js @@ -1,6 +1,6 @@ /* This file is part of REANA. - Copyright (C) 2022 CERN. + Copyright (C) 2022, 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. @@ -168,7 +168,7 @@ export default function LaunchOnReana() { {isMissingRequiredParams(query) ? ( ) : ( - +
diff --git a/reana-ui/src/pages/workflowDetails/WorkflowDetails.js b/reana-ui/src/pages/workflowDetails/WorkflowDetails.js index 1f26dd8c..24e9d4d7 100644 --- a/reana-ui/src/pages/workflowDetails/WorkflowDetails.js +++ b/reana-ui/src/pages/workflowDetails/WorkflowDetails.js @@ -11,9 +11,10 @@ import { useCallback, useEffect, useRef } from "react"; import { useSelector, useDispatch } from "react-redux"; import { useParams } from "react-router-dom"; -import { Container, Dimmer, Loader, Tab } from "semantic-ui-react"; +import { Container, Dimmer, Icon, Loader, Tab } from "semantic-ui-react"; import { fetchWorkflow, fetchWorkflowLogs } from "~/actions"; +import { NON_FINISHED_STATUSES } from "~/config"; import { getWorkflow, getWorkflowRefresh, @@ -144,13 +145,23 @@ export default function WorkflowDetails() { return ( - -
- -
+
+ +
+ {NON_FINISHED_STATUSES.includes(workflow.status) && ( + window.location.reload()} + /> + )}
+
+ +
:first-child { + flex-grow: 1; + } + + .actions { + display: flex; + gap: 10px; + } +} + +.badges { + margin: 1rem 0; } diff --git a/reana-ui/src/pages/workflowList/components/WorkflowList.js b/reana-ui/src/pages/workflowList/components/WorkflowList.js index f8bc70f4..40eca422 100644 --- a/reana-ui/src/pages/workflowList/components/WorkflowList.js +++ b/reana-ui/src/pages/workflowList/components/WorkflowList.js @@ -33,7 +33,12 @@ export default function WorkflowList({ workflows, loading }) { <> {workflows.map((workflow) => { return ( - +
@@ -42,12 +47,7 @@ export default function WorkflowList({ workflows, loading }) {
-
- -
+
); diff --git a/reana-ui/src/pages/workflowList/components/WorkflowList.module.scss b/reana-ui/src/pages/workflowList/components/WorkflowList.module.scss index ad8b5ddf..4f98f1e6 100644 --- a/reana-ui/src/pages/workflowList/components/WorkflowList.module.scss +++ b/reana-ui/src/pages/workflowList/components/WorkflowList.module.scss @@ -15,9 +15,13 @@ justify-content: space-between; } +.deleted { + opacity: 0.5; +} + .divider { margin: 0 !important; - border-color: #f8f8f8 !important; + border-color: $sepia !important; } .badges-and-actions { @@ -25,27 +29,11 @@ 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 { background-color: lighten($sepia, 3%); - border-color: darken($sepia, 10%); - cursor: pointer; - color: $raven; } }