-
-
-
-
{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 17c531ec..27902bf7 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,
@@ -143,13 +144,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 a74780e0..9290fc82 100644
--- a/reana-ui/src/pages/workflowList/components/WorkflowList.js
+++ b/reana-ui/src/pages/workflowList/components/WorkflowList.js
@@ -32,7 +32,12 @@ export default function WorkflowList({ workflows, loading }) {
<>
{workflows.map((workflow) => {
return (
-
+
@@ -41,12 +46,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;
}
}
diff --git a/reana-ui/src/reducers.js b/reana-ui/src/reducers.js
index 0a09de96..04ac36c7 100644
--- a/reana-ui/src/reducers.js
+++ b/reana-ui/src/reducers.js
@@ -2,7 +2,7 @@
-*- coding: utf-8 -*-
This file is part of REANA.
- Copyright (C) 2020, 2022, 2023 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.