Skip to content

About

Browser-only web app for CRUD on RDF data over any SPARQL endpoint. Forms, validation and widgets are generated from SHACL/DASH shapes.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

51 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RDF Data Manager

A web application for create, read, update and delete (CRUD) operations on RDF data behind a SPARQL endpoint. Its whole user interface is driven by a SHACL / DASH configuration that is either stored in the same endpoint as the data or loaded from an external source.

Licensed under the MIT License.

Status

The first target is the metadata of the Bane NOR Digital Infrastructure Model (DIM): the CSV datasets and key figures that the dim-etl-dataset-generation pipeline reads from the Fuseki /metadata dataset.

Running the app

Try it without an endpoint: the feature tour on GitHub Pages runs a small railway network in a SPARQL store inside your browser, with shapes that use every editor, widget and SHACL feature the app supports (what to look at). ?demo=dim runs the DIM example and ?demo=geo-time a minimal map and time example.

The app is a static TypeScript/React site with no backend: the browser talks to the SPARQL endpoint directly, so the endpoint must allow CORS from the app's origin (Fuseki does by default).

npm install
npm run dev        # http://localhost:5173

Other ways to run it (details in docs/CONFIG.md):

npx rdf-data-manager --port 8080 --config ./config.json          # the npm package serves the built app
docker run -p 8080:8080 -e RDM_DATASET=http://host.docker.internal:3030/metadata/ ghcr.io/matdata-eu/rdf-data-manager
docker compose up --build                                       # the app next to a Fuseki, for a local trial

Every push to main deploys to GitHub Pages. Publishing a GitHub release with a vX.Y.Z tag publishes the npm packages and the container image at that version.

Open Settings and enter the endpoint (for Fuseki, the dataset URL fills in the query and update URLs) and where the shapes come from: a named graph in the endpoint, a Turtle URL or a local file. For the DIM metadata the shapes graph is https://data.banenor.no/data/_shapes_metadata. Settings are kept in the browser. They can also be passed in the URL, e.g. ?dataset=http://localhost:3030/metadata/&shapesGraph=https://…, or served as a config.json next to index.html ("locked": true hides Settings).

The look follows the MatData design system: Barlow and JetBrains Mono (bundled, so no outside network is needed), and light and dark themes. All colours, fonts, spacing and radii are CSS variables in src/theme.css, so another organisation can restyle the app by replacing that one file.

If the endpoint does not send CORS headers, run the dev server with RDM_PROXY_TARGET=http://localhost:8030 npm run dev and use http://localhost:5173/proxy/jena-fuseki/metadata/ as the dataset URL.

What the app does:

  • Lists the instances of every class the shapes describe, with counts and a filter.
  • Creates, edits and deletes resources with forms built from the shapes, including nested nodes such as a table's columns, which are saved together with their parent.
  • Validates the would-be stored data with the shapes before every save (in the browser, with shacl-engine). Violations block the save unless you choose "Save anyway"; warnings are shown after saving.
  • Refuses to save over someone else's edit: a resource that changed since it was opened must be reloaded first, and creating an IRI that appeared in the meantime fails.
  • Writes only the triples the form manages, as a minimal DELETE DATA / INSERT DATA update, so properties outside the shapes are left alone. Before writing, it shows the changes in plain words (what is removed, what is added) for a last look.
  • Checks all stored data of a class, or of every class, against the shapes and lists each problem with a link to the resource ("Check" on a class page, "Check all data" in the sidebar).
  • Edits every translation of a class in one grid, with a filter for missing languages; each row is saved through the same checks as the form.
  • Searches across all classes from the top bar, and shows on every resource what else refers to it ("Used by").
  • Exports a class as Turtle (all triples) or CSV (one row per resource), and imports Turtle after checking it against the shapes, replacing resources that already exist.
  • Shows the interface in Norwegian (Bokmål; Nynorsk falls back to it) when the language is nb or nn; other languages show English until a catalogue is added.
  • Previews the result of a SPARQL query a value points at (rdm:queryText, for the DIM managed queries), and offers dash:AutoCompleteEditor for classes with too many instances for a select.

Packages

The repository is an npm workspace (docs/ARCHITECTURE.md):

Package What npm
packages/core Shapes model, form state, diff and SPARQL Update, SPARQL client, SHACL validation. Plain TypeScript, no UI @rdf-data-manager/core
packages/react NodeForm and the widget registry; forms for any React app (docs/WIDGETS.md) @rdf-data-manager/react
packages/app The app: router, settings, theme, config.json, runtime widget loading rdf-data-manager
packages/widget-map Map editor for GeoSPARQL geometries (Leaflet), loaded on demand @rdf-data-manager/widget-map
packages/widget-time Calendar and clock editors for XSD date/time types and OWL-Time nodes @rdf-data-manager/widget-time
packages/store-memory An in-memory SPARQL store (Oxigraph, WebAssembly) behind the same client interface, for tests and the demo @rdf-data-manager/store-memory
packages/shapes-dim The Bane NOR DIM shapes, sample data, invalid test cases and endpoint tools private

