Skip to content

Commit ae7d429

Browse files
committed
Merge branch 'master' into userprofile
2 parents 1a4a512 + 5fd5523 commit ae7d429

File tree

19 files changed

+245
-214
lines changed

19 files changed

+245
-214
lines changed

changes.d/1802.fix.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed bug where task progress animations would reset when switching between tabs in the workspace.

cypress/component/cylc-icons.cy.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,15 @@ describe('Task component', () => {
103103
.should('have.css', 'animation-duration', `${MEAN_ELAPSED_TIME}s`)
104104
// the offset should be set to the "percent" of the expected job duration
105105
.should('have.css', 'animation-delay')
106-
.and('match', /([\d.]+)s/) // NOTE the delay should be negative
106+
.and('match', /([\d.-]+)s/)
107107
.then((number) => {
108-
// convert the duration string into a number that we can test
109-
cy.wrap(Number(number.match(/([\d.]+)s/)[1]))
108+
expect(parseInt(number)).to.be.closeTo(
110109
// ensure this number is ±5 from the expected value
111110
// (give it a little bit of margin to allow for timing error)
112-
.should('closeTo', MEAN_ELAPSED_TIME * (percent / 100), 5)
111+
// NOTE the delay should be negative
112+
-MEAN_ELAPSED_TIME * (percent / 100),
113+
5
114+
)
113115
})
114116
}
115117
})

cypress/component/utils/task.js

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,13 @@
1919
export const MEAN_ELAPSED_TIME = 10000
2020

