Skip to content

Coral Onboarding

OwenGalvia edited this page Dec 1, 2023 · 12 revisions

Coral

The Historic Environment Division (HED) records, protects, conserves and promotes Northern Ireland’s historic environment and has gathered a wealth of information for present and future generations to use and enjoy. This information is publicly accessible through The Historic Environment Record of Northern Ireland (HERoNI).

However a lot of data is done using paper forms or with inconsistant data collection methods.

Coral aims to use Arches to collate data in one place for all the teams across the country.
Currently, everyone enters data differently and this project is to streamline processes while maintaining shareability of the data.

Phase 1 of Coral was the data intake. This involved uploading and mapping the data.

The second phase is to do with their processes to capture their surveys and what type of information they store.

This page aims to provide information for people onboarding to Coral during phase 2.

The main knowledge required for data capture within arches is knowledge of:

  • Resource Models (graphs)
  • Cards (nodegroups)
  • Widgets (nodes)
  • Tiles (data)
  • Workflows

There should also be some information on setting up and commands/scripts that will be needed to develop during phase 2.

Resource Models (Graphs)

Resource Models are how we group our data into types.
In arches a model contains a fixed set of cards. Each card has one or more nodes which collect one specific type of information.

card

In the above example the Archive Material card has 4 visible nodes.
Archive Source accepts a 'concept' which is a predefined list of related terms.
Repository Owner accepts a reference to different resources. In this case Person or Organization resources. The other two nodes only allow text.

Screenshot from 2023-11-30 11-00-30

Since a Resource Model is a collection of these cards it means they control exactly what kinds of data are allowed in a resource of that type.
Resources can only inherit their structure from one resource model so I like to imagine them as being stored together in their own filing cabinets.

Screenshot from 2023-11-30 10-47-22

A resource is therefore a folder holding completed cards.

Workflows

HED has a lot of processes which are interconnected and may involve multiple resource models.
Also, different responsibilities for the same resource model can be divided amongst separate teams.
This means some cards on a resource model will never be used by some users but are essential for others.
HED have concerns that staff will get confused with witch fields they are meant to fill in and which are only supposed to be filled in by other teams.
Furthermore, some processes are carried out over a long period of time and different actions are needed at different stages of the process. This could leave staff unsure of which fields to update when carrying out different stages of the process.

In order to prevent these confusions Coral uses a lot of workflows.
Screenshot from 2023-11-30 11-13-12

User's can select the process they are completing and will be presented with the relevant cards to fill out. Screenshot from 2023-11-30 11-16-16

Workflows are split into 'steps' which logically organise the cards rendered on each page.
The designs for these steps are usually given to developers via penpot.


Screenshot from 2023-11-30 11-23-41

and we do our best to recreate these in arches.
Screenshot from 2023-11-30 11-26-28

The basics

To create a workflow, first we define the modules we will be using.
This tends to be knockout, arches, the workflow viewmodel, and the html for the workflow.

We make sure we register the component with a name that is not used by another component. A workflow will return the javascript logic for creating the workflow and the template provided.

// coral-arches/coral/coral/media/js/views/components/plugins/assign-consultation-workflow.js
define([
  'knockout',
  'arches',
  'viewmodels/workflow',
  'templates/views/components/plugins/default-workflow.htm', // this will work unless you need custom htm for a workflow
], function (ko, arches, Workflow, workflowTemplate) {
  return ko.components.register('archive-catalog-workflow', {
    viewModel: function (params) {
      this.componentName = 'archive-catalog-workflow';
      this.stepConfig = [
        ... // step logic will go here
      ];

      Workflow.apply(this, [params]); // it's important to include the logic from the workflow viewmodel like so

      this.quitUrl = arches.urls.plugin('init-workflow');
    },
    template: workflowTemplate
  });
});

Now we can start configuring the steps. The first step in coral tends to be an initial step. Some of these can be quite complex. A simple one can be created like below.

