shacl-vue/docs/features-wizard-editors.md
Stephan Heunis 3c091c324f New wizard editor component
This feature allows custom form dialog construction via config, as well as TTL template
specification, which is then string-serialized using the user inputs upon form save, followed
by adding the parsed quads to the graph store. This is a powerful feature that allows
arbitrarily complex user input and metadata linkage via relatively simple primitive form
input configuration. These wizard editors can be configured to appear for any class.
These are the working principles:

- a new wizard is declared and configured via the new 'wizard_editors' option, which allows
  several standard options along with the important: an array of 'inputs' and the 'template'
- 'inputs' have to specify the 'type', among other rendering options; currently supported
  'type's include 'text', 'text-paragraph', and 'boolean'. The plan is to extend these
  substantially, possibly driven by LinkML types provided by a specific schema, but also
  allowing already supported 'shacl-vue' editors. Each 'input' configures the associated
  input component in the wizard form, and they will render in the order provided via
  configuration.
- 'input's also have to specify a unique 'prop', which becomes the field name through which
  this input is referenced, both in 'shacl-vue' internals and inside the TTL template.
- the 'template' should be a TTL string, with to-be-populated field names inside
  'curly brackets'. Field names include all 'prop's configured for 'input's, as well as
  'pid', which refers to the identifty of the current record being edited and from which
  the wizard is launched. TTL can either be supplied directly as a string, or as a URL via
  the existing 'content' option.
- declared wizards are configured for rendering for specific classes via the new option
  'wizard_editor_selection'.
- wizards can be supplied with icons via configuration; these can come in different formats:
  - an 'mdi-' string which will render any of the standard free 'mdi' icons
  - an svg string, which will be rendered as is
  - a 'content:' pointer to an SVG file, which will be loaded and rendered as is
  Importantly, any SVG used in this context should have a viewport or width/height of 24x24 px

This commit includes a documentation update that covers all details related to the wizard
editor feature, extensively.

To achieve the above, the following major code changes were done:
- The 'NodeShapeEditor', which renders for a given record when it is being created or edited
  inside the 'FormEditor', will check the 'wizard_editor_selection' to see if any wizards need
  to be made available for the current record type (a.k.a. class). If yes, it will render those
  as buttons at the top of the form below the 'All fields' button. The wizards render as clickable
  buttons, with customizable tooltips and icons, which will open a dialog when clicked, passing
  along all config options related to the selected wizard
- The new 'WizardEditor' will render inside the dialog. It will display all general config
  options of the wizard, and will then render a row per input. Inputs have their own descriptions
  and validation rules embedded (taken from config). Reset and Cancel buttons are self-explanatory.
  The save button will run validation on all inputs, and on successful validation will emit a 'save'
  event to the parent component ('NodeShapeEditor'), also passing along all entered input values.
- On detecting a 'save' event from a wizard, the 'NodeShapeEditor' will:
   - receive the input values and declare them as 'wizardData'
   - add the node ID of the current record to the 'wizardData' under the 'pid' field, which is how
     the record can be referenced inside the TTL template
   - pass 'wizardData' to the existing 'fillStringTemplate' utility function to render valid TTL
     output
   - pass the TTL to 'rdfDS.parseTTLandDedup(newTTL)' that outputs quads and adds them to the graph
     store
- 'rdfDS.parseTTLandDedup(newTTL)' returns all the quads that were parsed and added to the graph
  store. These are now process individually. Importantly, if an added quad has a subject value that
  is identical
  to the current node ID, we delete it from the graph store, because it uses a nonsense named node
  (the node ID of the record, which is not reproducibly identical to the record PID). However, we
  also add the quad's object to the 'formData' under the index of the current node and the quad's
  predicate, in order to keep linkage to the TTL-parsed quads. Importantly, the existing standard
  functionality that runs when saving a form (for record creation or editing) will then take care
  of adding the correct quads to the graph store to replace those that were deleted.
- Continuing with the individual processing of quads that were parsed from TTL and added to the graph
  store, if an added quad has a subject value that is NOT identical to the current node ID, AND it
  is a named node, this means that a new record has been added to the graph store and it is therefore
  eligible for submission. This is added to 'savedNodes' and 'nodesToSubmit', as well as a separate
  'NodeShapeEditor'-specific tracker of all wizard-added quads.
- Garbage cleanup is also necessary in the case where quads were added to the graph store by a wizard
  but the form was then subsequently cancelled. To deal with this, 'NodeShapeEditor' registers a form
  cancel handler via the existing 'registerHandler' functionality, which will delete all the relevant
  quads.

Lastly, for improved UI the headings of 'property groups' in the 'NodeShapeEditor' have been
removed. This is in anticipation of the complete removal of parent-class-based grouping of
properties inside the 'NodeShapeEditor'.
2026-02-04 18:40:17 +01:00

134 lines
No EOL
6.8 KiB
Markdown

