-
Notifications
You must be signed in to change notification settings - Fork 27
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
expose the cylc views standalone #376
Comments
I think there is a view that displays the There is one for |
I did this for the treeview here: #378 ... but forgot to reference this issue. So now we have:
What do we need to close this issue?
|
View registration with automatic route creation is probably overkill as we don't expect new views to be created very often! |
|
Coming back to this after a discussion with @hjoliver about endpoints: To close this issue properly, I think we need to separate the Lumino tabs layer from the Workflow Component. At the moment the standalone views are brokering their own subscriptions with the workflow service, they should go through the Workflow Component:
The architecture would look like this: Note the URL endpoints, @hjoliver suggested "tabs" puts the standalone views at the same level as the workflow dashboard provided by Lumnio. |
After the GScan + deltas PR is reviewed and merged, I think we should be able to have a simpler way to create views and add them to workflow lumino widgets with the following diff: diff --git a/src/components/cylc/workflow/Toolbar.vue b/src/components/cylc/workflow/Toolbar.vue
index 6dd4da34..0385fea2 100644
--- a/src/components/cylc/workflow/Toolbar.vue
+++ b/src/components/cylc/workflow/Toolbar.vue
@@ -96,7 +96,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
class="py-0 px-8 ma-0 c-add-view"
>
<v-list-item-icon>
- <v-icon>{{ view.icon }}</v-icon>
+ <v-icon>{{ view.data().widget.icon }}</v-icon>
</v-list-item-icon>
<v-list-item-title>{{ view.name }}</v-list-item-title>
</v-list-item>
@@ -124,8 +124,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<script>
import { mapGetters, mapState } from 'vuex'
import {
- mdiAppleKeyboardCommand,
- mdiFileTree,
mdiMicrosoftXboxControllerMenu,
mdiPause,
mdiPlay,
@@ -135,8 +133,6 @@ import {
} from '@mdi/js'
import toolbar from '@/mixins/toolbar'
import WorkflowState from '@/model/WorkflowState.model'
-import TreeView from '@/views/Tree'
-import MutationsView from '@/views/Mutations'
import {
mutationStatus
@@ -144,11 +140,15 @@ import {
export default {
name: 'Toolbar',
-
+ props: {
+ views: {
+ type: Array,
+ required: true
+ }
+ },
mixins: [
toolbar
],
-
data: () => ({
extended: false,
// FIXME: remove local state once we have this data in the workflow - https://github.com/cylc/cylc-ui/issues/221
@@ -164,21 +164,8 @@ export default {
// store state from mutations in order to compute the "enabled" attrs
paused: null,
stop: null
- },
- views: [
- {
- name: TreeView.name,
- icon: mdiFileTree
-
- },
- {
- name: MutationsView.name,
- icon: mdiAppleKeyboardCommand
-
- }
- ]
+ }
}),
-
computed: {
...mapState('app', ['title']),
...mapGetters('workflows', ['currentWorkflow']),
@@ -220,7 +207,6 @@ export default {
}
}
},
-
watch: {
isPaused () {
this.expecting.paused = null
@@ -229,7 +215,6 @@ export default {
this.expecting.stop = null
}
},
-
methods: {
onClickReleaseHold () {
const ret = this.$workflowService.mutate(
diff --git a/src/views/Mutations.vue b/src/views/Mutations.vue
index 6d782a4a..00f948e7 100644
--- a/src/views/Mutations.vue
+++ b/src/views/Mutations.vue
@@ -40,9 +40,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<script>
import gql from 'graphql-tag'
import { getIntrospectionQuery as getGraphQLIntrospectionQuery, print } from 'graphql'
-
-import Mutation from '@/components/cylc/Mutation'
+import { mdiAppleKeyboardCommand } from '@mdi/js'
import subscriptionViewMixin from '@/mixins/subscriptionView'
+import Mutation from '@/components/cylc/Mutation'
export function associate (mutations, objects) {
const associations = {}
@@ -117,6 +117,10 @@ export default {
Job: [
['JobID', false]
]
+ },
+ widget: {
+ title: 'mutations',
+ icon: mdiAppleKeyboardCommand
}
}),
computed: {
diff --git a/src/views/Tree.vue b/src/views/Tree.vue
index b6b279ab..746b9257 100644
--- a/src/views/Tree.vue
+++ b/src/views/Tree.vue
@@ -42,6 +42,7 @@ import SubscriptionQuery from '@/model/SubscriptionQuery.model'
import TreeComponent from '@/components/cylc/tree/Tree'
import CylcObjectMenu from '@/components/cylc/cylcObject/Menu'
import { WORKFLOW_TREE_DELTAS_SUBSCRIPTION } from '@/graphql/queries'
+import { mdiFileTree } from '@mdi/js'
export default {
mixins: [
@@ -60,6 +61,14 @@ export default {
title: this.getPageTitle('App.workflow', { name: this.workflowName })
}
},
+ data () {
+ return {
+ widget: {
+ title: 'tree',
+ icon: mdiFileTree
+ }
+ }
+ },
computed: {
...mapState('workflows', ['workflow']),
workflows () {
diff --git a/src/views/Workflow.vue b/src/views/Workflow.vue
index 51c5f20f..453a8470 100644
--- a/src/views/Workflow.vue
+++ b/src/views/Workflow.vue
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<div>
<CylcObjectMenu />
<toolbar
+ :views="views"
v-on:add="this.addView"
></toolbar>
<div class="workflow-panel fill-height">
@@ -28,24 +29,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
tab-title-prop="tab-title"
>
<v-skeleton-loader
- v-for="widgetId of treeWidgets"
- :key="widgetId"
- :id="widgetId"
+ v-for="(view, id) of widgets"
+ :key="id"
+ :id="id"
:loading="isLoading"
+ :tab-title="view.data().widget.title"
type="list-item-three-line"
- tab-title="tree"
>
- <tree-view
+ <component
+ :is="view"
:workflow-name="workflowName"
/>
</v-skeleton-loader>
- <mutations-view
- v-for="widgetId of mutationsWidgets"
- :key="widgetId"
- :id="widgetId"
- :workflow-name="workflowName"
- tab-title="mutations"
- />
</lumino>
</div>
</div>
@@ -64,6 +59,7 @@ import Toolbar from '@/components/cylc/workflow/Toolbar'
import CylcObjectMenu from '@/components/cylc/cylcObject/Menu'
import MutationsView from '@/views/Mutations'
import TreeView from '@/views/Tree'
+import WorkflowsTableView from '@/views/WorkflowsTable'
import { mapState } from 'vuex'
export default {
@@ -76,8 +72,6 @@ export default {
components: {
CylcObjectMenu,
Lumino,
- TreeView,
- MutationsView,
Toolbar
},
metaInfo () {
@@ -91,22 +85,22 @@ export default {
*
* @type {Object.<String, String>}
*/
- widgets: {}
+ widgets: {},
+ views: [
+ TreeView,
+ MutationsView,
+ WorkflowsTableView
+ ]
}),
+ created () {
+ // We need to load each view used by this view/component.
+ // See "local-registration" in Vue.js documentation.
+ this.views.forEach(view => {
+ this.$options.components[view.name] = view
+ })
+ },
computed: {
- ...mapState('workflows', ['workflow']),
- treeWidgets () {
- return Object
- .entries(this.widgets)
- .filter(([id, type]) => type === TreeView.name)
- .map(([id, type]) => id)
- },
- mutationsWidgets () {
- return Object
- .entries(this.widgets)
- .filter(([id, type]) => type === MutationsView.name)
- .map(([id, type]) => id)
- }
+ ...mapState('workflows', ['workflow'])
},
beforeRouteEnter (to, from, next) {
next(vm => {
@@ -134,18 +128,17 @@ export default {
methods: {
/**
* Add a new view widget.
+ *
+ * @type {String} viewName - the name of the view to be added (Vue component name).
*/
- addView (view) {
- switch (view) {
- case TreeView.name:
- Vue.set(this.widgets, createWidgetId(), TreeView.name)
- break
- case MutationsView.name:
- Vue.set(this.widgets, createWidgetId(), MutationsView.name)
- break
- default:
- throw Error(`Unknown view "${view}"`)
+ addView (viewName) {
+ const view = this.views
+ .filter(v => v.name === viewName)
+ .slice(0)[0]
+ if (!view) {
+ throw Error(`Unknown view "${viewName}"`)
}
+ Vue.set(this.widgets, createWidgetId(), view)
this.$nextTick(() => {
// Views use navigation-guards to start the pending subscriptions. But we don't have
// this in this view. We must pretend we are doing the beforeRouteEnter here, and
diff --git a/src/views/WorkflowsTable.vue b/src/views/WorkflowsTable.vue
index 13c31aa8..33e41bf1 100644
--- a/src/views/WorkflowsTable.vue
+++ b/src/views/WorkflowsTable.vue
@@ -29,7 +29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
md12
>
<v-alert
- :icon="svgPath"
+ :icon="svgPath.table"
prominent
color="grey lighten-3"
>
@@ -125,7 +125,13 @@ export default {
value: 'port'
}
],
- svgPath: mdiTable
+ svgPath: {
+ table: mdiTable
+ },
+ widget: {
+ title: 'workflows table',
+ icon: mdiTable
+ }
}),
computed: {
...mapState('workflows', ['workflows']), After that, we should be able to add any view as long as it
# file: Table.vue <- for the table view, for instance
import { mdiTable } from '@mdi/js'
export default {
...
data () {
return {
widget: {
title: 'table',
icon: mdiTable
}
}
}
...
} And we would have to add it to the |
Should have a pull request tomorrow or Wednesday (have a performance review meeting tomorrow, and may need to write unit and/or e2e tests). |
Copying a comment by @oliver-sanders with more things to be done as part of this ticket
I think there are three things left to do, we can bump them to their own issues
|
We are pretty much there on this one, just a couple of things remaining:
Suggest:
Note this commit splits GScan into view/component (similar to the tree & table views) which makes things a little easier. |
This has been discussed before but @hjoliver made me aware we hadn't documented it anywhere.
The Cylc workflow views (tree, dot, graph, etc) and Cylc GScan should all be accessible via their own URL endpoints. This is currently true of the Graph view and should be fairly straight forward.
This is to allow the components to be used standalone for embedding and other purposes.
The main use case I'm aware of is that some users (namely operators) might want to have GScan open full-screen on one monitor.
Cylc views can be built to be responsive to make use of the available screen space.
Questions:
/#/workflow/tabs/<flow>
)?Pull requests welcome!
The text was updated successfully, but these errors were encountered: