Skip to content

Commit ddbbb1a

Browse files
committed
Replace task state icons with badges in sidebar
1 parent 2d3f25e commit ddbbb1a

File tree

6 files changed

+137
-159
lines changed

6 files changed

+137
-159
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<!--
2+
Copyright (C) NIWA & British Crown (Met Office) & Contributors.
3+
4+
This program is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
-->
17+
18+
<template>
19+
<div
20+
class="task-state-badge d-flex justify-center align-center px-1 font-weight-medium"
21+
:class="state"
22+
v-tooltip="{ text: tooltip, openDelay: 400, location: 'top' }"
23+
>
24+
{{ value > 99 ? '99+' : value }}
25+
</div>
26+
</template>
27+
28+
<script setup>
29+
import { computed } from 'vue'
30+
31+
const props = defineProps({
32+
state: {
33+
type: String,
34+
required: true
35+
},
36+
value: {
37+
type: Number,
38+
required: true,
39+
},
40+
})
41+
42+
const tooltip = computed(
43+
() => `${props.value} ${props.state} task${props.value > 1 ? 's' : ''}`
44+
)
45+
</script>

src/components/cylc/WarningIcon.vue

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
2626

2727
<template>
2828
<span
29-
class="c-warn"
29+
class="c-warn d-inline-flex"
3030
:class="{'active': workflow.node.warningActive}"
31-
style="display: inline-block;"
3231
>
3332
<v-tooltip
3433
:activator="null"
@@ -45,7 +44,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
4544
@click="deactivate"
4645
@click.prevent
4746
style="
48-
vertical-align: middle;
4947
cursor: pointer;
5048
"
5149
:style="[workflow.node.logRecords?.length ? {opacity: 1} : {opacity: 0.3}]"

src/components/cylc/tree/GScanTreeItem.vue

Lines changed: 17 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -47,37 +47,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
4747
</span>
4848
</div>
4949
<div class="d-flex text-right c-gscan-workflow-states flex-grow-0">
50-
<!-- task summary tooltips -->
51-
<!-- a v-tooltip does not work directly set on Cylc job component, so we use a div to wrap it -->
52-
<div
53-
class="ma-0 pa-0"
54-
min-width="0"
55-
min-height="0"
56-
style="font-size: 120%; width: auto;"
57-
>
58-
<WarningIcon v-if="workflowWarnings" :workflow="node" />
59-
</div>
60-
<div
61-
v-for="[state, tasks] in Object.entries(descendantTaskInfo.latestTasks)"
62-
:key="`${node.id}-${state}`"
63-
:class="getTaskStateClass(descendantTaskInfo.stateTotals, state)"
64-
class="ma-0 pa-0"
65-
min-width="0"
66-
min-height="0"
67-
style="font-size: 120%; width: auto;"
68-
>
69-
<Job :status="state" />
70-
<v-tooltip location="top">
71-
<!-- tooltip text -->
72-
<div class="text-grey-lighten-1">
73-
{{ descendantTaskInfo.stateTotals[state] ?? 0 }} {{ state }}. Recent {{ state }} tasks:
74-
</div>
75-
<div v-for="(task, index) in tasks.slice(0, $options.maxTasksDisplayed)" :key="index">
76-
{{ task }}<br v-if="index !== tasks.length - 1" />
77-
</div>
78-
</v-tooltip>
79-
</div>
50+
<WarningIcon
51+
v-if="workflowWarnings"
52+
:workflow="node"
53+
style="font-size: 120%;"
54+
/>
8055
</div>
56+
<template
57+
v-for="state in Object.keys(descendantTaskInfo.latestTasks)"
58+
:key="`${node.id}-${state}`"
59+
>
60+
<TaskStateBadge
61+
v-if="descendantTaskInfo.stateTotals[state]"
62+
:state="state"
63+
:value="descendantTaskInfo.stateTotals[state]"
64+
/>
65+
</template>
8166
</div>
8267
</v-list-item>
8368

@@ -95,7 +80,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
9580
</template>
9681