---
layout: doc
---
# Wizard editors
Sometimes the standard `shacl-vue` approach of matching a dedicated editor component to a single modeled property shape does not fully address the use case at hand. Think of creating complicated, multi-jump linkages between a record being edited and some other records, perhaps multiple at a time.
Let's take the following example: a user might want to add a DOI (Digital Object Identifier) to a `Publication` record, but there is no `doi` property on the `Publication` class, and instead:
- a `Publication` has an `identifiers` slot, with the range `Identifier`
- the `Identifier` class has slots: `notation` and `creator`
- there is also a `DOI` class that subclasses from `Identifier`
- to create a `DOI` record, the `notation` is important while the `creator` is already known
Ideally, all of these classes and slots and linkages are details that should be of no concern to the user. They just want to add a DOI for their publication (actually the only really required field to enter is `notation`!) and having to do that via the existing route (find the `identifiers` slot -> create a new `DOI` record -> add `notation` -> add the `creator` correctly! -> finally save and link the created `DOI` record) is unnecessarily complex and bad UX.
There should be simpler way to achieve this. And there is, using the "Wizard Editor"!
This is a powerful feature that allows specification of arbitrarily complex user input and metadata linkage via relatively simple configuration of primitive form inputs and metadata templates. Think of it as a way to:
- specify which arbitrary inputs should be shown in a form
- specify how those input values should feed into a TTL template
- autocreate arbitrarily complex and linked metadata upon saving the wizard form
A wizard editor can be configured to appear for any class, to use any of the supported inputs, and to use any TTL template. Specific configuration options are provided below.
## Wizard configuration
This section will provide all currently available wizard configuration options using the DOI use case as a demonstrator, with the following config:
```yaml
wizard_editor_selection:
xyzri:XYZPublication:
- DOIWizard
wizard_editors:
DOIWizard:
name: DOI Wizard
description: Enter the 'Notation' field and hit *Save* in order to create a DOI record
icon: mdi-identifier
tooltip: Add a DOI
inputs:
- prop: notation
name: Notation
description: This is the unique DOI identifier text usually following 'http://doi.org/'
type: text
placeholder: 'example: 10.21105/joss.03262'
required: true
pattern: # some XSD-compatible regular expression
default: # some default value
template: content:DOIWizardTemplate
content:
DOIWizardTemplate:
url: DOIWizardTemplate.ttl
```
### `wizard_editor_selection`
This option provides a means to specify which wizards should show up for which classes. It is an object with class IRIs as keys (in CURIE format) and associated values being lists of wizards to make available for the class identied by the key.
### `wizard_editors`
This is the main config option that allows creation of a wizard editor and specification of its `input`s, `template`, and other options. The wizard receives a key (here `DOIWizard`), and then its options:
Wizard options include:
#### `name`
This is a human-readable name for the wizard that will be displayed at the top of the wizard form.
#### `description`
This is human-readble descriptive text or instructions to help users understand the context and purpose of the form, and will render inside the initiated wizard form underneath the name.
#### `icon`
This provides a means to specify the icon image that will show up on records for which the specific wizard has been configured to render. Clicking on the icon is the primary and only way to open the associated wizard editor. Icons can be specified in different formats:
- an `mdi-` string which will render any of the standard free icons from the [`mdi` icon library](https://pictogrammers.com/library/mdi/)
- an svg string, which will be rendered as is
- a `content:` pointer to an SVG file, which will be loaded and rendered as is
Importantly, any SVGf file or string used in this context should have a viewport or width/height of `24x24 px`.
#### `tooltip`
This is a short human-readable sentence that will show when the cursor hovers over the wizard icon and is intended to explain shortly what the wizard does.
#### `input`s
The core of the wizard lies in its specification of `input`s. An `input` can have several properties:
- `prop` is the field name through which this input is referenced, both in `shacl-vue` internals and inside the TTL template
- `name` will render as the input label
- `description` is a further description of the input that will render when hovering over the input label
- `type` tells `shacl-vue` which type of input component to render, for which the input value will be captured; currently only `text`, `text-paragraph` and `boolean` are supported, and many more are in the pipeline
- `placeholder` will render if the field has no entered value yet
- `required` will make the field required (or not) for validation purposes
- `pattern` will apply a regular expression check to text-based inputs for validation purposes
- `default` will prepulate the value of the input
#### `template`
Another core part of the wizard specification is the TTL template string, which will be populated using the values entered for the wizard inputs. The TTL string format is the same as is already supported by `shacl-vue`. For example:
```ttl
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix dlthings: <https://concepts.datalad.org/s/things/unreleased/> .
@prefix ror: <https://ror.org/> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
<{pid}> dcterms:identifier _:n0-1.
_:n0-1 a dlthings:DOI;
skos:notation "{notation}";
dcterms:creator ror:01fyxcz70.
```
Note the following inside the template:
- `{pid}` is the standard way to refer to the record within the context of which the wizard editor is rendered, for example if the `DOIWizard` is initiated from a specific `Publication` record, that record's identifier becomes available inside the TTL template.
- `{notation}` is an example of how the `prop` of a configured `input` is used to reference it inside the TTL template
The TTL template can be specified as a direct string inside the configuration, but also as a file via a `content:` pointer to the file URL.
Finally, another new config option `wizard_editor_selection` can be used to specify which wizards should be made available to which classes. The config above says: show the `DOI Wizard` for `xyzri:XYZPublication` records (during creation/editing).
## Wizard editor demo
::: info
TODO
:::