Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use dynamic async components for workspace view tabs + 1.6.x -> master (SimpleTree view) #1318

Merged
merged 8 commits into from
Jun 12, 2023
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ module.exports = {
objects: 'only-multiline',
imports: 'only-multiline',
exports: 'only-multiline',
functions: 'never',
functions: 'only-multiline',
},
],
'template-curly-spacing': [
Expand Down
75 changes: 21 additions & 54 deletions src/components/cylc/workflow/Lumino.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<div ref="main" class="main pa-2 fill-height">
<!-- Lumino box panel gets inserted here -->
</div>
<div v-show="false">
<!-- Hidden div acts as staging area for views before they are
moved into a lumino widget -->
<component
v-for="(item, id) of views"
:key="id"
:ref="(ref) => setViewRef(id, ref)"
:is="item.view"
:tab-title="getTabTitle(item.view)"
:workflow-name="workflowName"
:initialOptions="item.initialOptions"
class="h-100"
/>
</div>
<template
v-for="(item, id) in views"
:key="id"
>
<Teleport :to="`#${id}`">
<component
:is="item.view"
:workflow-name="workflowName"
:initialOptions="item.initialOptions"
class="h-100"
/>
</Teleport>
</template>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👏 👏 👏

</template>

<script>
import { startCase } from 'lodash'
import LuminoWidget from '@/components/cylc/workflow/lumino-widget'
import { BoxPanel, DockPanel, Widget } from '@lumino/widgets'

Expand Down Expand Up @@ -74,27 +74,17 @@ export default {
type: Array,
required: true
},
/**
* Prop to customize the tab title. Defaults to name.
* If a component does not have the $component.$tabTitleProp
* set, then we still revert to the old default $component.name.
*/
tabTitleProp: {
type: String,
default: 'name'
}
},

emits: [
'lumino:activated',
'lumino:deleted'
],