...
this.stepConfig = [
        {
          title: 'Initialise Archive Source',
          name: 'init-step',  // init-step and app-id are consistent naming conventions currently. Please try to use them for your own workflows.
          required: true,
          informationboxdata: {
            heading: 'Important Information',
            text: 'Boiler plate text displayed in the steps header.'
          },
          layoutSections: [
            {
              componentConfigs: [
                {
                  componentName: 'default-card',
                  uniqueInstanceName: 'app-id', // init-step and app-id are consistent naming conventions currently.
                  tilesManaged: 'one',
                  parameters: {
                    graphid: 'b07cfa6f-894d-11ea-82aa-f875a44e0e11',
                    nodegroupid: '3bdc39f8-9a93-11ea-b807-f875a44e0e11',
                  }
                }
              ]
            }
          ]
        },
      ];
...

Each step needs a title which will be displayed and a name that identifies it during the workflow logic. The name must be unique within each workflow or else there can be issues with reloading pages and potentially how data gets saved.

The required paramater dictates whether a user is allowed to move on in the workflow without saving a change during this step.

Then we place however many cards as we need for this step as componentConfigs in the layoutSections.
uniqueInstanceName is the card equivilent to the steps 'name' field. It is used to identify this card within the workflow logic. If you re-use this name you will duplicate one of the cards, even if the other information is different.
The name and uniqueInstanceName parameters are very important because they ensure data entered in later steps is sent to the correct resource and tile.

...
  this.stepConfig = [
        {
          title: 'Initialise Archive Source',
          name: 'init-step',
          required: true,
          informationboxdata: {
            heading: 'Important Information',
            text: 'Boiler plate text displayed in the steps header.'
          },
          layoutSections: [
            {
              componentConfigs: [
                {
                  componentName: 'default-card',
                  uniqueInstanceName: 'app-id',
                  tilesManaged: 'one',
                  parameters: {
                    graphid: 'b07cfa6f-894d-11ea-82aa-f875a44e0e11',
                    nodegroupid: '3bdc39f8-9a93-11ea-b807-f875a44e0e11',
                    // no resourceid or tileid are specified so arches will create new ones
                  }
                }
              ]
            },
            {
          title: 'Archive Source Details',
          name: 'app-details-step',
          required: true,
          workflowstepclass: 'workflow-form-component',
          layoutSections: [
            {
              componentConfigs: [
                {
                  componentName: 'widget-labeller',
                  uniqueInstanceName: 'source-title',
                  tilesManaged: 'one',
                  parameters: {
                    graphid: 'b07cfa6f-894d-11ea-82aa-f875a44e0e11',
                    nodegroupid: '145f9615-9ad2-11ea-b4d3-f875a44e0e11',
                    /**
                     * We want the resourceid for this card to be the same as the resourceid for the 'app-id' card in the 'init-step' step
                     * The full path is a little confusing because arches changes its case frequently and object structures aren't always obvious.
                     * */
                    resourceid: "['init-step']['app-id'][0]['resourceid']['resourceInstanceId']",
                    // there is still no tile specified so data filled into this card will create a new tile within the same resource instance as the initial step
                  }
                },
              ]
            }
          ]
        },
      ];
    }
  ]
...

componentName decides how this card should be rendered.
You can decide on any of the components which are registered to django. (usually either a card or a widget component)

owen@debian:~/codebook/coral/coral-arches$ djmang card_component list
Default Card
Grouping Card
Related Resources Map Card
File Viewer
Photo Gallery Card
IIIF Card
Map Card
owen@debian:~/codebook/coral/coral-arches$ djmang widget list
file-widget
concept-select-widget
concept-radio-widget
map-widget
concept-multiselect-widget
concept-checkbox-widget
number-widget
resource-instance-select-widget
resource-instance-multiselect-widget
datepicker-widget
rich-text-widget
text-widget
domain-select-widget
domain-radio-widget
domain-multiselect-widget
domain-checkbox-widget
radio-boolean-widget
iiif-widget
switch-widget
node-value-select
edtf-widget
urldatatype
cover-letter-widget
check-open-applications
map-with-latlon-widget
sample-widget
bngpoint
auto-generate-id-widget
photo-widget

or if you have a custom component that hasn't been registered you can define it before hand.

define([
  'knockout',
  'arches',
  'viewmodels/editable-workflow',
  'templates/views/components/plugins/default-workflow.htm',
  'views/components/workflows/archive-storage-card' // defined a custom component here
], function (ko, arches, EditableWorkflow, workflowTemplate) {
  return ko.components.register('archive-catalog-workflow', {
    viewModel: function (params) {
      this.componentName = 'archive-catalog-workflow';
      this.stepConfig = [
        ...
        {
          title: 'Repository Storage Location',
          name: 'app-location-step',
          required: false,
          layoutSections: [
            {
              componentConfigs: [
                {
                  componentName: 'archive-storage-card', // so we can use it here
                  uniqueInstanceName: 'source-location',
                  tilesManaged: 'one',
                  parameters: {
                    graphid: 'b07cfa6f-894d-11ea-82aa-f875a44e0e11',
                    nodegroupid: 'c69aa19d-fe7b-11ea-9e10-f875a44e0e11',
                    resourceid: "['init-step']['app-id'][0]['resourceid']['resourceInstanceId']",
                    parenttileid: "['app-details-step']['archive-holding'][0]['tileId']",
                  }
                }
              ]
            }
          ]
        },
        ...
      ]
      Workflow.apply(this, [params]);

      this.quitUrl = arches.urls.plugin('init-workflow');
    },
    template: workflowTemplate
  });
});

Widgets will only work for one specified datatype so if you try to use a widget on a node of a different datatype you will get rendering errors.
Card components usually have rules on how to render different datatypes but there can still be rendering errors if a card is selected that isn't suitable for the nodes.

default-card is the easiest to use since it essentially means for every widget inside the card render it in the default way.

This default is selected in the graph_designer.

widget

Here we can see the available defaults for a node with the string datatype.
There are different rules for how the widget is rendered and how the user inputs data but the data stored in that tile will always be a string.

tilesManaged decides whether we want the user to be able to fill in 'one' or 'many' tiles.
It is important to note that, in order to use 'many' you must make sure the card is for a nodegroup which has multiple cardinality.

Then within paramaters: graphid specifies which resource model this card is associated with.
nodegroupid specifies the actual card (collection of nodes) to be rendered.
There are also resourceid; tileid; parenttileid paramaters which informs arches of the structure the data are in.

default-card-util

In coral, we have created another commonly used card which inherits from default-card but adds more flexibility on how to render cards and handle their logic.

  {
    componentName: 'default-card-util',
    uniqueInstanceName: 'source-subtitle',
    tilesManaged: 'one',
    parameters: {
      graphid: 'b07cfa6f-894d-11ea-82aa-f875a44e0e11',
      nodegroupid: '145f9615-9ad2-11ea-b4d3-f875a44e0e11',
      /**
       * hiddenNodes allows us to select the widgets we do not want to render on this occasion
       */
      hiddenNodes: [
        '145f9619-9ad2-11ea-83ec-f875a44e0e11',
        '145f961a-9ad2-11ea-948a-f875a44e0e11',
        '145f9618-9ad2-11ea-925e-f875a44e0e11'
      ],
      resourceid: "['init-step']['app-id'][0]['resourceid']['resourceInstanceId']",
      /**
       * labels allows us to change the title of the card. This is useful for customising how the  * same node is displayed for different teams or use cases
       */
      labels: [['Archive Source Name', 'Subtitle']],
      /**
       * prefilledNodes allows us to set values on behalf of our users.
       * we commonly use this to automatically fill in 'type' nodes
       * in this case we have prefilled the node for 'Archive Source Name Type' with the concept id * for 'subtitle'
       */
      prefilledNodes: [
        [
          '145f9618-9ad2-11ea-925e-f875a44e0e11',
          'c109d688-2ff4-45c5-873c-1a2ebc93d4fa'
        ]
      ]
    },
    ...
    {
                  componentName: 'default-card-util',
                  uniqueInstanceName: 'archive-holding',
                  tilesManaged: 'one',
                  parameters: {
                    graphid: 'b07cfa6f-894d-11ea-82aa-f875a44e0e11',
                    nodegroupid: '66576cda-9b69-11ea-9143-f875a44e0e11',
                    resourceid: "['init-step']['app-id'][0]['resourceid']['resourceInstanceId']",
                    hiddenNodes: [
                      '66576cda-9b69-11ea-9143-f875a44e0e11',
                      'e31709dd-b469-11ea-ae1c-f875a44e0e11',
                      'c69aa19d-fe7b-11ea-9e10-f875a44e0e11',
                      '3001afdf-b46a-11ea-a528-f875a44e0e11'
                    ],
                    /**
                     * hiddenCard allows us to not render the card at all.
                     * Here this is used to have an archive holding nodegroup to be instantiated
                     * This will allow nodegroups in future steps to use
                     * parenttileid: "['app-details-step']['archive-holding'][0]['tileId']"
                     * This is also commonly used for location Data where cards such address and geometries cards both need to
                     * belong to location data nodegroup
                     */
                    hiddenCard: true
                  }
                }
  },

