Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow editing saved nodes #54

Open
jsheunis opened this issue Oct 29, 2024 · 3 comments
Open

Allow editing saved nodes #54

jsheunis opened this issue Oct 29, 2024 · 3 comments

Comments

@jsheunis
Copy link
Collaborator

From https://hub.datalad.org/datalink/tools/issues/9

shacl-vue works with graph data using the rdf-ext library, by saving some quads to an rdf.dataset() (import rdf from 'rdf-ext'), after loading them from a ttl file with pre-existing rdf data. shacl-vue also works with shacl shapes (loaded from a ttl file) from which it can autogenerate forms. The forms make use of all the property shapes for any given node shape in order to know which form fields there should be and what type of data they should allow a user to enter, including how these fields should be validated. There is an internal representation of the data entered into a form: it is basically an object with any particular node shape uri (i.e. a triple subject) as a key and a javascript object as the value, which in turn has the triple predicates as keys and the triple objects as values. If a form is saved, a function takes this internal representation and converts it to quads that are added to the same rdf.dataset.

The user should more or less experience the following:

  • open the application in the browser
  • see and browse through an overview of the existing linked data
  • navigate to a specific node (a.k.a. data object) and see its properties
  • have an option to select a node for further annotation / editing, and saving the edits
  • have an option to add a new node, by entering all necessary data in a form (generated from the relevant shacl shapes)

I am currently thinking about how to design the different aspects of the data store. There is:

  • the rdf.dataset(), which is more or less an in-browser-in-memory quad store, for the existing data and for any data saved from a form, and
  • the internal javascript object-based representation for data being entered into a form

I am not sure if the internal representation is a good way to do it, and whether there are existing alternatives for such a use case. I am also not sure how to approach the step of editing an existing node. Since a node will also be edited in a form generated from relevant shacl shapes, I could take the relevant quads from the dataset, convert them into the internal representation for a given form for editing, then edit, and then save it back to the dataset as quads when the editing process is completed. But this could be an inefficient way of doing it, perhaps there are known and widely used alternatives? Also, when saving the "edited" quads back to the dataset, these will be new nodes and the equivalent existing nodes will remain unchanged, which means older versions of the data that remain in the dataset might cause conflicts or confusion.

@jsheunis
Copy link
Collaborator Author

During my search for a better understanding of and possible solution to this challenge, I found https://github.com/rubensworks/rdf-object.js. This can import quads from an rdf.dataset() and represent "Resources" as javascript objects with properties (translated from subjects with predicates and objects), e.g. get a subject's label value from myResource.properties.label. I haven't done enough testing yet to say for sure, but looks like it can possibly be an alternative to the current so-called internal representation. It seems like what I built was more or less a stupid/insufficient version of rdf-object. More investigation underway...

@jsheunis
Copy link
Collaborator Author

jsheunis commented Nov 6, 2024

Trying to implement rdf-object into shacl-vue has led me down a rabbit hole of polyfill issues. So far, the best and most similar description of the problem I found was: nodejs/readable-stream#539 and davidmyersdev/vite-plugin-node-polyfills#106. This seems to be an incompatibility between vite-based polyfills and the readable-stream library, mainly resulting in the error Uncaught (in promise) TypeError: process.nextTick is not a function. There is a possible solution (described as "hacky") at nodejs/readable-stream#543. I will investigate this further.

UPDATE:

After a lot of digging, i got it to work. Or at least, the nextTick error is not happening anymore. I followed these steps:

  • removed the package-lock.json file and removed all unnecessary packages (that I toyed with previously but that didn't solve the issue) from package.json
  • removed node_modules from the project
  • reinstall the package in a clean node environment, with package.json being:
{
  "name": "shacl-vue",
  "version": "0.0.1",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "docs:dev": "vitepress dev docs",
    "docs:build": "vitepress build docs",
    "docs:preview": "vitepress preview docs"
  },
  "dependencies": {
    "@mdi/font": "7.0.96",
    "@rdfjs/dataset": "^2.0.2",
    "@rdfjs/fetch-lite": "^3.2.3",
    "@rdfjs/formats-common": "^3.1.0",
    "@rdfjs/parser-n3": "^2.0.2",
    "buffer": "^6.0.3",
    "rdf-ext": "^2.5.1",
    "roboto-fontface": "*",
    "stream-browserify": "^3.0.0",
    "util": "^0.12.5",
    "uuid": "^10.0.0",
    "vue": "^3.4.0",
    "vuetify": "^3.5.0"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^5.0.4",
    "readable-stream": "github:WasabiThumb/readable-stream#bug/vite-esm",
    "sass": "^1.71.1",
    "unplugin-fonts": "^1.1.1",
    "unplugin-vue-components": "^0.26.0",
    "vite": "^5.1.5",
    "vite-plugin-node-polyfills": "^0.22.0",
    "vite-plugin-vuetify": "^2.0.3",
    "vitepress": "^1.3.4"
  }
}
  • update my vite.config.mjs file to use polyfills and alias to the correct absolute file:
// Plugins
import Components from 'unplugin-vue-components/vite'
import Vue from '@vitejs/plugin-vue'
import Vuetify, { transformAssetUrls } from 'vite-plugin-vuetify'
import ViteFonts from 'unplugin-fonts/vite'

// Utilities
import { defineConfig } from 'vite'
import { fileURLToPath, URL } from 'node:url'

// Polyfill stuff
import { nodePolyfills } from 'vite-plugin-node-polyfills'
import path from 'path';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    Vue({
      template: { transformAssetUrls }
    }),
    // https://github.com/vuetifyjs/vuetify-loader/tree/master/packages/vite-plugin#readme
    Vuetify(),
    Components(),
    ViteFonts({
      google: {
        families: [{
          name: 'Roboto',
          styles: 'wght@100;300;400;500;700;900',
        }],
      },
    }),
    nodePolyfills(),
  ],
  define: {
    'process.env': {}, 
  },
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url)),
      'readable-stream': path.resolve(__dirname, 'node_modules/readable-stream'),
    },
    extensions: [
      '.js',
      '.json',
      '.jsx',
      '.mjs',
      '.ts',
      '.tsx',
      '.vue',
    ],
  },
  optimizeDeps: {
    include: ['rdf-object', 'readable-stream'],
  },
  build: {
    rollupOptions: {
      plugins: [
        nodePolyfills(),
      ]
    }
  },
  server: {
    port: 3000,
    mimeTypes: {
      '.vue': 'application/javascript',
    },
  },
  base: '/shacl-vue/',
})
  • run npm run dev

no issues!

@jsheunis
Copy link
Collaborator Author

Update: this investigation is still ongoing. The current status is that rdf-object would need to be understood thoroughly to see exactly how and where it would fit into the load triples -> edit triples -> save triples pipeline. While working on this, I detoured a bit to rdf-object's dependents on github: https://github.com/rubensworks/rdf-object.js/network/dependents, which led me to projects that have very similar aims as shacl-vue:

There are probably others. shacl-form seems like it has some traction. One neat feature of theirs is to dynamically populate a dropdown list from an online ontology/vocabulary, see https://github.com/ULB-Darmstadt/shacl-form?tab=readme-ov-file#providing-additional-data-to-the-shapes-graph. This is useful for when a form field should require a user to select a term from a controlled vocabulary of sorts, e.g. a diagnosis from a preselected diagnosis vocab. In their demonstration of this feature, they use a list from https://w3id.org/nfdi4ing/metadata4ing, which could prove to be useful since it aligns with higher-level interoperability goals of metadata at a national level.

I created this issue to find out more about shacl-form: ULB-Darmstadt/shacl-form#28

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant