Skip to content

Commit 3d8d9b8

Browse files
committed
Fix N-window selector sending mutation upon navigation to stopped workflows
1 parent 447657b commit 3d8d9b8

File tree

3 files changed

+65
-27
lines changed

3 files changed

+65
-27
lines changed

src/components/cylc/workflow/Toolbar.vue

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -91,19 +91,31 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
9191
size="small"
9292
>
9393
N={{ nWindow }}
94-
<v-menu activator="parent" :close-on-content-click="false">
94+
<v-menu
95+
activator="parent"
96+
:close-on-content-click="false"
97+
max-width="400"
98+
>
9599
<v-card title="Graph Window Depth">
96-
<v-card-subtitle>
100+
<v-card-text>
97101
This changes the number of tasks which are displayed.
98102

99103
Higher values may impact performance.
100-
</v-card-subtitle>
104+
</v-card-text>
101105
<v-card-text>
102106
<v-select
103-
density="compact"
104107
v-model="nWindow"
105108
:items="[0,1,2,3]"
106-
/>
109+
>
110+
<template #append-inner>
111+
<v-progress-circular
112+
v-if="changingNWindow"
113+
indeterminate
114+
size="20"
115+
width="2"
116+
/>
117+
</template>
118+
</v-select>
107119
</v-card-text>
108120
</v-card>
109121
</v-menu>
@@ -198,6 +210,7 @@ import {
198210
mdiAccount
199211
} from '@mdi/js'
200212
import { startCase } from 'lodash'
213+
import { until } from '@/utils'
201214
import { useToolbar, toolbarHeight } from '@/utils/toolbar'
202215
import WorkflowState from '@/model/WorkflowState.model'
203216
import graphql from '@/mixins/graphql'
@@ -279,7 +292,7 @@ export default {
279292
paused: null,
280293
stop: null
281294
},
282-
nWindow: 1
295+
changingNWindow: false,
283296
}),
284297
285298
computed: {
@@ -357,9 +370,20 @@ export default {
357370
)
358371
}
359372
},
360-
nEdgeDistance () {
361-
// the graph window distance reported by the scheduler
362-
return this.currentWorkflow?.node?.nEdgeDistance
373+
nWindow: {
374+
get () {
375+
// the graph window distance reported by the scheduler
376+
return this.currentWorkflow?.node?.nEdgeDistance ?? 1
377+
},
378+
async set (val) {
379+
if (val == null || this.isStopped) return
380+
381+
this.changingNWindow = true
382+
if (await this.setGraphWindow(val)) {
383+
await until(() => this.currentWorkflow?.node?.nEdgeDistance === val)
384+
}
385+
this.changingNWindow = false
386+
},
363387
}
364388
},
365389
@@ -373,16 +397,6 @@ export default {
373397
isStopped () {
374398
this.expecting.stop = null
375399
},
376-
nWindow (newVal) {
377-
// the user has requested to change the window size
378-
this.setGraphWindow(newVal)
379-
},
380-
nEdgeDistance (newVal) {
381-
// the scheduler has reported that the window size has changed
382-
if (newVal !== undefined) {
383-
this.nWindow = newVal
384-
}
385-
}
386400
},
387401
388402
methods: {
@@ -416,12 +430,13 @@ export default {
416430
}
417431
})
418432
},
419-
setGraphWindow (nWindow) {
420-
this.$workflowService.mutate(
433+
async setGraphWindow (nWindow) {
434+
const { status } = await this.$workflowService.mutate(
421435
'setGraphWindowExtent',
422436
this.currentWorkflow.id,
423437
{ nEdgeDistance: nWindow }
424438
)
439+
return status === mutationStatus.SUCCEEDED
425440
},
426441
startCase,
427442
},

src/utils/index.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,30 @@ export const getPageTitle = (key, params = {}) => {
3838
* @param {import('vue').WatchCallback} callback
3939
* @param {import('vue').WatchOptions?} options
4040
*/
41-
export const when = (source, callback, options = {}) => {
41+
export function when (source, callback, options = {}) {
4242
const unwatch = watch(
4343
source,
4444
(ready) => {
4545
if (ready) {
46-
callback()
4746
unwatch()
47+
callback()
4848
}
4949
},
5050
{ immediate: true, ...options }
5151
)
5252
}
53+
54+
/**
55+
* Return a promise that resolves when the source becomes truthy.
56+
*
57+
* Awaitable version of when().
58+
*
59+
* @param {import('vue').WatchSource} source
60+
* @param {import('vue').WatchOptions?} options
61+
* @returns {Promise<void>}
62+
*/
63+
export function until (source, options = {}) {
64+
return new Promise((resolve) => {
65+
when(source, resolve, options)
66+
})
67+
}

tests/unit/utils/index.spec.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,27 @@
1616
*/
1717

1818
import { nextTick, ref } from 'vue'
19-
import { getPageTitle, when } from '@/utils/index'
19+
import { getPageTitle, when, until } from '@/utils/index'
2020

2121
describe('getPageTitle()', () => {
2222
it('displays the application title correctly', () => {
2323
expect(getPageTitle('App.dashboard')).to.equal('Cylc UI | Dashboard')
2424
})
2525
})
2626

27-
describe('when()', () => {
28-
it('watches source until true and then stops watching', async () => {
27+
describe.each([
28+
{ func: when, description: 'watches source until true and then stops watching' },
29+
{ func: until, description: 'returns a promise that resolves when source becomes true' },
30+
])('$func', ({ func, description }) => {
31+
it(description, async () => {
2932
const source = ref(false)
3033
let counter = 0
31-
when(source, () => counter++)
34+
switch (func) {
35+
case when:
36+
when(source, () => counter++); break
37+
case until:
38+
until(source).then(() => counter++); break
39+
}
3240
expect(counter).toEqual(0)
3341
source.value = true
3442
await nextTick()

0 commit comments

Comments
 (0)