workstepclass

By default arches sets quite a large fixed size for each card. If you are putting lots of cards into a step you will want to prevent this.
To do this we created out own CSS override.

/** coral-arches/coral/coral/media/css/project.css */
/**
 * Custom CSS Overrides by F&T
 */

.workflow-form-component {
  height: min-content;
}

We can then use this as the workflowstepclass paramater.

  {
    title: 'Archive Source Creation',
    name: 'app-creation-step',
    required: false,
    workflowstepclass: 'workflow-form-component', // here
    layoutSections: [
      {
        componentConfigs: [
          {
            componentName: 'default-card-util',
            uniqueInstanceName: 'source-creation',
            tilesManaged: 'one',
            parameters: {
              graphid: 'b07cfa6f-894d-11ea-82aa-f875a44e0e11',
              nodegroupid: '3001afdf-b46a-11ea-a528-f875a44e0e11',
              resourceid: "['init-step']['app-id'][0]['resourceid']['resourceInstanceId']",
              parenttileid: "['app-details-step']['archive-holding'][0]['tileId']"
            }
          }
        ]
      }
    ]
  },

It's possible we will create more overrides in the same way as development continues.

Registering Workflows

Once you've completed the workflow you need to register it before user's can access it.

# coral-arches/coral/coral/plugins/archive-catalog-workflow.json
{
  "pluginid": "7089fecd-c110-4b03-bbff-5f3cc78a92b8", // it will create it's own if this is not provided
  "name": "Archive Cataloguing",
  "icon": "fa fa-check",
  "component": "views/components/plugins/archive-catalog-workflow",
  "componentname": "archive-catalog-workflow",
  "config": {
    "show": false
  },
  "slug": "archive-catalog-workflow",
  "sortorder": 0
}

This is done via the django script manage.py
djmang is a useful script see (link) which runs manage.py in the container from your local machine.

djmang plugin register --source coral/plugins/archive-catalog-workflow.json

If you want the workflow to appear on the workflow selection screen you will also need to add it to init-workflow.json

# coral-arches/coral/coral/plugins/init-workflow.json
{
  "pluginid": "49507fb0-89c6-47b7-b506-9b2b29a3b8d8",
  "name": "Workflows",
  "icon": "fa fa-play-circle",
  "component": "views/components/plugins/init-workflow",
  "componentname": "init-workflow",
  "config": {
    "unusedArchesWorkflows": [
      ...
      {
        "workflowid": "7089fecd-c110-4b03-bbff-5f3cc78a92b8",
        "slug": "archive-catalog-workflow",
        "name": "Archive Cataloguing",
        "icon": "fa fa-file-text",
        "bgColor": "#689480",
        "circleColor": "#79b59a",
        "desc": "A workflow for Archive Sources and Cataloguing"
      },
      ...
    ],
    "show": true
  },
  "slug": "init-workflow",
  "sortorder": 0
}

and update the init-workflow

djmang plugin update --source coral/plugins/init-workflow.json

Editable Workflows

Since HED have processes which span for months or potentially years, they need to be able to re-enter workflows.
This is not a core functionality in Arches. Arches treats workflows as individual processes so 'create new licence' and 'edit existing licence' or 'add correspondence record' would be separate workflows acting on the same resource. HED felt this would be confusing and wanted a main workflow for the entire process and we have had to implement a custom way of achieving this.

The typical process for a workflow is as follows: -1 A workflow is prepared for the user, selecting the cards needed from any resource model required. -2 The user completes the workflow and the data for each card is saved as a tile -3 The tiles are then taken from the workflow and reorganised back into resource instance(s) in the same structure as their respective resource models and stored as normal (in their filing cabinet to continue the analogy)

Screenshot from 2023-11-30 14-10-57

The workflow only exists while people are using it.

We need to be able to select a resource instance and have our workflow work out which tiles came from which section of the workflow.
This is complicated by the fact that a workflow might use the same card in multiple places. For example in the licensing workflow External Cross Reference is used for CM ref, SMR, Planning Reference etc. The workflow renders that card multiple times but prefills the 'type' node to differentiate them.

// coral-arches/coral/coral/media/js/views/components/plugins/archive-catalog-workflow.js
define([
  'knockout',
  'arches',
  'viewmodels/editable-workflow', // we changed the viewmodel
  'templates/views/components/plugins/default-workflow.htm',
], function (ko, arches, EditableWorkflow, workflowTemplate) {
  return ko.components.register('archive-catalog-workflow', {
    viewModel: function (params) {
      this.componentName = 'archive-catalog-workflow';
      this.stepConfig = [
        ...
      ];

      this.safeArrayAccesses = ['resourceInstanceId', 'tileId']; // and declare which values are needed to determine the correct cards to load tiles into

      EditableWorkflow.apply(this, [params]);

      this.quitUrl = arches.urls.plugin('init-workflow');
    },
    template: workflowTemplate
  });
});

For this workflow, making it editable is relatively simple. We only need the resource id and tile id to figure out the correct place to display the tiles.
We write the logic for how the workflow should find archive specific data in edit-workflow.js

// coral-arches/coral/coral/media/js/views/components/plugins/edit-workflow.js
this.loadArchiveData = async (archiveResourceId) => {
  const archiveTiles = await this.fetchTileData(archiveResourceId);
  componentData = {};
  this.resourceName(
    this.getNameFromNodeId(archiveTiles, '145f961b-9ad2-11ea-bf90-f875a44e0e11') // an extra bit of logic just for finding the tile that names the resource
  );
  archiveTiles.forEach((tile) => {
    componentData[tile.nodegroup] = {
      value: JSON.stringify({
        tileData: koMapping.toJSON(tile.data),
        resourceInstanceId: tile.resourceinstance,
        tileId: tile.tileid,
        nodegroupId: tile.nodegroup
      })
    };
  });
  return componentData;
};

There is an additional step in registering an editable workflow.
We must register it as an editable workflow in the edit-workflow.json

# coral-arches/coral/coral/plugins/edit-workflow.json
{
  "pluginid": "90d00be6-c447-4fef-8b98-cf0579fb4a65",
  "name": "Edit Workflow",
  "icon": "fa fa-edit",
  "component": "views/components/plugins/edit-workflow",
  "componentname": "edit-workflow",
  "config": {
    "show": false,
    "editableWorkflows": [
      ...
      {
        "slug": "archive-catalog-workflow",
        "name": "Archive and Cataloguing",
        "graphId": "b07cfa6f-894d-11ea-82aa-f875a44e0e11",
        "setupFunction": "loadArchiveData" // this is the function from the code-block above
      },
      ...
    ]
  },
  "slug": "edit-workflow",
  "sortorder": 0
}

and then update init-step.json in the following way:

