Skip to content

Workflow Component

Bruno P. Kinoshita edited this page Mar 25, 2021 · 4 revisions

The workflow component is used by the Workflow view. This component uses Lumino to display other components inside "widgets".

Adding a new widget

What is a widget?

A widget in Cylc UI is simply a Vue component that is displayed within a Lumino widget, and appears as a tab in the workflow view. Users can add many instances of the same widget type. Widgets can be moved around, changing the layout of the workflow view, or removed from the view.

The easiest way to write a widget, is by creating a view (e.g. src/views/MyNewWidgetTemp.vue with a minimal structure like:

<template>
  <div>
    <comp
      :workflows="workflowTree"
    ></comp>
  </div>
</template>

<script>
import Comp from '@/components/cylc/comp/Comp.vue'

export default {
  name: 'MyNewWidgetTemp',
  props: {
    workflowName: {
      type: String,
      required: true
    }
  },

  components: {
    Comp
  },

  metaInfo () {
    return {
      title: 'Temp View'
    }
  },

  data: () => ({}),

  // ...
}
</script>

This view simply loads the component from '@/components/cylc/comp/Comp.vue' which you have created, and displays for you in the UI. This is useful for development, but this view must be deleted before you create a new pull request (unless it is supposed to be kept afterwards, check in the chat-room with other team members).

In order for the view to be accessed from a URL, you also need to bind the component to a route (which makes the component into a view). Modify the file src/router/paths.js to create your view.

If your component needs the workflow data from a GraphQL subscription, you may want to look at the Tree component for the required code to start a subscription and to populate the JS objects.

Once you have your widget displaying the data as expected, the next step is choosing when your widget is created.

When is your new widget created?

Widgets are added in the Workflow.vue view. This view is bound to a VueRouter route, so it has the lifecycles of both a Vue Component (e.g. beforeUpdate), and of a VueRouter route (e.g. beforeRouteEnter).

By default a Tree widget is created and added to the view when it is loaded (beforeRouteEnter of a VueRouter route). Other widgets are created when the user clicks on a button in the UI.

The buttons where the user clicks to add new widgets are not in the Workflow.vue view, but in the cylc/workflow/Toolbar.vue component. This component is displayed at the top of the Workflow view, and has a drop down with the valid widgets to be added to a workflow.

You can now choose whether your new widget is created when the page is loaded, or when the user clicks on a widget type. Check how other widgets are created, and just copy-paste and adjust it for your component.

Adding the new widget to Workflow.vue

You have created a new component to display in the widget. Maybe a view to preview the component. And have also chosen when the component is created.

Now you must be ready to add the new widget to Workflow.vue. Start by importing the component.

import Comp from '@/components/cylc/comp/Comp.vue'

...
  components: {
    //,
    Comp
  }
...

Now add a computed variable to hold the list of widgets for this new component type.

  computed: {
    ...
    compWidgets () {
      return Object
        .entries(this.widgets)
        .filter(([id, type]) => type === Comp.name)
        .map(([id, type]) => id)
    }
  },

Add a method to add the widget.

  methods: {
    ...
    addCompWidget () {
      Vue.set(this.widgets, (new Date()).getTime(), Comp.name)  // or another unique ID instead of timestamp
    }
  }

Finally, update the template to add the widgets holding your component.

<template>
...
      <lumino
        ref="lumino"
        v-on:lumino:deleted="onWidgetDeletedEvent"
        tab-title-prop="tab-title"
      >
        <comp
          v-for="widgetId of compWidgets"
          :key="widgetId"
          :id="widgetId"
          :workflow-name="workflowName"
          :other-props-as-required="String/Object/etc"
          tab-title="Super-COMP!"
        />
      </lumino>
...
</template>

You are almost done. Remember that now you have to either add the widget from one of the lifecycle methods, or from a button in the workflow/Toolbar.vue component. For the latter, you will need to update the component template to include a new list item and call @click="$listeners['add-comp']".

The $listeners is passed down to the Toolbar.vue component from the Workflow.vue view. Go back to the Workflow.vue, and look where the toolbar component is used. You need to add a new entry to the listener linking your new method with the click event, e.g.:

    <toolbar
      ...
      v-on:add-tree="this.addCompWidget"
    ></toolbar>

Widget tab title

The name displayed in the tab is, by default, the Vue component name. But that can be customized when the component is used in a template.

For example, the Tree.vue component name is “Tree”. Here's how we use this component in the Workflow.vue view template.

<v-skeleton-loader
  v-for="widgetId of treeWidgets"
  :key="widgetId"
  :id="widgetId"
  :loading="isLoading"
  type="list-item-three-line"
  tab-title="tree"
>
  <tree-component
    :workflows="tree.root.children"
  />
</v-skeleton-loader>

Note that we are already defining a title for the tree component tab, as “tree” (lower cased).