9782
<script>
98-
import Job from '@/components/cylc/Job.vue'
83+
import TaskStateBadge from '@/components/cylc/TaskStateBadge.vue'
9984
import WorkflowIcon from '@/components/cylc/gscan/WorkflowIcon.vue'
10085
import TreeItem from '@/components/cylc/tree/TreeItem.vue'
10186
import WarningIcon from '@/components/cylc/WarningIcon.vue'
@@ -150,7 +135,7 @@ export default {
150135
name: 'GScanTreeItem',
151136
152137
components: {
153-
Job,
138+
TaskStateBadge,
154139
TreeItem,
155140
WarningIcon,
156141
WorkflowIcon,
@@ -203,14 +188,6 @@ export default {
203188
}
204189
},
205190
206-
methods: {
207-
getTaskStateClass (stateTotals, state) {
208-
return {
209-
'empty-state': !stateTotals[state]
210-
}
211-
},
212-
},
213-
214191
nodeTypes: ['workflow-part', 'workflow'],
215192
maxTasksDisplayed: 5,
216193
WorkflowState,

src/components/cylc/workspace/Toolbar.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
4545

4646
<!-- control bar elements displayed only when there is a current workflow in the store -->
4747
<template v-if="currentWorkflow">
48-
<div class="c-workflow-controls flex-shrink-0">
48+
<div class="c-workflow-controls d-flex align-center flex-shrink-0">
4949
<WarningIcon
5050
:workflow="currentWorkflow"
5151
style="font-size: 120%; padding-right: 0.3em;"

src/styles/cylc/_job.scss

Lines changed: 65 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -15,131 +15,89 @@
1515
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1616
*/
1717

18+
@use "sass:list";
19+
1820
/* css namespace for job element */
1921
$cjob: ".c-job .job rect";
2022

21-
2223
#{$cjob} {
2324
/* if no job status display nothing */
2425
fill: transparent;
2526
stroke: transparent;
2627
}
2728

28-
.c-job {
29-
.job {
30-
vertical-align: middle;
31-
/* scale the icon to the font-size */
32-
width: 1em;
33-
height: 1em;
34-
}
29+
.c-job .job {
30+
/* scale the icon to the font-size */
31+
width: 1em;
32+
height: 1em;
3533
}
3634

37-
@mixin job_theme($theme) {
38-
@if $theme == "default" {
39-
$teal: rgb(109,213,194);
40-
$blue: rgb(106,164,241);
41-
$green: rgb(81,175,81);
42-
$red: rgb(207,72,72);
43-
$pink: rgb(190,106,192);
44-
45-
#{$cjob} {
46-
&.submitted {
47-
fill: $teal;
48-
stroke: $teal;
49-
}
50-
51-
&.running {
52-
fill: $blue;
53-
stroke: $blue;
54-
}
55-
56-
&.succeeded {
57-
fill: $green;
58-
stroke: $green;
59-
}
60-
61-
&.failed {
62-
fill: $red;
63-
stroke: $red;
64-
}
65-
66-
&.submit-failed {
67-
fill: $pink;
68-
stroke: $pink;
69-
}
70-
}
71-
} @else if $theme == "greyscale" {
72-
$light: rgb(208,208,208);
73-
$medium: rgb(133,133,133);
74-
$dark: rgb(0,0,0);
75-
76-
#{$cjob} {
77-
&.submitted {
78-
fill: transparent;
79-
stroke: $light;
80-
}
81-
82-
&.running {
83-
fill: $light;
84-
stroke: $light;
85-
}
86-
87-
&.succeeded {
88-
fill: $medium;
89-
stroke: $medium;
90-
}
91-
92-
&.failed {
93-
fill: $dark;
94-
stroke: $dark;
95-
}
96-
97-
&.submit-failed {
98-
fill: transparent;
99-
stroke: $dark;
100-
}
101-
}
102-
} @else if $theme == "colour_blind" {
103-
$grey: rgb(152,152,152);
104-
$success: rgb(108,218,255);
105-
$error: rgb(146,0,0);
106-
107-
#{$cjob} {
108-
&.submitted {
109-
fill: transparent;
110-
stroke: $grey;
111-
}
112-
113-
&.running {
114-
fill: $grey;
115-
stroke: $grey;
116-
}
117-
118-
&.succeeded {
119-
fill: $success;
120-
stroke: $success;
121-
}
122-
123-
&.failed {
124-
fill: $error;
125-
stroke: $error;
126-
}
127-
128-
&.submit-failed {
129-
fill: transparent;
130-
stroke: $error;
131-
}
132-
}
133-
}
35+
.task-state-badge {
36+
font-size: 0.7em;
37+
height: 1.8em;
38+
min-width: 1.8em;
39+
border-radius: 1.8em;
40+
border: 2px solid;
41+
margin: 0 0.1em;
42+
line-height: normal;
13443
}
13544

