@@ -25,14 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
<g
26
26
class =" c8-task"
27
27
: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,
36
29
held: task.isHeld,
37
30
queued: task.isQueued && !task.isHeld,
38
31
runahead: task.isRunahead && !(task.isHeld || task.isQueued),
@@ -48,7 +41,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
48
41
The circle outline of the task icon.
49
42
50
43
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.
52
45
-->
53
46
<circle
54
47
class =" outline"
@@ -76,7 +69,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
76
69
r =" 16"
77
70
stroke-width =" 50"
78
71
stroke-dasharray =" 157"
79
- :style =" getRunningStyle() "
72
+ :style =" runningStyle "
80
73
/>
81
74
</g >
82
75
<!-- dot
@@ -163,15 +156,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
163
156
-->
164
157
<g
165
158
class =" modifier"
166
- :transform =" getModiferTransform() "
159
+ :transform =" modifierTransform "
167
160
>
168
161
<!-- modifier
169
162
170
163
The circle outline of the modifier which is displayed for some modifier
171
164
states.
172
165
173
166
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.
175
168
-->
176
169
<circle
177
170
class =" outline"
@@ -253,84 +246,86 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
253
246
</g >
254
247
</template >
255
248
256
- <script >
249
+ <script setup>
250
+ import { computed , inject , ref } from ' vue'
257
251
import TaskState from ' @/model/TaskState.model'
258
252
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
278
256
},
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
+ }
332
293
}
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
+ `
333
325
}
326
+
327
+ // Doesn't need to be reactive:
328
+ const modifierTransform = _getModifierTransform ()
334
329
< / script>
335
330
336
331
< style lang= " scss" >
@@ -460,6 +455,12 @@ export default {
460
455
fill: $foreground;
461
456
}
462
457
}
458
+
459
+ & .running .progress {
460
+ animation- name: c8- task- progress- animation;
461
+ animation- timing- function: steps (50 );
462
+ animation- iteration- count: 1 ;
463
+ }
463
464
}
464
465
465
466
@keyframes c8- task- progress- animation {
0 commit comments