data () {
return {
/** Keep track of views' refs separate from $refs in order to access
* by ID */
viewRefs: {}
beforeCreate () {
// Populate components
for (const { name, component } of this.allViews) {
this.$options.components[name] = component
}
},

Expand All @@ -103,12 +93,6 @@ export default {
* Box panel. In the next tick of Vue, the DOM element and the Vue element/ref are attached.
*/
created () {
// We need to load each view used by this view/component.
// See "local-registration" in Vue.js documentation.
this.allViews.forEach(view => {
this.$options.components[view.name] = view
})

// create a box panel, which holds the dock panel, and controls its layout
this.box = new BoxPanel({ direction: 'left-to-right', spacing: 0 })
// create dock panel, which holds the widgets
Expand Down Expand Up @@ -152,40 +136,27 @@ export default {
},

methods: {
/** Keep track of views' refs separate from $refs, allowing access by ID */
setViewRef (id, ref) {
if (ref) {
this.viewRefs[id] = ref
} else {
delete this.viewRefs[id]
}
},
/**
* Look for newly added views, creating a corresponding Lumino Widget
* for each.
*/
syncWidgets (newVal, oldVal) {
const { tabTitleProp } = this.$props
for (const [id, item] of Object.entries(newVal)) {
if (!(id in oldVal)) {
const view = this.$options.components[item.view]
const name = view[tabTitleProp] ?? view.name
this.addWidget(id, name)
this.addWidget(id, item.view)
}
}
},

/**
* Create a widget, add it to the dock, and move the corresponding view
* from the hidden div into it.
* Create a widget and add it to the dock.
*/
addWidget (id, name, onTop = true) {
const luminoWidget = new LuminoWidget(id, name, /* closable */ true)
const luminoWidget = new LuminoWidget(id, startCase(name), /* closable */ true)
this.dock.addWidget(luminoWidget, { mode: 'tab-after' })
// give time for Lumino's widget DOM element to be created
this.$nextTick(() => {
const widgetEl = document.getElementById(id)
widgetEl.appendChild(this.viewRefs[id].$el)
widgetEl.addEventListener('lumino:activated', this.onWidgetActivated)
widgetEl.addEventListener('lumino:deleted', this.onWidgetDeleted)
if (onTop) {
Expand Down Expand Up @@ -227,10 +198,6 @@ export default {
widgetEl.removeEventListener('lumino:activated', this.onWidgetActivated)
this.$emit('lumino:deleted', customEvent.detail)
},

getTabTitle (viewName) {
return this.$options.components[viewName].data().widget.title
}
}
}
</script>
28 changes: 18 additions & 10 deletions src/components/cylc/workflow/Toolbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<v-spacer class="mx-0" />

<v-btn
v-if="$route.name === 'workspace'"
class="add-view"
color="primary"
data-cy="add-view-btn"
Expand All @@ -101,20 +102,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<v-menu
activator="parent"
location="bottom"
v-if="$route.name === 'workspace'"
>
<v-list class="pa-0">
>
<v-list>
<v-list-item
:id="`toolbar-add-${ view.name }-view`"
v-for="view in views"
:id="`toolbar-add-${ view.name }-view`"
:key="view.name"
@click="$emit('add', { viewName: view.name })"
class="py-0 px-8 ma-0 c-add-view"
>
<template v-slot:prepend>
<v-icon>{{ view.data().widget.icon }}</v-icon>
<v-icon>{{ view.icon }}</v-icon>
</template>
<v-list-item-title>{{ view.name }}</v-list-item-title>
<v-list-item-title>{{ startCase(view.name) }}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
Expand Down Expand Up @@ -148,6 +147,7 @@ import {
mdiStop,
mdiViewList
} from '@mdi/js'
import { startCase } from 'lodash'
import toolbar from '@/mixins/toolbar'
import WorkflowState from '@/model/WorkflowState.model'
import graphql from '@/mixins/graphql'
Expand All @@ -158,20 +158,24 @@ import {

export default {
name: 'Toolbar',

mixins: [
toolbar,
graphql
],

props: {
views: {
type: Array,
required: true
}

},

emits: ['add'],

data: () => ({
extended: false,
// FIXME: remove local state once we have this data in the workflow - https://github.com/cylc/cylc-ui/issues/221
svgPaths: {
add: mdiPlusBoxMultiple,
hold: mdiPause,
Expand All @@ -187,6 +191,7 @@ export default {
stop: null
}
}),

computed: {
...mapState('app', ['title']),
...mapState('user', ['user']),
Expand Down Expand Up @@ -253,6 +258,7 @@ export default {
}
}
},

watch: {
isRunning () {
this.expecting.play = null
Expand All @@ -264,6 +270,7 @@ export default {
this.expecting.stop = null
}
},

methods: {
onClickPlay () {
this.$workflowService.mutate(
Expand All @@ -285,7 +292,7 @@ export default {
}
})
},
async onClickStop () {
onClickStop () {
this.$workflowService.mutate(
'stop',
this.currentWorkflow.id
Expand All @@ -297,7 +304,8 @@ export default {
},
toggleExtended () {
this.extended = !this.extended
}
},
startCase,
}
}
</script>
5 changes: 0 additions & 5 deletions src/views/Analysis.vue
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ import {
platformOptions
} from '@/components/cylc/analysis/filter'
import {
mdiChartLine,
mdiRefresh
} from '@mdi/js'

Expand Down Expand Up @@ -185,10 +184,6 @@ export default {
data () {
const tasks = []
return {
widget: {
title: 'analysis',
icon: mdiChartLine
},
/** Defines controls which get added to the toolbar */
groups: [
{
Expand Down
5 changes: 0 additions & 5 deletions src/views/Graph.vue
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ import {
import { Graphviz } from '@hpcc-js/wasm/graphviz'
import svgPanZoom from 'svg-pan-zoom'
import {
mdiGraph,
mdiTimer,
mdiImageFilterCenterFocus,
mdiArrowCollapse,
Expand Down Expand Up @@ -219,10 +218,6 @@ export default {

data () {
return {
widget: {
title: 'graph',
icon: mdiGraph
},
// the graph orientation
orientation: 'TB',
// the auto-refresh timer
Expand Down
6 changes: 0 additions & 6 deletions src/views/Log.vue
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<script>
import {
mdiClockOutline,
mdiFileDocumentMultipleOutline,
mdiFolderRefresh,
mdiPowerPlugOff,
mdiPowerPlug
Expand Down Expand Up @@ -253,11 +252,6 @@ export default {

data () {
return {
// metadata for the workspace view
widget: {
title: 'logs',
icon: mdiFileDocumentMultipleOutline
},
// the log subscription query
query: null,
// list of log files for the selected workflow/task/job
Expand Down
Loading