Skip to content

Commit c44944a

Browse files
committed
Merge branch 'master' into task-animation
2 parents 83be763 + 1ecfe08 commit c44944a

File tree

23 files changed

+181
-239
lines changed

23 files changed

+181
-239
lines changed

changes.d/1466.feat.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added gantt view: a new view showing job durations over time.

src/components/cylc/GraphNode.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
2323
:modifierSize="0.5"
2424
:startTime="startTime"
2525
viewBox="-40 -40 140 140"
26-
v-cylc-object="task"
26+
v-command-menu="task"
2727
x="0" y="0"
2828
/>
2929

@@ -64,7 +64,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
6464
:svg="true"
6565
:status="job.node.state"
6666
viewBox="0 0 100 100"
67-
v-cylc-object="job"
67+
v-command-menu="job"
6868
/>
6969
</g>
7070
<!-- overflow indicator if there are surplus jobs -->

src/components/cylc/cylcObject/Menu.vue renamed to src/components/cylc/commandMenu/Menu.vue

Lines changed: 40 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
1818
<template>
1919
<div>
2020
<!-- 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>
4232
<v-card-title class="pb-1 pt-3">
4333
{{ node.id }}
4434
</v-card-title>
@@ -89,7 +79,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
8979
<v-list-item v-if="canExpand">
9080
<v-btn
9181
id="less-more-button"
92-
@click="expandCollapse"
82+
@click="() => expanded = !expanded"
9383
block
9484
variant="tonal"
9585
>
@@ -98,7 +88,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
9888
</v-list-item>
9989
</v-list>
10090
</v-card>
101-
</component>
91+
</v-menu>
10292
<v-dialog
10393
v-if="dialogMutation"
10494
v-model="dialog"
@@ -111,7 +101,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
111101
:cylcObject="node"
112102
:initialData="initialData(dialogMutation, node.tokens)"
113103
@close="() => dialog = false"
114-
@success="closeMenu"
104+
@success="() => showMenu = false"
115105
:types="types"
116106
:key="dialogKey /* Enables re-render of component each time dialog opened */"
117107
ref="mutationComponent"
@@ -121,24 +111,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
121111
</template>
122112