coral-arches/coral/coral/plugins/init-workflow.json
{
  "pluginid": "49507fb0-89c6-47b7-b506-9b2b29a3b8d8",
  "name": "Workflows",
  "icon": "fa fa-play-circle",
  "component": "views/components/plugins/init-workflow",
  "componentname": "init-workflow",
  "config": {
    "unusedArchesWorkflows": [
      ...
      {
        "workflowid": "7089fecd-c110-4b03-bbff-5f3cc78a92b8",
        "slug": "edit-workflow?workflow-slug=archive-catalog-workflow", // notice that the slug is for edit-workflow with the selected workflow slug as a query string.
        "name": "Archive Cataloguing",
        "icon": "fa fa-file-text",
        "bgColor": "#689480",
        "circleColor": "#79b59a",
        "desc": "A workflow for Archive Sources and Cataloguing"
      },
      ...
    ],
    "show": true
  },
  "slug": "init-workflow",
  "sortorder": 0
}

Both the init-workflow and the edit-workflow plugins will need updated for this to work.

djmang plugin update --source coral/plugins/init-workflow.json

djmang plugin update --source coral/plugins/edit-workflow.json

and now we should see this screen when we enter the archive cataloguing workflow

Screenshot from 2023-11-30 14-54-56

Advanced Initial Steps

Todo

custom components

Todo

related-document-upload

Todo

custom steps

Todo

custom templates

Todo

Useful Scripts

There are a number of useful scripts which will help to speed up your productivity.

cli util

this provides a list of useful aliases to speed up setting up, rebuilding the webpack, making local changes to the arches_1 container and finding uuid's

# coral-arches/cli_util.sh
alias rbwebpack="rm -f log && docker exec -ti coral-arches_arches_1 /bin/sh -c '. ../ENV/bin/activate; cd coral; DJANGO_MODE=DEV NODE_PATH=./media/node_modules NODE_OPTIONS=--max_old_space_size=8192 node --inspect ./media/node_modules/.bin/webpack --config webpack/webpack.config.dev.js'"
alias rbwebpacklog="rm -f log && docker exec -ti coral-arches_arches_1 /bin/sh -c '. ../ENV/bin/activate; cd coral; DJANGO_MODE=DEV NODE_PATH=./media/node_modules NODE_OPTIONS=--max_old_space_size=8192 node --inspect ./media/node_modules/.bin/webpack --config webpack/webpack.config.dev.js' 2>&1 > log"

alias djmang='docker exec -it coral-arches_arches_1 bash -c "source ../ENV/bin/activate && python manage.py \"\${0:-help}\" \"\$@\""'

coralup_fn() {
  # if [ ! -d "../docker-arches" ]; then
  #   docker create --name arches_temp_container arches_coral
  #   docker cp arches_temp_container:/web_root/arches ../docker-arches
  #   docker rm arches_temp_container
  # fi
  docker-compose --env-file docker/env_file.env up
}
alias coralup=coralup_fn

alias archesbash='docker exec -it coral-arches_arches_1 bash'

# This command must be ran from the two repositorys, both folders should be visible
archescopy_fn() {
  docker cp ./$1 coral-arches_arches_1:/web_root/$1
}
alias archescopy=archescopy_fn

# docker cp ./arches/arches/app/media/js/viewmodels/workflow-step.js coral-arches_arches_1:/web_root/arches/arches/app/media/js/viewmodels/workflow-step.js

# Can be used to find things such as UUID's across the project
coralfind_fn() {
  find -path ./coral/coral/media/build -prune -o -type f -exec grep --color -n -E $1 {} + | cut -b 1-400
}
alias coralfind=coralfind_fn

You can load the aliases into your current terminal from the coral-arches directory with

source cli_util.sh
# or
. cli_util.sh
  • coralup: starts all of the containers
  • rbwebpack: rebuilds the webpack (necessary after making changes to javascript code)
  • djmang: allows you to use manage.py commands in the arches_1 container's virtual environment from your local terminal
  • archesbash: enter the arches_1 container
  • archescopy: Replaces files in the arches container with your local version; useful for adding logs (must be done from the parent directory which contains coral-arches/ and arches/)
  • coralfind: a quick way to grep for words or uuids within the coral-arches directory