136-
@each $theme in "default", "greyscale", "colour_blind" {
45+
$teal: rgb(109,213,194);
46+
$blue: rgb(106,164,241);
47+
$green: rgb(81,175,81);
48+
$red: rgb(207,72,72);
49+
$pink: rgb(190,106,192);
50+
51+
$light: rgb(208,208,208);
52+
$medium: rgb(133,133,133);
53+
$dark: rgb(0,0,0);
54+
55+
$grey: rgb(152,152,152);
56+
$success: rgb(108,218,255);
57+
$error: rgb(146,0,0);
58+
59+
// Mapping of job themes to job states to (fill, outline, text) colors
60+
$themes: (
61+
"default": (
62+
"submitted": ($teal, $teal, white),
63+
"running": ($blue, $blue, white),
64+
"succeeded": ($green, $green, white),
65+
"failed": ($red, $red, white),
66+
"submit-failed": ($pink, $pink, white),
67+
),
68+
"greyscale": (
69+
"submitted": (transparent, $light, black),
70+
"running": ($light, $light, black),
71+
"succeeded": ($medium, $medium, white),
72+
"failed": ($dark, $dark, white),
73+
"submit-failed": (transparent, $dark, black),
74+
),
75+
"colour_blind": (
76+
"submitted": (transparent, $grey, black),
77+
"running": ($grey, $grey, white),
78+
"succeeded": ($success, $success, black),
79+
"failed": ($error, $error, white),
80+
"submit-failed": (transparent, $error, black),
81+
),
82+
);
83+
84+
@each $theme, $state_map in $themes {
13785
.job_theme--#{$theme} {
13886
&, // job theme as configured by the top-level application
13987
&.job_theme_override {
14088
// if overridden elsewhere the new value should take priority
14189
// (this allows us to override the theme in the user profile)
142-
@include job_theme($theme);
90+
@each $state, $colors in $state_map {
91+
#{$cjob}.#{$state} {
92+
fill: list.nth($colors, 1);
93+
stroke: list.nth($colors, 2);
94+
}
95+
.task-state-badge.#{$state} {
96+
background-color: list.nth($colors, 1);
97+
border-color: list.nth($colors, 2);
98+
color: list.nth($colors, 3);
99+
}
100+
}
143101
}
144102
}
145103
}

tests/e2e/specs/userprofile.cy.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,19 @@ describe('User Profile', () => {
6666
}
6767
})
6868

69-
it('Sets the job theme', () => {
69+
it('Sets the task/job theme', () => {
7070
cy.get('#input-job-theme-default')
7171
.click({ force: true })
72-
// set the job theme to normal
73-
cy.get('.c-gscan:first .c-job:first rect:first')
74-
.should('have.css', 'fill')
72+
// set the theme to normal
73+
cy.get('.c-gscan .task-state-badge.running').as('taskBadge')
74+
.should('have.css', 'background-color')
7575
.then(($fill1) => {
76-
// set the job theme to greyscale
76+
// set the theme to greyscale
7777
cy.get('#input-job-theme-greyscale')
7878
.click({ force: true })
79-
cy.get('.c-gscan:first .c-job:first rect:first')
80-
.should('have.css', 'fill')
81-
// make sure that the job has changed colour
79+
cy.get('@taskBadge')
80+
.should('have.css', 'background-color')
81+
// make sure that the task state badge has changed colour
8282
.then(($fill2) => {
8383
expect($fill1).not.to.equal($fill2)
8484
})

0 commit comments

Comments
 (0)