123113
<script>
124-
import { computed, nextTick } from 'vue'
114+
import { nextTick } from 'vue'
125115
import {
126116
filterAssociations,
127117
getMutationArgsFromTokens,
128118
mutate
129119
} from '@/utils/aotf'
130-
import { useReducedAnimation } from '@/composables/localStorage'
131120
import Mutation from '@/components/cylc/Mutation.vue'
132121
import {
133122
mdiPencil
134123
} from '@mdi/js'
135124
import { mapGetters, mapState } from 'vuex'
136125
import WorkflowState from '@/model/WorkflowState.model'
137-
import { VDialogTransition } from 'vuetify/components/transitions'
138126
import { eventBus } from '@/services/eventBus'
139127
140128
export default {
141-
name: 'CylcObjectMenu',
129+
name: 'CommandMenu',
142130
143131
components: {
144132
Mutation
@@ -152,15 +140,6 @@ export default {
152140
}
153141
},
154142
155-
setup () {
156-
const reducedAnimation = useReducedAnimation()
157-
return {
158-
menuTransition: computed(
159-
() => reducedAnimation.value ? 'slot' : VDialogTransition
160-
),
161-
}
162-
},
163-
164143
data () {
165144
return {
166145
dialog: false,
@@ -172,20 +151,16 @@ export default {
172151
isLoadingMutations: true,
173152
showMenu: false,
174153
types: [],
175-
x: 0,
176-
y: 0,
177154
target: null,
178155
}
179156
},
180157
181158
mounted () {
182159
eventBus.on('show-mutations-menu', this.showMutationsMenu)
183-
document.addEventListener('keydown', this.onKeydown)
184160
},
185161
186162
beforeUnmount () {
187163
eventBus.off('show-mutations-menu', this.showMutationsMenu)
188-
document.removeEventListener('keydown', this.onKeydown)
189164
},
190165
191166
computed: {
@@ -269,66 +244,6 @@ export default {
269244
this.dialogKey = !this.dialogKey
270245
},
271246
272-
closeMenu () {
273-
this.showMenu = false
274-
this.expanded = false
275-
},
276-
277-
/**
278-
* Handler for clicking outside menu (close it).
279-
*
280-
* We override vuetify default handling because we don't want to
281-
* close when clicking on another cylc object.
282-
*
283-
* @param {Event} e - the click event
284-
*/
285-
onClickOutside (e) {
286-
this.closeMenu()
287-
288-
// check if the thing being clicked on is a child of the thing that the
289-
// menu is open for
290-
let target = e.target
291-
while (target) {
292-
if (target?.getAttribute('data-c-interactive')) {
293-
// keep the menu open
294-
this.showMenu = true
295-
break
296-
}
297-
target = target.parentElement
298-
}
299-
},
300-
301-
onKeydown (e) {
302-
if (!this.dialog && e.key === 'Escape') {
303-
this.closeMenu()
304-
}
305-
},
306-
307-
expandCollapse () {
308-
this.expanded = !this.expanded
309-
this.reposition()
310-
},
311-
312-
/**
313-
* Place the menu in a way that prevents it overflowing off screen and
314-
* so it takes up the full width as needed on narrow viewports.
315-
*
316-
* @param {number} x - preferred x coordinate
317-
* @param {number} y - preferred y coordinate
318-
*/
319-
reposition (x = null, y = null) {
320-
x ??= this.x
321-
y ??= this.y
322-
nextTick(() => {
323-
this.x = x + this.$refs.menuContent.$el.clientWidth > document.body.clientWidth
324-
? document.body.clientWidth - this.$refs.menuContent.$el.clientWidth
325-
: x
326-
this.y = y + this.$refs.menuContent.$el.clientHeight > document.body.clientHeight
327-
? document.body.clientHeight - this.$refs.menuContent.$el.clientHeight - 5
328-
: y
329-
})
330-
},
331-
332247
/* Call a mutation using only the tokens for args. */
333248
callMutationFromContext (mutation) {
334249
this.showMenu = false
@@ -363,32 +278,32 @@ export default {
363278
}
364279
},
365280
366-
showMutationsMenu ({ node, event }) {
367-
this.target = event.target
281+
async showMutationsMenu ({ node, target }) {
282+
this.target = target
368283
this.node = node
284+
this.expanded = false
285+
// show the menu after it's rendered to ensure animation works properly
286+
await nextTick()
369287
this.showMenu = true
370-
this.reposition(event.clientX, event.clientY)
371-
// await graphql query to get mutations
372-
this.$workflowService.introspection.then(({ mutations, types }) => {
373-
// if mutations are slow to load then there will be a delay before they are reactively
374-
// displayed in the menu (this is what the skeleton-loader is for)
375-
this.isLoadingMutations = false
376-
this.types = types
377-
let type = this.node.type
378-
if (type === 'family') {
379-
// show the same mutation list for families as for tasks
380-
type = 'task'
381-
}
382-
this.mutations = filterAssociations(
383-
type,
384-
this.node.tokens,
385-
mutations,
386-
this.user.permissions
387-
).sort(
388-
(a, b) => a.mutation.name.localeCompare(b.mutation.name)
389-
)
390-
this.reposition(event.clientX, event.clientY)
391-
})
288+
// ensure graphql query to get mutations has completed
289+
const { mutations, types } = await this.$workflowService.introspection
290+
// if mutations are slow to load then there will be a delay before they are reactively
291+
// displayed in the menu (this is what the skeleton-loader is for)
292+
this.isLoadingMutations = false
293+
this.types = types
294+
let type = this.node.type
295+
if (type === 'family') {
296+
// show the same mutation list for families as for tasks
297+
type = 'task'
298+
}
299+
this.mutations = filterAssociations(
300+
type,
301+
this.node.tokens,
302+
mutations,
303+
this.user.permissions
304+
).sort(
305+
(a, b) => a.mutation.name.localeCompare(b.mutation.name)
306+
)
392307
},
393308
394309
initialData (mutation, tokens) {

src/components/cylc/cylcObject/plugin.js renamed to src/components/cylc/commandMenu/plugin.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/**
1+
/*
22
* Copyright (C) NIWA & British Crown (Met Office) & Contributors.
33
*
44
* This program is free software: you can redistribute it and/or modify
@@ -15,21 +15,24 @@
1515
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1616
*/
1717

18+
import { uniqueId } from 'lodash-es'
1819
import { eventBus } from '@/services/eventBus'
1920

20-
// reference to closure listeners (needed as we are using variables from another scope)
21+
/** Reference to closure listeners (needed as we are using variables from another scope) */
2122
const listeners = new WeakMap()
2223

2324
function bind (el, binding, vnode) {
25+
// Set data-c-interactive = <unique identifier> for every element that opens the menu.
26+
// This allows the menu component to tell apart every activating element.
27+
el.dataset.cInteractive = uniqueId()
2428
const listener = function (e) {
2529
e.stopPropagation() // prevents click event from bubbling up to parents
2630
eventBus.emit('show-mutations-menu', {
2731
node: binding.value,
28-
event: e
32+
target: el,
2933
})
3034
}
3135
el.addEventListener('click', listener)
32-
el.dataset.cInteractive = true
3336
listeners.set(el, listener)
3437
}
3538

@@ -57,7 +60,7 @@ export default {
5760
*/
5861
install (app, options) {
5962
// add a global directive
60-
app.directive('cylc-object', {
63+
app.directive('command-menu', {
6164
beforeMount: bind,
6265
unmounted: unbind,
6366
updated

0 commit comments

Comments
 (0)