Shapes

File Content
packages/shapes-dim/shapes/dim-metadata.shapes.ttl SHACL/DASH shapes for dcat:Dataset, bno:KeyFigure, bno:KeyFigureTable, bno:KeyFigureSection, csvw:Column and (read-only) dcat:Distribution
packages/shapes-dim/examples/dim-metadata.sample.ttl Sample metadata that conforms to the shapes
packages/shapes-dim/tests/data/invalid/ One file per rule the shapes must catch

Datasets, key figures and key figure tables need exactly one title and one description in each of English (en), Bokmål (nb) and Nynorsk (nn). Key figure sections need an English title and may add nb and nn; a legacy @no title gives a warning.

The shapes are meant to live in the named graph <https://data.banenor.no/data/_shapes_metadata> of /metadata, next to the data.

npm test                                                              # shapes vs. sample and invalid cases, form logic, form components
npm run lint                                                          # Standard style with TypeScript (npm run lint:fix repairs most findings)
FUSEKI_DATASET=http://localhost:3030/metadata/ npx playwright test    # browser smoke test, from packages/app, against a Fuseki
npm run validate-endpoint -- http://localhost:8030/jena-fuseki/metadata/   # reads shape targets only; --full, --no-distributions, --timeout, --json
npm run load-shapes -- http://localhost:8030/jena-fuseki/metadata/         # PUT the shapes into their named graph

How the shapes drive the UI

  • Every class targeted by a node shape with an rdfs:label becomes a menu entry, in rdm:order. Shapes targeting the same class are merged.
  • Property shapes give the form fields: sh:group and sh:order place them, dash:editor / dash:viewer choose the widget (any registered widget, built-in or added through config.json; see docs/WIDGETS.md), dash:readOnly disables editing.
  • Nested resources (a table's columns) use dash:DetailsEditor with sh:node.
  • New IRIs are dash:uriStart + a local name the user types, checked against rdm:localNamePattern.

SHACL and DASH support

Construct Effect in the form
sh:targetClass, rdfs:label on the node shape A menu entry; shapes targeting the same class are merged
sh:node on a node shape Inherits the parent's property shapes
sh:property with a predicate sh:path A field; complex paths are validated only
sh:datatype, sh:class, sh:nodeKind, sh:in, sh:languageIn, sh:minCount, sh:maxCount, sh:pattern, sh:defaultValue Choose the editor, type new literals, offer instances or options, mark required fields
sh:or / sh:xone on a property shape One field: the classes of every branch are offered together, the first branch's datatype types new literals; each branch is still validated
sh:closed, sh:ignoredProperties Triples outside the shape are listed under "Other properties" and flagged; saving never touches them
sh:targetSubjectsOf, sh:targetObjectsOf Validated, but not a menu entry: the menu and the lists are by class
dash:editor, dash:viewer, dash:readOnly, dash:hidden, dash:singleLine, dash:uriStart Widget choice, read-only and hidden fields, IRI minting
Everything else in SHACL Core Validated by shacl-engine on save, import and "Check"

Annotations in the rdm: namespace (https://matdata.eu/ns/rdf-data-manager#, defined in vocab/rdf-data-manager.ttl):

Property Used on Meaning
rdm:order node shape Menu order
rdm:hideFromMenu node shape Do not list the target class in the menu
rdm:localNamePattern node shape Regex for the local name of new instances
rdm:localNameDescription node shape Help text for that local name
rdm:localNameProperty node shape Property whose value completes the IRI of a new nested node
rdm:defaultValue property shape Value pre-filled on create (rdm:today = current date)
rdm:updateOnSave property shape Set the value to today whenever the resource is saved
rdm:orderBy, rdm:orderDescending property / node shape Sort order of multiple values
rdm:collapsed property shape Start the field collapsed; without it, fields with more than 5 values start collapsed
rdm:pageSize property shape Number of values shown before "Show more" (default 10)
rdm:languages property shape Language tags the form offers for a text field
rdm:queryText property shape SPARQL property path from a value to the text of a query, which the form offers to run and preview

Contributing

See CONTRIBUTING.md for how to run, test and submit changes, and docs/adr/ for the decisions behind the design.

About

Browser-only web app for CRUD on RDF data over any SPARQL endpoint. Forms, validation and widgets are generated from SHACL/DASH shapes.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages