@@ -40,15 +40,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
4040 <div class =" c-gscan-workflow-name flex-grow-1" >
4141 <span >
4242 {{ node.name || node.id }}
43- <v-tooltip
44- location =" top"
45- style =" overflow-wrap : anywhere;"
46- >
43+ <v-tooltip style =" overflow-wrap : anywhere;" >
4744 {{ node.id }}
4845 </v-tooltip >
4946 </span >
5047 </div >
51- <div class =" d-flex c-gscan-workflow-states flex-grow-0" >
48+ <div class =" d-flex c-gscan-workflow-states flex-grow-0 align-center" >
49+ <v-icon
50+ v-for =" modifier in statesInfo.modifiers"
51+ :key =" modifier"
52+ :icon =" modifierIcons[modifier]"
53+ v-tooltip =" `Has ${modifier} tasks.`"
54+ size =" 1em"
55+ class =" modifier-badge"
56+ :class =" modifier"
57+ />
5258 <TaskStateBadge
5359 v-for =" (value, state) in statesInfo.stateTotals"
5460 :key =" state"
@@ -86,6 +92,7 @@ import TreeItem from '@/components/cylc/tree/TreeItem.vue'
8692import WarningIcon from ' @/components/cylc/WarningIcon.vue'
8793import TaskState from ' @/model/TaskState.model'
8894import { WorkflowState } from ' @/model/WorkflowState.model'
95+ import { taskHeld , taskRetry } from ' @/utils/icons'
8996import { useCompactMode , useWorkflowWarnings } from ' @/composables/localStorage'
9097
9198const nodeTypes = [' workflow-part' , ' workflow' ]
@@ -98,27 +105,40 @@ const taskStatesOrdered = [
98105 TaskState .RUNNING .name ,
99106]
100107
108+ const modifierIcons = {
109+ held: taskHeld,
110+ retrying: taskRetry,
111+ }
112+
101113/**
102114 * Get aggregated task state totals for all descendents of a node.
103115 *
104116 * Also get latest state tasks for workflow nodes.
105117 *
106118 * @param {Object} node
107119 * @param {Record<string, number>} stateTotals - Accumulator for state totals.
120+ * @param {Set<string>} modifiers - Accumulator for modifier states.
108121 */
109- function getStatesInfo (node , stateTotals = {}) {
122+ function getStatesInfo (node , stateTotals = {}, modifiers = new Set () ) {
110123 const latestTasks = {}
111124 // if we aren't at the end of the node tree, continue recurse until we hit something other then a workflow part
112125 if (node .type === ' workflow-part' && node .children ) {
113126 // at every branch, recurse all child nodes except stopped workflows
114127 for (const child of node .children ) {
115128 if (child .node .status !== WorkflowState .STOPPED .name ) {
116- getStatesInfo (child, stateTotals, latestTasks )
129+ getStatesInfo (child, stateTotals, modifiers )
117130 }
118131 }
119132 } else if (node .type === ' workflow' && node .node .stateTotals ) {
120133 // if we hit a workflow node, stop and merge state
121134
135+ if (node .node .containsHeld ) {
136+ modifiers .add (' held' )
137+ }
138+ if (node .node .containsRetry ) {
139+ modifiers .add (' retrying' )
140+ }
141+
122142 // the non-zero state totals from this node with all the others from the tree
123143 for (const state of taskStatesOrdered) {
124144 let nodeTotal = node .node .stateTotals [state]
@@ -138,7 +158,7 @@ function getStatesInfo (node, stateTotals = {}) {
138158 }
139159 }
140160 }
141- return { stateTotals, latestTasks }
161+ return { stateTotals, latestTasks, modifiers }
142162}
143163
144164const workflowWarnings = useWorkflowWarnings ()
0 commit comments