@@ -18,27 +18,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
18
18
<template >
19
19
<div >
20
20
<!-- dropdown menu -->
21
- <component :is =" menuTransition" :target =" target" >
22
- <v-card
23
- ref =" menuContent"
24
- v-if =" node"
25
- v-show =" showMenu"
26
- @show-mutations-menu =" showMutationsMenu"
27
- :key =" node.id"
28
- v-click-outside =" { handler: onClickOutside, closeConditional: () => !dialog }"
29
- class =" c-mutation-menu elevation-10 overflow-y-auto"
30
- max-height =" 90vh"
31
- width =" max-content"
32
- max-width =" min(600px, 100%)"
33
- theme =" dark"
34
- position =" absolute"
35
- :style =" {
36
- left: `${x}px`,
37
- top: `${y}px`,
38
- // Set transition origin relative to clicked target:
39
- '--v-overlay-anchor-origin': 'bottom right',
40
- }"
41
- >
21
+ <v-menu
22
+ v-if =" node"
23
+ :key =" target.dataset.cInteractive"
24
+ v-model =" showMenu"
25
+ :target =" target"
26
+ :close-on-content-click =" false"
27
+ content-class =" c-mutation-menu"
28
+ max-width =" 600px"
29
+ theme =" dark"
30
+ >
31
+ <v-card >
42
32
<v-card-title class =" pb-1 pt-3" >
43
33
{{ node.id }}
44
34
</v-card-title >
@@ -89,7 +79,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
89
79
<v-list-item v-if =" canExpand" >
90
80
<v-btn
91
81
id =" less-more-button"
92
- @click =" expandCollapse "
82
+ @click =" () => expanded = !expanded "
93
83
block
94
84
variant =" tonal"
95
85
>
@@ -98,7 +88,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
98
88
</v-list-item >
99
89
</v-list >
100
90
</v-card >
101
- </component >
91
+ </v-menu >
102
92
<v-dialog
103
93
v-if =" dialogMutation"
104
94
v-model =" dialog"
@@ -111,7 +101,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
111
101
:cylcObject =" node"
112
102
:initialData =" initialData(dialogMutation, node.tokens)"
113
103
@close =" () => dialog = false"
114
- @success =" closeMenu "
104
+ @success =" () => showMenu = false "
115
105
:types =" types"
116
106
:key =" dialogKey /* Enables re-render of component each time dialog opened */"
117
107
ref =" mutationComponent"
@@ -121,23 +111,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
121
111
</template >
122
112
123
113
<script >
124
- import { computed , nextTick } from ' vue'
114
+ import { nextTick } from ' vue'
125
115
import {
126
116
filterAssociations ,
127
117
getMutationArgsFromTokens ,
128
118
mutate
129
119
} from ' @/utils/aotf'
130
- import { useReducedAnimation } from ' @/composables/localStorage'
131
120
import Mutation from ' @/components/cylc/Mutation.vue'
132
121
import {
133
122
mdiPencil
134
123
} from ' @mdi/js'
135
124
import { mapGetters , mapState } from ' vuex'
136
125
import WorkflowState from ' @/model/WorkflowState.model'
137
- import { VDialogTransition } from ' vuetify/components/transitions'
138
126
139
127
export default {
140
- name: ' CylcObjectMenu ' ,
128
+ name: ' CommandMenu ' ,
141
129
142
130
components: {
143
131
Mutation
@@ -151,15 +139,6 @@ export default {
151
139
}
152
140
},
153
141
154
- setup () {
155
- const reducedAnimation = useReducedAnimation ()
156
- return {
157
- menuTransition: computed (
158
- () => reducedAnimation .value ? ' slot' : VDialogTransition
159
- ),
160
- }
161
- },
162
-
163
142
data () {
164
143
return {
165
144
dialog: false ,
@@ -171,20 +150,16 @@ export default {
171
150
isLoadingMutations: true ,
172
151
showMenu: false ,
173
152
types: [],
174
- x: 0 ,
175
- y: 0 ,
176
153
target: null ,
177
154
}
178
155
},
179
156
180
157
mounted () {
181
158
this .$eventBus .on (' show-mutations-menu' , this .showMutationsMenu )
182
- document .addEventListener (' keydown' , this .onKeydown )
183
159
},
184
160
185
161
beforeUnmount () {
186
162
this .$eventBus .off (' show-mutations-menu' , this .showMutationsMenu )
187
- document .removeEventListener (' keydown' , this .onKeydown )
188
163
},
189
164
190
165
computed: {
@@ -268,66 +243,6 @@ export default {
268
243
this .dialogKey = ! this .dialogKey
269
244
},
270
245
271
- closeMenu () {
272
- this .showMenu = false
273
- this .expanded = false
274
- },
275
-
276
- /**
277
- * Handler for clicking outside menu (close it).
278
- *
279
- * We override vuetify default handling because we don't want to
280
- * close when clicking on another cylc object.
281
- *
282
- * @param {Event} e - the click event
283
- */
284
- onClickOutside (e ) {
285
- this .closeMenu ()
286
-
287
- // check if the thing being clicked on is a child of the thing that the
288
- // menu is open for
289
- let target = e .target
290
- while (target) {
291
- if (target? .getAttribute (' data-c-interactive' )) {
292
- // keep the menu open
293
- this .showMenu = true
294
- break
295
- }
296
- target = target .parentElement
297
- }
298
- },
299
-
300
- onKeydown (e ) {
301
- if (! this .dialog && e .key === ' Escape' ) {
302
- this .closeMenu ()
303
- }
304
- },
305
-
306
- expandCollapse () {
307
- this .expanded = ! this .expanded
308
- this .reposition ()
309
- },
310
-
311
- /**
312
- * Place the menu in a way that prevents it overflowing off screen and
313
- * so it takes up the full width as needed on narrow viewports.
314
- *
315
- * @param {number} x - preferred x coordinate
316
- * @param {number} y - preferred y coordinate
317
- */
318
- reposition (x = null , y = null ) {
319
- x ?? = this .x
320
- y ?? = this .y
321
- nextTick (() => {
322
- this .x = x + this .$refs .menuContent .$el .clientWidth > document .body .clientWidth
323
- ? document .body .clientWidth - this .$refs .menuContent .$el .clientWidth
324
- : x
325
- this .y = y + this .$refs .menuContent .$el .clientHeight > document .body .clientHeight
326
- ? document .body .clientHeight - this .$refs .menuContent .$el .clientHeight - 5
327
- : y
328
- })
329
- },
330
-
331
246
/* Call a mutation using only the tokens for args. */
332
247
callMutationFromContext (mutation ) {
333
248
this .showMenu = false
@@ -362,32 +277,32 @@ export default {
362
277
}
363
278
},
364
279
365
- showMutationsMenu ({ node, event }) {
366
- this .target = event . target
280
+ async showMutationsMenu ({ node, target }) {
281
+ this .target = target
367
282
this .node = node
283
+ this .expanded = false
284
+ // show the menu after it's rendered to ensure animation works properly
285
+ await nextTick ()
368
286
this .showMenu = true
369
- this .reposition (event .clientX , event .clientY )
370
- // await graphql query to get mutations
371
- this .$workflowService .introspection .then (({ mutations, types }) => {
372
- // if mutations are slow to load then there will be a delay before they are reactively
373
- // displayed in the menu (this is what the skeleton-loader is for)
374
- this .isLoadingMutations = false
375
- this .types = types
376
- let type = this .node .type
377
- if (type === ' family' ) {
378
- // show the same mutation list for families as for tasks
379
- type = ' task'
380
- }
381
- this .mutations = filterAssociations (
382
- type,
383
- this .node .tokens ,
384
- mutations,
385
- this .user .permissions
386
- ).sort (
387
- (a , b ) => a .mutation .name .localeCompare (b .mutation .name )
388
- )
389
- this .reposition (event .clientX , event .clientY )
390
- })
287
+ // ensure graphql query to get mutations has completed
288
+ const { mutations , types } = await this .$workflowService .introspection
289
+ // if mutations are slow to load then there will be a delay before they are reactively
290
+ // displayed in the menu (this is what the skeleton-loader is for)
291
+ this .isLoadingMutations = false
292
+ this .types = types
293
+ let type = this .node .type
294
+ if (type === ' family' ) {
295
+ // show the same mutation list for families as for tasks
296
+ type = ' task'
297
+ }
298
+ this .mutations = filterAssociations (
299
+ type,
300
+ this .node .tokens ,
301
+ mutations,
302
+ this .user .permissions
303
+ ).sort (
304
+ (a , b ) => a .mutation .name .localeCompare (b .mutation .name )
305
+ )
391
306
},
392
307
393
308
initialData (mutation , tokens ) {
0 commit comments