2121
export function getStartTime (percent) {
22-
return String(
23-
new Date(
24-
// the current time in ms
25-
Date.now() -
26-
// minus the elapsed time in ms
27-
(
28-
(MEAN_ELAPSED_TIME * 1000) *
29-
(percent / 100)
30-
)
31-
).toISOString()
32-
)
22+
return new Date(
23+
// the current time in ms
24+
Date.now() -
25+
// minus the elapsed time in ms
26+
(
27+
(MEAN_ELAPSED_TIME * 1000) *
28+
(percent / 100)
29+
)
30+
).toISOString()
3331
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"@unhead/vue": "1.9.9",
3333
"@vueuse/core": "10.9.0",
3434
"apexcharts": "3.41.0",
35-
"axios": "1.6.8",
35+
"axios": "1.7.2",
3636
"dedent": "1.5.3",
3737
"enumify": "2.0.0",
3838
"graphiql": "3.2.2",

src/components/cylc/SVGTask.vue

Lines changed: 86 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
2525
<g
2626
class="c8-task"
2727
:class="{
28-
waiting: task.state === 'waiting',
29-
preparing: task.state === 'preparing',
30-
submitted: task.state === 'submitted',
31-
running: task.state === 'running',
32-
succeeded: task.state === 'succeeded',
33-
failed: task.state === 'failed',
34-
'submit-failed': task.state === 'submit-failed',
35-
expired: task.state === 'expired',
28+
[task.state]: true,
3629
held: task.isHeld,
3730
queued: task.isQueued && !task.isHeld,
3831
runahead: task.isRunahead && !(task.isHeld || task.isQueued),
@@ -48,7 +41,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
4841
The circle outline of the task icon.
4942
5043
NOTE: If changing the radius or stroke of the circle then the values
51-
in getModiferTransform must be updated.
44+
in getModifierTransform must be updated.
5245
-->
5346
<circle
5447
class="outline"
@@ -76,7 +69,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
7669
r="16"
7770
stroke-width="50"
7871
stroke-dasharray="157"
79-
:style="getRunningStyle()"
72+
:style="runningStyle"
8073
/>
8174
</g>
8275
<!-- dot
@@ -163,15 +156,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
163156
-->
164157
<g
165158
class="modifier"
166-
:transform="getModiferTransform()"
159+
:transform="modifierTransform"
167160
>
168161
<!-- modifier
169162
170163
The circle outline of the modifier which is displayed for some modifier
171164
states.
172165
173166
NOTE: If changing the radius or stroke of the circle then the values
174-
in getModiferTransform must be updated to match.
167+
in getModifierTransform must be updated to match.
175168
-->
176169
<circle
177170
class="outline"
@@ -253,84 +246,86 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
253246
</g>
254247
</template>
255248

256-
<script>
249+
<script setup>
250+
import { computed, inject, ref } from 'vue'
257251
import TaskState from '@/model/TaskState.model'
258252
259-
export default {
260-
name: 'SVGTask',
261-
props: {
262-
task: {
263-
required: true
264-
},
265-
startTime: {
266-
// The start time as an ISO8601 date-time string in expanded format
267-
// e.g. 2022-10-26T13:43:45Z
268-
// TODO: aim to remove this in due course
269-
// (we should be able to obtain this directly from the task)
270-
type: String,
271-
required: false
272-
},
273-
modifierSize: {
274-
// Scale the size of the task state modifier
275-
type: Number,
276-
default: 0.7
277-
},
253+
const props = defineProps({
254+
task: {
255+
required: true
278256
},
279-
methods: {
280-
getRunningStyle () {
281-
if (
282-
this.task.state === TaskState.RUNNING.name &&
283-
this.startTime &&
284-
this.task.task?.meanElapsedTime
285-
) {
286-
// job start time in ms
287-
const startTime = Date.parse(this.startTime)
288-
// current time in ms
289-
const now = Date.now()
290-
// job elapsed time in s
291-
const elapsedTime = ((now - startTime) / 1000)
292-
const ret = `
293-
animation-name: c8-task-progress-animation;
294-
animation-timing-function: steps(50);
295-
animation-iteration-count: 1;
296-
animation-duration: ${this.task.task.meanElapsedTime}s;
297-
animation-delay: -${elapsedTime}s;
298-
animation-fill-mode: forwards;
299-
`
300-
return ret.replace('\n', ' ')
301-
}
302-
return ''
303-
},
304-
getModiferTransform () {
305-
// Returns the translation required to position the ".modifier" nicely in
306-
// relation to the ".status".
307-
308-
// Both ".status" and ".modifier" are centered at (50, 50), we need to
309-
// move ".modifier" up and to the left so that the two don't touch and
310-
// have a sensible gap between them
311-
312-
// translation = -(
313-
// # (1) the x/y translation to the edge of ".modifier"
314-
// (
315-
// (.modifier.outline.width + .modifier.outline.stroke)
316-
// * modifierSize * sin(45)
317-
// )
318-
// # (2) the x/y translation to the edge of ".status"
319-
// (.status.outline.width + .status.outline.stroke) * sin(45)
320-
// )
321-
const translation = -(
322-
// (1) the x/y translation to the edge of ".modifier"
323-
(35.35 * this.modifierSize) +
324-
// (2) the x/y translation to the edge of ".status"
325-
42.42
326-
)
327-
return `
328-
scale(${this.modifierSize}, ${this.modifierSize})
329-
translate(${translation}, ${translation})
330-
`
331-
},
257+
startTime: {
258+
// The start time as an ISO8601 date-time string in expanded format
259+
// e.g. 2022-10-26T13:43:45Z
260+
// TODO: aim to remove this in due course
261+
// (we should be able to obtain this directly from the task)
262+
type: String,
263+
required: false
264+
},
265+
modifierSize: {
266+
// Scale the size of the task state modifier
267+
type: Number,
268+
default: 0.7
269+
},
270+
})
271+
272+
/**
273+
* @type {import('vue').Ref<number>}
274+
* @see @/components/cylc/workspace/Widget.vue
275+
*/
276+
const animResetTime = inject('animResetTime', () => ref(0), true)
277+
278+
const runningStyle = computed(() => {
279+
if (
280+
props.task.state === TaskState.RUNNING.name &&
281+
props.startTime &&
282+
props.task.task?.meanElapsedTime
283+
) {
284+
// current time in ms (UTC); updates whenever widget is unhidden
285+
const now = Math.max(Date.now(), animResetTime.value)
286+
// job elapsed time in ms
287+
const elapsedTime = now - Date.parse(props.startTime)
288+
return {
289+
animationDuration: `${props.task.task.meanElapsedTime}s`,
290+
animationDelay: `-${elapsedTime}ms`,
291+
animationFillMode: 'forwards',
292+
}
332293
}
294+
return {}
295+
})
296+
297+
/**
298+
* Returns the translation required to position the ".modifier" nicely in
299+
* relation to the ".status".
300+
*
301+
* Both ".status" and ".modifier" are centered at (50, 50), we need to
302+
* move ".modifier" up and to the left so that the two don't touch and
303+
* have a sensible gap between them.
304+
*/
305+
function _getModifierTransform () {
306+
// translation = -(
307+
// # (1) the x/y translation to the edge of ".modifier"
308+
// (
309+
// (.modifier.outline.width + .modifier.outline.stroke)
310+
// * modifierSize * sin(45)
311+
// )
312+
// # (2) the x/y translation to the edge of ".status"
313+
// (.status.outline.width + .status.outline.stroke) * sin(45)
314+
// )
315+
const translation = -(
316+
// (1) the x/y translation to the edge of ".modifier"
317+
(35.35 * props.modifierSize) +
318+
// (2) the x/y translation to the edge of ".status"
319+
42.42
320+
)
321+
return `
322+
scale(${props.modifierSize}, ${props.modifierSize})
323+
translate(${translation}, ${translation})
324+
`
333325
}
326+
327+
// Doesn't need to be reactive:
328+
const modifierTransform = _getModifierTransform()
334329
</script>
335330
336331
<style lang="scss">
@@ -460,6 +455,12 @@ export default {
460455
fill: $foreground;
461456
}
462457
}
458+
459+
&.running .progress {
460+
animation-name: c8-task-progress-animation;
461+
animation-timing-function: steps(50);
462+
animation-iteration-count: 1;
463+
}
463464
}
464465
465466
@keyframes c8-task-progress-animation {

src/components/cylc/commandMenu/Menu.vue

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ import {
123123
} from '@mdi/js'
124124
import { mapGetters, mapState } from 'vuex'
125125
import WorkflowState from '@/model/WorkflowState.model'
126+
import { eventBus } from '@/services/eventBus'
126127
127128
export default {
128129
name: 'CommandMenu',
@@ -155,11 +156,11 @@ export default {
155156
},
156157
157158
mounted () {
158-
this.$eventBus.on('show-mutations-menu', this.showMutationsMenu)
159+
eventBus.on('show-mutations-menu', this.showMutationsMenu)
159160
},
160161
161162
beforeUnmount () {
162-
this.$eventBus.off('show-mutations-menu', this.showMutationsMenu)
163+
eventBus.off('show-mutations-menu', this.showMutationsMenu)
163164
},
164165
165166
computed: {
@@ -258,7 +259,7 @@ export default {
258259
workflowName: this.node.tokens.workflow
259260
}
260261
}).then(() => {
261-
this.$eventBus.emit(
262+
eventBus.emit(
262263
'add-view',
263264
{
264265
name: 'Log',

src/components/cylc/commandMenu/plugin.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717

1818
import { uniqueId } from 'lodash-es'
19+
import { eventBus } from '@/services/eventBus'
1920

2021
/** Reference to closure listeners (needed as we are using variables from another scope) */
2122
const listeners = new WeakMap()
@@ -26,7 +27,7 @@ function bind (el, binding, vnode) {
2627
el.dataset.cInteractive = uniqueId()
2728
const listener = function (e) {
2829
e.stopPropagation() // prevents click event from bubbling up to parents
29-
binding.instance.$eventBus.emit('show-mutations-menu', {
30+
eventBus.emit('show-mutations-menu', {
3031
node: binding.value,
3132
target: el,
3233
})

0 commit comments

Comments
 (0)