New approach to generating/maintaining list of records + ShaclVueStarter feature #349
No reviewers
Labels
No labels
bug
config
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
orinoco/shacl-vue!349
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "shaclvue-kickstarter"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
New approach to generating/maintaining list of records
The premise of this change is that the
getInstanceItemsapproach to generating the list of displayed records (from graph data) results in bad performance. This is mainly becausegetInstanceItemsis called many times (mainly triggered by a watcher reacting to any graph changes), each time regenerating the full list of records. The proposed new approach is based on maintaining a global list of items that is incrementally updated when new nodes are added to or updated in the graph.parseTTLandDedupis theReactiveRdfDatasetclass method that receives incoming TTL strings parses it into quads, deduplicates blank nodes, and adds it to theN3store. It already provided an array with all added quads as the return value. A new utility function,getUniqueRootNodes, is now used to determine the unique named nodes that are included in the added quads. This allows saying: 'these are the records that were just added or updated' in the graph store.parseTTLandDedupnow returns both the added quads and the array of unique added/updated record IRIs, and downstream functionality using it has been updated to access its outputs correctly. A newReactiveRdfDatasetclass methodemitAddedRecords(records)is also added, which can be called with an array of named node (i.e. record) IRIs and which usesdispatchEventto emit the newrecordsChangedevent, for which listeners can be added.emitAddedRecordsis now used in multiple places in order to emit records that have just been added/updated (because of this, the previous calls tordfDS.triggerReactivitybecome redundant):useDatacomposable, insidefetchRdfDataright afterparseTTLandDedupreturns the list of unique added/updated records. This happens downstream for every call tofetchFromService, which is the standard way in whichshacl-vuegets backend data in response to user interaction.useWizardcomposable: here we only callemitAddedRecordsif the context is not_recordbecause it means there is no open form (which would need to process added quads in its own way); it means the wizard immediately adds all quads to the graph.FormEditorcomponent when the user saved the record, i.e. in thesaveFormfunction. Here it is called specifically when the record is a PID record (i.e. not a blank node).Now, onto the algorithmic change for
getInstanceItems, which is done in theuseRecordscomposable. As mentioned, we now maintain a global list of items (recordItemsAllandrecordItemsByClass) that is incrementally updated when new nodes are added to or updated in the graph. This composable handles the new process as follows:rdfDSfor the newrecordsChangedevent, which calls the newenqueueChangesfunctionenqueueChangesadds all added/updated records to a queue, and runs the code to process the queueprocessQueuewill keep on running as long as there are records in the queue, and will process records in batches of 10 by calling theupdateRecordItemfunction per recordupdateRecordItemruns all the code that used to be run per item bygetInstanceItems, and then adds the processed record to therecordItemsAllandrecordItemsByClassreactive variablesfilteredRecordItemsAllandfilteredRecordItemsByClasswhich filters all records and record per class based on search text, as well asfilteredRecordItemsForClassWithSubclassItemswhich filters records per class while also including all records of a class's subclasses, which is required for the existingpriority_classes/include_subclassesconfig feature.The main
ShaclVuecomponent has been updated to use the adjusteduseRecordscomposable correctly, specifically passing the new filtered computed refs to theShaclVueRecordscomponent, which has updated propsfilteredRecordsandfetchedItemCountto handle the new composable structure.Also, as part of cleanup several previous computed refs were moved as functions to the
useShapescomposable:getIdFilteredNodeShapeNamesgetNoEditClassListgetFilteredNodeShapeNamesgetPriorityFilteredNodeShapeNamesgetOrderedNodeShapeNamesgetAllClassItemsThese are now called on app startup during config processing.
Lastly, the
useWizardcomposable has been updated to include a new feature needed by the upcoming kickstarter component. This feature allows a wizard to be shown not specifically for a record, nor specifically for a class, but for all classes. It's goal is to allow the configuration of very generic wizards that would be applicable for all classes. The config spec for it's selection is as follows (withAddRecordWizardbeing an example wizard name):To allow distinction of the applicable class IRI when the associated wizard template is processed, the class IRI is now made part of the wizard data by default in
handleWizardSave(accessible asclass_uri). AlsoshowWizardGroupandsetupWizardsfunctions are updated to handle the newwizard_editor_selectionkey.Introduce new
ShaclVueStarterapp variantThis work is in response to the identified need for kick-starting the user-based entry of domain-specific knowledge into a
shacl-vuemetadata system, so that a critical mass for continued use of the system is available soon after deploying it for the first time. The newShaclVueStartercomponent is designed to encourage users to enter minimal records in a quick, intuitive, and interactive way. It has the following features:shacl-vuedeployment. This requires the specification of a Vite-recognizable environment variable,VITE_SHACLVUE_VARIANTthat influences whether the application is built with the (default)ShaclVuecomponent or the newShaclVueStartercomponent. An example command for building the starter app:If the environment variable is not specified, the default application will be built.
Instead of making only a single class selectable at a time,
ShaclVueStartershows all record types (aka classes), and many records per class. The user can scroll down the main view through all classes, and relevant records can be scrolled within each class "card". The left-hand-side pane now shows the list of classes with added checkboxes, which allows including/exluding classes from being displayed in the main view.A
ShaclVueStarterdeployment uses the new_classesoption of thewizard_selectionconfiguration to specify a wizard that will be shown for all classes. This allows the use of a generic "add new record" wizard that only asks for a display name and description, with example config:Text search functionality provides the same UX as before, however the search now happens across all records, i.e. not only on a single class-level.
Unnecessary detail and functionality from the default
ShaclVueapplication are not available in the starter application. This mainly means the record viewer is minimalistic, containing just the display name and a mini menu button with options to edit the record (which will open the established form) and view the record RDF.New/updated functionality to support all of the above:
ShaclVueStarter,ShaclVueRecordsMini, andNodeShapeViewerMinicomponentsApp.vuenow dynamically loads the main entrypoint components and uses<component :is="">to render the component that is selected based on theVITE_SHACLVUE_VARIANTvalueShaclVueStarteruses a newgetFirstPages()function during app startup in order to fetch the first page from the dumpthings backend for all classes. This allows getting upfront info about number of records, and some actual records, to display on the main view that shows all classes and their records.ShaclVueStarter, theselectTypeis only called once on app startup, using theThingclass as the selected type.ShaclVueStarterhas a new computed variable,itemsByClass, which takes all filtered records as input and groups them by class. This reactive ref is provided as the input of records toShaclVueRecordsMiniper class.ShaclVueRecords,ShaclVueRecordsMiniemits an event when the user scrolls to the bottom of the list of records. However,ShaclVueStarterhas a new function that listens for this event and will then fetch the next page of records for that specific class.NodeShapeViewerMinihas the simplistic rendering of a record display name and menu options.The premise of this change is that the 'getInstanceItems' approach to generating the list of displayed records (from graph data) results in bad performance. This is mainly because 'getInstanceItems' is called many times (mainly triggered by a watcher reacting to any/all graph changes), each time regenerating the full list of records. The proposed new approach is based on maintaining a global list of items that is incrementally updated when new nodes are added to or updated in the graph. 'parseTTLandDedup' is the 'ReactiveRdfDataset' class method that receives incoming TTL strings parses it into quads, deduplicates blank nodes, and adds it to the 'N3' store. It already provided an array with all added quads as the return value. A new utility function, 'getUniqueRootNodes', is now used to determine the unique named nodes that are included in the added quads. This allows saying: 'these are the records that were just added or updated' in the graph store. 'parseTTLandDedup' now returns both the added quads and the array of unique added/updated record IRIs, and downstream functionality using it has been updated to access its outputs correctly. A new 'ReactiveRdfDataset' class method 'emitAddedRecords(records)' is also added, which can be called with an array of named node (i.e. record) IRIs and which uses 'dispatchEvent' to emit the new 'recordsChanged' event, for which listeners can be added. 'emitAddedRecords' is now used in multiple places in order to emit records that have just been added/updated (because of this, the previous calls to 'rdfDS.triggerReactivity' become redundant): - In the 'useData' composable, inside 'fetchRdfData' right after 'parseTTLandDedup' returns the list of unique added/updated records. This happens downstream for every call to 'fetchFromService', which is the standard way in which 'shacl-vue' gets backend data in response to user interaction. - In the 'useWizard' composable: here we only call 'emitAddedRecords' if the context is not '_record' because it means there is no open form (which would need to process added quads in its own way); it means the wizard immediately adds all quads to the graph. - In the 'FormEditor' component when the user saved the record, i.e. in the 'saveForm' function. Here it is called specifically when the record is a PID record (i.e. not a blank node). Now, onto the algorithmic change for 'getInstanceItems', which is done in the 'useRecords' composable. As mentioned, we now maintain a global list of items ('recordItemsAll' and 'recordItemsByClass') that is incrementally updated when new nodes are added to or updated in the graph. This composable handles the new process as follows: - adds an event listener to 'rdfDS' for the new 'recordsChanged' event, which calls the new 'enqueueChanges' function - 'enqueueChanges' adds all added/updated records to a queue, and runs the code to process the queue - 'processQueue' will keep on running as long as there are records in the queue, and will process records in batches of 10 by calling the 'updateRecordItem' function per record - 'updateRecordItem' runs all the code that used to be run per item by 'getInstanceItems', and then adds the processed record to the 'recordItemsAll' and 'recordItemsByClass' reactive variables - any further computations on the global lists, such as filtering based on user-typed text, are done via computed refs that depend on the above reactive refs. Important new computed refs include 'filteredRecordItemsAll' and 'filteredRecordItemsByClass' which filters all records and record per class based on search text, as well as 'filteredRecordItemsForClassWithSubclassItems' which filters records per class while also including all records of a class's subclasses, which is required for the existing 'priority_classes'/'include_subclasses' config feature. The main 'ShaclVue' component has been updated to use the adjusted 'useRecords' composable correctly, specifically passing the new filtered computed refs to the 'ShaclVueRecords' component, which has updated props 'filteredRecords' and 'fetchedItemCount' to handle the new composable structure. Also, as part of cleanup several previous computed refs were moved as functions to the 'useShapes' composable: - 'getIdFilteredNodeShapeNames' - 'getNoEditClassList' - 'getFilteredNodeShapeNames' - 'getPriorityFilteredNodeShapeNames' - 'getOrderedNodeShapeNames' - 'getAllClassItems' These are now called on app startup during config processing. Lastly, the 'useWizard' composable has been updated to include a new feature needed by the upcoming kickstarter component. This feature allows a wizard to be shown not specifically for a record, nor specifically for a class, but for all classes. It's goal is to allow the configuration of very generic wizards that would be applicable for all classes. The config spec for it's selection is as follows (with 'AddRecordWizard' being an example wizard name): wizard_editor_selection: _classes: - AddRecordWizard To allow distinction of the applicable class IRI when the associated wizard template is processed, the class IRI is now made part of the wizard data by default in 'handleWizardSave' (accessible as 'class_uri'). Also 'showWizardGroup' and 'setupWizards' functions are updated to handle the new 'wizard_editor_selection' key.New approach to generating/maintaining list of records and newto WIP: New approach to generating/maintaining list of records +ShaclVueStarterShaclVueStarterfeatureThis work is in response to the identified need for kick-starting the user-based entry of domain-specific knowledge into a 'shacl-vue' metadata system, so that a critical mass for continued use of the system is available soon after deploying it for the first time. The new 'ShaclVueStarter' component is designed to encourage users to enter minimal records in a quick, intuitive, and interactive way. It has the following features: 1. It serves as a new variant of the main entrypoint of a 'shacl-vue' deployment. This requires the specification of a Vite-recognizable environment variable, 'VITE_SHACLVUE_VARIANT' that influences whether the application is built with the (default) 'ShaclVue' component or the new 'ShaclVueStarter' component. An example command for building the starter app: VITE_SHACLVUE_VARIANT=starter npm run build:app If the environment variable is not specified, the default application will be built. 2. Instead of making only a single class selectable at a time, 'ShaclVueStarter' shows all record types (aka classes), and many records per class. The user can scroll down the main view through all classes, and relevant records can be scrolled within each class 'card'. The left-hand-side pane now shows the list of classes with added checkboxes, which allows including/exluding classes from being displayed in the main view. 3. A 'ShaclVueStarter' deployment uses the new '_classes' option of the 'wizard_selection' configuration to specify a wizard that will be shown for all classes. This allows the use of a generic 'add new record' wizard that only asks for a display name and description, with example config: AddRecordWizard: name: Add New Record Wizard tooltip: Add a new record icon: mdi-plus-circle-outline description: Add the display name and description and then hit *Save* inputs: - prop: name name: Display name description: The display name of the new record type: text placeholder: 'My record title' required: true - prop: description name: Description description: The description of the new record type: text-paragraph placeholder: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod...' template: content:add-record 4. Text search functionality provides the same UX as before, however the search now happens across all records, i.e. not only on a single class-level. 5. Unnecessary detail and functionality from the default 'ShaclVue' application are not available in the starter application. This mainly means the record viewer is minimalistic, containing just the display name and a mini menu button with options to edit the record (which will open the established form) and view the record RDF. New/updated functionality to support all of the above: - New 'ShaclVueStarter', 'ShaclVueRecordsMini', and 'NodeShapeViewerMini' components - 'App.vue' now dynamically loads the main entrypoint components and uses 'component :is=' to render the component that is selected based on the 'VITE_SHACLVUE_VARIANT' value - 'ShaclVueStarter' uses a new 'getFirstPages()' function during app startup in order to fetch the first page from the dumpthings backend for all classes. This allows getting upfront info about number of records, and some actual records, to display on the main view that shows all classes and their records. - In 'ShaclVueStarter', the 'selectType' is only called once on app startup, using the 'Thing' class as the selected type. - 'ShaclVueStarter' has a new computed variable, 'itemsByClass', which takes all filtered records as input and groups them by class. This reactive ref is provided as the input of records to 'ShaclVueRecordsMini' per class. - As with 'ShaclVueRecords', 'ShaclVueRecordsMini' emits an event when the user scrolls to the bottom of the list of records. However, 'ShaclVueStarter' has a new function that listens for this event and will then fetch the next page of records for that specific class. - 'NodeShapeViewerMini' has the simplistic rendering of a record display name and menu options.WIP: New approach to generating/maintaining list of records +to New approach to generating/maintaining list of records +ShaclVueStarterfeatureShaclVueStarterfeature