djmang

Some of the commonly used djmang commands are:

  • djmang [plugin | widget | card_component | fn] list: lists the currently registered pligins, widgets, cards, and functions resplectively

  • djmang [plugin | widget | card_component | fn] register

  • djmang [plugin | widget | card_component | fn] update

  • djmang [plugin | widget | card_component | fn] unregister

  • djmang packages -o import_graphs [-s path_to_json_directory_or_file]

  • djmang packages -o import_reference_data -s 'path_to_rdf_file' [-ow {'overwrite'|'ignore'}] [-st {'stage'|'keep'}]

  • djmang coral reload: compares the list of registered components to the files in coral-arches/ it will register files you have which are unregistered and unregister files when it can not find the component in the correct directory

scripts/

Two of the scripts in this directory are for managing your arches deployment.

  • scripts/build_project.sh: rebuilds the docker containers
  • scripts/reset_db.sh: destroys and recreates your arches database. This takes around 30 minutes so should only be done if absolutely necessary

create-workflow script

python3 scripts/generate_new_workflow.py new-workflow

This very handy python scripts will create the files needed for a workflow and update the init-workflow and edit-workflow steps.
The above command will generate:

// coral-arches/coral/coral/media/js/views/components/plugins/new-workflow.js
define([
  'knockout',
  'arches',
  'viewmodels/editable-workflow',
  'templates/views/components/plugins/default-workflow.htm'
], function (ko, arches, EditableWorkflow, workflowTemplate) {
  return ko.components.register('new-workflow', {
    viewModel: function (params) {
      this.componentName = 'new-workflow';
      this.stepConfig = [
        {
          title: 'Initialise Workflow',
          name: 'init-step',
          required: true,
          layoutSections: [
            {
              componentConfigs: [
                {
                  componentName: 'default-card',
                  uniqueInstanceName: 'app-id',
                  tilesManaged: 'one',
                  parameters: {
                    graphid: '',
                    nodegroupid: ''
                  }
                }
              ]
            }
          ]
        }
      ];

      EditableWorkflow.apply(this, [params]);

      this.quitUrl = arches.urls.plugin('init-workflow');
    },
    template: workflowTemplate
  });
});

and

# coral-arches/coral/coral/plugins/new-workflow.json
{
  "pluginid": "9c7f9571-8c70-4c68-b9c4-5d2c81a9c3f5",
  "name": "new-workflow",
  "icon": "fa fa-check",
  "component": "views/components/plugins/new-workflow",
  "componentname": "new-workflow",
  "config": {
    "show": false
  },
  "slug": "new-workflow",
  "sortorder": 0
}

as well as updating init-workflow.json

# coral-arches/coral/coral/plugins/init-workflow.json
{
  "pluginid": "49507fb0-89c6-47b7-b506-9b2b29a3b8d8",
  "name": "Workflows",
  "icon": "fa fa-play-circle",
  "component": "views/components/plugins/init-workflow",
  "componentname": "init-workflow",
  "config": {
    "unusedArchesWorkflows": [
      ...
      {
        "workflowid": "9c7f9571-8c70-4c68-b9c4-5d2c81a9c3f5",
        "slug": "new-workflow",
        "name": "new-workflow",
        "icon": "fa fa-check",
        "bgColor": "#8096ba",
        "circleColor": "#a3b5d4",
        "desc": "Please provide a description for this workflow"
      }
      ...
    ],
    "show": true
  },
  "slug": "init-workflow",
  "sortorder": 0
}

graph-component-export endpoint

Finding the node/nodegroup/graph id's when making workflows is the most time consuming part.
There is now an enpoint which makes this much quicker.

http://localhost:8000/graph-component-export?graph-id=b9e0701e-5463-11e9-b5f5-000d3ab1e588

replace the graph-id with the one you are creating a workflow for.

this will download a json which has all of the cards in a resource model organised how they would be used in a workflow.

Screenshot from 2023-11-30 16-09-19

all of the nodes are placed in the hiddenNodes with their names commented. Simply remove the nodes you actually want to render and this will work.