ISA-95 hierarchy controlled vocabulary#663
Merged
Merged
Conversation
6fcb037 to
69b0f85
Compare
A leftover `toast.warning("Test message")` fired on every CSV import,
showing a meaningless warning to the user.
The ISA-95 levels are a controlled vocabulary, editable only through the ISA-95 Hierarchy panel, and hidden from the metric tree. CSV import knew nothing about this: it wrote every schema leaf it found, so exporting a device, typing free text into the ISA-95 columns and re-importing would bypass the vocabulary entirely. Skip those rows before the model traversal, so an import can neither write a hierarchy value nor create the ISA95_Hierarchy parent object as a side effect. An empty CSV cell can no longer delete an existing value. Export is unchanged: the columns are still emitted, so a CSV remains a complete picture of the device. Rows whose value the CSV would have changed are counted and reported in a toast, pointing the user at the panel. An untouched round-trip reports nothing.
AlexGodbehere
added a commit
that referenced
this pull request
Jul 9, 2026
# ISA-95 hierarchy editor and device import ## Summary Adds a first-party editor for the ISA-95 controlled vocabulary introduced by #663, plus a one-click migration that builds the vocabulary from the free-text hierarchy values already saved on devices. Built on #663, which merged this morning. ## Changes ### ISA-95 page (`acs-admin/src/pages/ISA95/`) A new top-level "ISA-95" nav entry, following the same shape as the Bridges page: searchable table of all vocabulary nodes (name, level, parent, aliases) with a Level filter, and a details sidebar with edit/delete actions. - **Create/edit dialog**: level, name, parent (required for non-Enterprise levels so every node stays reachable from a root), and an alias list. Creates the ConfigDB object in the right level class, names it via the Info app, writes the `ISA95Vocabulary` config and links it into the parent's `children`. - **Delete**: unlinks the node from every parent before deleting so no vocabulary config points at a dead UUID. Nodes with children can't be deleted - prune bottom-up instead of orphaning subtrees. ### Import from Devices (`useISA95Migration.js`, `ImportISA95Dialog.vue`) Scans every device's origin map for `Device_Information.ISA95_Hierarchy` values, shows a preview (new nodes with their parents, aliases to add, devices skipped), then applies. Notable behaviour: - **Scoped matching**: a value only matches a node that is a child of the node matched at the level above, so "Building 1" under two different enterprises stays two nodes - no cross-tree merging. - **Case-insensitive with alias capture**: `amrc` matches canonical `AMRC`, and the typed variant is saved as an alias so the device's exact text resolves against the vocabulary. - **Gaps**: values below a missing level (an Area with no Site) can't be placed in the tree; they're counted, reported in the preview, and left on the device untouched. - The planning logic is a pure module with the ConfigDB writes confined to `apply_plan`, so it's testable without a browser. ### Store (`useISA95Store.js`) Exports the level-to-class map and adds a `parents_of` getter alongside the existing `children_of`. ## How to test 1. Open the new **ISA-95** nav entry. With no vocabulary, you get an empty state. 2. Create an Enterprise, then a Site under it. The parent dropdown for a Site only offers Enterprises, and is required. 3. Open a device with hierarchy values typed in (or set some free text via the metric editor on a pre-#663 build), then use **Import from Devices**. The preview should show the chain of new nodes; import and check the Device page's ISA-95 panel now resolves those values. 4. Re-run the import: it should report nothing to do. 5. Save a device value differing only in case from a canonical name, re-import: no new node, the variant appears as an alias on the existing node. 6. Try to delete a node with children: refused with a toast. Delete a leaf: it disappears from its parent's children list in the sidebar. ## Testing done - Migration planning/apply logic covered by a 20-case harness driven against the real module (scoped matching, alias capture and dedup, gap handling, existing-node merges, ConfigDB call contents via a mock client). - `vite build` passes; new modules confirmed present in the bundle. - No UI-in-browser testing - needs a review pass on a live install. ## Release notes A first-party editor for the ISA-95 hierarchy vocabulary is available under "ISA-95" in the admin UI, including a one-click import that builds the vocabulary from the hierarchy values already saved on existing devices.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ISA-95 hierarchy controlled vocabulary
Summary
Introduces a controlled vocabulary system for ISA-95 hierarchy values (Enterprise -> Site -> Area -> Work Centre -> Work Unit) to prevent inconsistent free-text entries across devices.
Hierarchy nodes are first-class ConfigDB objects. Each node has a canonical name (via the existing Info app) and an optional list of aliases and child-node UUIDs (via a new
ISA95Vocabularyapp). The Manager UI enforces selection from this vocabulary instead of allowing free-text entry.Changes
ConfigDB bootstrap (acs-service-setup/dumps/isa95.yaml)
Shared library (lib/js-service-client/lib/uuids.js)
ISA95Vocabulary) added to the shared constantsManager UI (acs-admin)
useISA95Store.js- new Pinia store that reactively watches all five level classes and combines member lists withISA95VocabularyandInfoconfigs viacombineLatest. Exposesenterprises,by_uuid,children_of, andfind_by_name(which searches both canonical name and aliases).ISA95HierarchyPanel.vue- new sidebar panel on the Device page with five cascading comboboxes, one per level. Each combobox is disabled until its parent level is selected. Selecting a value clears all lower levels. Alias search is built in: typing matches against the node name and any configured aliases.SchemaGroup.vue-ISA95_Hierarchyis unconditionally excluded from the schema tree so it never appears as an editable node in the left-hand metric list.SparkplugMetric.vue- when a metric path resolves to an ISA-95 level field, the free-text input is replaced with the same combobox (alias search, cascade clearing) for users who navigate to those metrics directly.Device.vue- wires the panel into the page; routes panel@changeevents toOriginMapEditor.applyISA95Selectionso the save model and the tree re-render are always in sync.OriginMapEditor.vue-applyISA95Selectionmethod applies hierarchy mutations directly tothis.model(the object that gets saved), bumpsgroupRerenderTrigger, and sets the correct null-delete values for cleared levels. The panel is only shown when the device's schema references the Device Information sub-schema.How to test
ISA95Enterprise,ISA95Site, etc. and give each anISA95Vocabularyconfig with aliases and children arrays linking them into a tree.