Skip to content

feat: central frontend store (RDFA-483)#128

Open
tarn-soptim wants to merge 25 commits into
mainfrom
chore/RDFA-483-central-frontend-store
Open

feat: central frontend store (RDFA-483)#128
tarn-soptim wants to merge 25 commits into
mainfrom
chore/RDFA-483-central-frontend-store

Conversation

@tarn-soptim

Copy link
Copy Markdown
Collaborator

Description

Test Checklist

General Behavior

  • Components reload automatically when data changes
  • Editing features are disabled in readonly datasets
  • Dialogs pre-select current dataset/graph
  • Required fields are validated in dialogs
  • Discarding unsaved changes opens a discard cancel confirm dialog

Global MenuBar

  • Navigate to home page works
  • File menu:
    • Import → Graph/SHACL works
    • Export → Graph/SHACL works
    • Share Snapshot works
    • Delete → Dataset/Graph works
  • Edit menu:
    • New → Class works
    • New → Package works
    • Edit/View → Create/Edit/View Ontology works
    • Edit/View → Package works
    • Undo/Redo (Ctrl+Z / Ctrl+Y) works
    • Enable/Disable editing works
    • Manage/View namespaces works
    • Delete → Ontology/Package works
  • View menu:
    • Changelog opens and shows current graph
    • Compare Graphs opens
    • Full SHACL works
  • Help menu:
    • Help link works
    • Submit Feedback link works
    • About navigation works

Welcome Page

  • Navigation to Editor works
  • Tips are displayed
  • Security and data information displayed
  • Copyright and version information displayed

Editor - MenuBar

  • Search function works with all filters (All Datasets, Current Dataset, Current Graph, Current Package)
  • Search finds classes, attributes, associations, packages
  • "Enable Editing" button appears for readonly datasets

Editor - Navigation

  • Hierarchical display (Datasets → Graphs → Packages) works
  • Selection is highlighted
  • Selecting a class does not change dataset/graph/package selection
  • Class selection stays open/highlighted when switching dataset/graph/package
  • Datasets and graphs are collapsible
  • Single click selects; double click or chevron toggles expand/collapse
  • State persists on reload (non-browser)
  • Context menus act on the dataset/graph/package they were opened on
  • Hover labels show prefixes when configured
  • Dataset context menu:
    • Import graph works (disabled in readonly datasets)
    • Share Snapshot works
    • Enable/Disable editing works
    • Manage/View namespaces works
    • Delete dataset works
  • Graph context menu:
    • New package works (disabled in readonly datasets)
    • Undo/Redo works (only enabled when available)
    • Create Ontology
    • Edit Ontology (View Ontology in readonly)
    • Delete Ontology
    • Changelog navigation works
    • Compare dialog works
    • SHACL import/export/full view works (import disabled in readonly datasets)
    • Export graph works
    • Delete graph works (disabled in readonly datasets)
  • Package context menu:
    • Create new class works (disabled in readonly datasets)
    • View/Edit package works
    • Copy URL works
    • Delete package works (disabled for external/default packages and readonly datasets)
  • Class context menu:
    • Open class (editor) works
    • SHACL works
    • Delete class works (disabled in readonly datasets)

Editor - Package View

  • Class diagram displays correctly
  • Moving nodes works and layout changes persist after reload
  • Loading animation shows while loading
  • Info cards show when no package or no classes available
  • Drag and zoom diagram works
  • "Reset View" button works
  • "Filter View" works
  • "Reset Layout" button resets diagram to auto-generated layout
  • Click on class opens class editor

Editor - Class Editor

  • Display and edit class properties: Label, Namespace, Package, Derived from, Abstract, Stereotypes, Attributes, Associations, Comment
  • Delete class works
  • Save changes works
  • Discard changes works
  • Attribute Editor works
  • Association Editor works
  • attribute/association SHACL View works
  • Class SHACL View works

Prefixes Page

  • View, add, remove and edit namespaces works

Changelog Page

  • Select graph and display write operations works
  • Operations shown in reverse chronological order
  • Detailed view of changed triples works
  • Restoring graph to a version works

Compare Page

  • Compare two graphs works

@tarn-soptim
tarn-soptim force-pushed the chore/RDFA-483-central-frontend-store branch from b01166d to 092ef5a Compare May 28, 2026 10:55
@spah-soptim spah-soptim changed the title chore: rdfa 483 central frontend store chore: central frontend store (RDFA-483) Jun 2, 2026
@tarn-soptim
tarn-soptim force-pushed the chore/RDFA-483-central-frontend-store branch from 092ef5a to acf3557 Compare June 11, 2026 14:06
Comment thread frontend/src/lib/stores/GraphStore.ts Fixed
tarn-soptim and others added 11 commits June 24, 2026 10:37
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Signed-off-by: Finn Tarnowsky <finn.tarnowsky@soptim.de>
Commit the spec as a contract and generate the client offline from it
@tarn-soptim
tarn-soptim force-pushed the chore/RDFA-483-central-frontend-store branch 2 times, most recently from 8c9e468 to 9105d54 Compare June 24, 2026 13:14
@tarn-soptim
tarn-soptim force-pushed the chore/RDFA-483-central-frontend-store branch from 9105d54 to fdf5b8e Compare June 24, 2026 13:25
@tarn-soptim
tarn-soptim force-pushed the chore/RDFA-483-central-frontend-store branch from fdf5b8e to b1e92a9 Compare June 24, 2026 13:29
…cross builds

Signed-off-by: Jan-Hendrik Spahn <jan-hendrik.spahn@soptim.de>
@spah-soptim
spah-soptim marked this pull request as ready for review June 25, 2026 11:45
@spah-soptim
spah-soptim self-requested a review June 29, 2026 17:53
Comment thread frontend/src/routes/layout/menu-bar/Edit.svelte Outdated
Comment thread frontend/src/routes/changelog/Changes.svelte Outdated
Comment thread frontend/src/routes/+layout.svelte Outdated
Comment thread frontend/src/routes/mainpage/classEditor/classEditor.svelte Outdated
Comment thread frontend/src/lib/api/hey-api.ts Outdated
Comment thread frontend/src/routes/ImportDialog.svelte Outdated
Comment thread frontend/src/routes/Searchbar.svelte Outdated
Comment thread frontend/src/lib/api/backend.js
Comment thread frontend/src/routes/NamespacesDialog.svelte Outdated
@spah-soptim spah-soptim changed the title chore: central frontend store (RDFA-483) feat: central frontend store (RDFA-483) Jul 7, 2026
@spah-soptim spah-soptim added the enhancement New feature or request label Jul 7, 2026
# Conflicts:
#	backend/src/main/java/org/rdfarchitect/api/controller/datasets/diagrams/CrossProfileDiagramIDRESTController.java
#	backend/src/main/java/org/rdfarchitect/api/controller/datasets/graphs/diagrams/CustomDiagramClassRESTController.java
#	backend/src/main/java/org/rdfarchitect/services/diagrams/CustomCustomDiagramService.java
#	backend/src/main/java/org/rdfarchitect/services/update/classes/UpdateClassService.java
#	backend/src/test/java/org/rdfarchitect/services/diagrams/CustomDiagramsServiceTest.java
#	frontend/package-lock.json
#	frontend/src/lib/api/apiDatasetUtils.js
#	frontend/src/lib/api/backend.js
#	frontend/src/lib/rendering/svelteflow/components/SvelteFlowPaneContextMenu.svelte
#	frontend/src/lib/rendering/svelteflow/svelteFlowWrapper.svelte
#	frontend/src/routes/GraphDeleteDialog.svelte
#	frontend/src/routes/ImportDialog.svelte
#	frontend/src/routes/NewClassDialog.svelte
#	frontend/src/routes/NewGraphDialog.svelte
#	frontend/src/routes/delete-relations-dialog/DeleteDependenciesDialog.svelte
#	frontend/src/routes/layout/menu-bar/Edit.svelte
#	frontend/src/routes/mainpage/classEditor/classEditor.svelte
#	frontend/src/routes/mainpage/classEditor/components/associations/save-association-to-backend.js
#	frontend/src/routes/mainpage/classEditor/components/enum-entries/save-enum-entry-to-backend.js
#	frontend/src/routes/mainpage/classEditor/fetch-class-editor-context.js
#	frontend/src/routes/mainpage/packageNavigation/DatasetSection.svelte
#	frontend/src/routes/mainpage/packageNavigation/PackageDeleteDialog.svelte
#	frontend/src/routes/mainpage/packageNavigation/build-nav-object.js
#	frontend/src/routes/mainpage/packageNavigation/custom-diagram-dialogs/CustomDiagramDeleteDialog.svelte
#	frontend/src/routes/mainpage/packageNavigation/custom-diagram-dialogs/RemoveFromDiagramDialog.svelte
#	frontend/src/routes/mainpage/packageNavigation/save-copy-class-to-backend.js
# Conflicts:
#	frontend/src/lib/api/backend.js
#	frontend/src/routes/NewClassDialog.svelte

@spah-soptim spah-soptim left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review done.

Architecture is half-wired: the stores notify subscribers, but the UI still refreshes via forceReloadTrigger and versionControlStore.undo/redo hardcodes which stores to invalidate (misses datatypesStore/diagramStore resulting into stale caches after undo). Not worth fixing in this PR, but worth a follow up.

Comment on lines 403 to 407
function pasteClass(copyAsAbstract, copyAttributes, copyAssociations) {
saveCopyClass(
classStore.saveCopyClass(
editorState.selectedDataset.getValue(),
editorState.selectedGraph.getValue(),
selectedPackageDetails,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The menu-bar/shortcut paste is broken.
pasteClass calls classStore.saveCopyClass(dataset, graph, selectedPackageDetails, copyAsAbstract, ...) with 6 args, but the actual store method is pasteCopiedClasses(datasetName, graphURI, request).
It should call the wrapper in save-copy-class-to-backend.js (which has exactly this 6-arg signature) instead. The svelteflow context-menu paste path is fine.

Comment on lines +216 to 227
const { error, data } = await crossProfileStore.fetchRenderingData(
editorState.selectedDataset.getValue(),
);

const responseText = await res.text();
if (!responseText) {
displayDiagram = false;
} else {
response = JSON.parse(responseText);
renderingFormat = response.format;
displayDiagram = true;
}
} catch (error) {
console.error("Error fetching cross profile diagram data:", error);
if (error || !data) {
displayDiagram = false;
response = null;
renderingFormat = null;
} finally {
isLoading = false;
} else {
renderingFormat = response.format;
displayDiagram = true;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fetchCrossProfileRenderingData destructures { error, data } but never assigns response = data (all the three other fetchers do).

Comment on lines +47 to +48
associationUUIDs.fromUUID,
associationUUIDs.toUUID,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

save-association-to-backend.js:44 / AssociationEditorDialog.svelte:102
new associations get undefined UUIDs.

classStore.addAssociationPair returns an AssociationPairDto ({from: {...}, to: {...}}), but the dialog reads result.associationUUIDs.fromUUID/.toUUID. Only the replace path returns {fromUUID, toUUID}.

const res = await bec.getOntology(
datasetNavEntry.label,
await ontologyStore.loadOntology(datasetNavEntry.id, graphNavEntry.id);
const { data } = await ontologyStore.getOntologyForGraph(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ontology is always undefined.
const { data } = await ontologyStore.getOntologyForGraph(...), but the store returns OntologyDto | null directly, not {data} (OntologyStore.ts:198-204). The {#if ontology} profile-header UI never renders.

Comment on lines +136 to +147
const { error } = versionControlStore.undo(
datasetNavEntry.id,
graphNavEntry.id,
);

if (!error) {
forceReloadTrigger.trigger();
}
}

async function getOntology() {
const res = await bec.getOntology(
datasetNavEntry.label,
function redo() {
const { error } = versionControlStore.redo(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GraphSection.svelte:136,147

missing await on versionControlStore.undo/redo.

{ error } is destructured from a Promise, so error is always undefined and the reload fires unconditionally before the undo round-trip completes.

* Generic loader for a slot in a graph's vocabulary. Caches data per
* (dataset, graph) and per slot, coalesces concurrent fetches.
*/
async function loadSlot<K extends keyof GraphVocabulary>(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Store scaffolding is copy-pasted six times: the {data, fetchedAt, pending, error} slot type, makeKey with the :: separator, prefix-based invalidation, and the describeError→log→toast→return boilerplate.

DatatypesStore.loadSlot already is the generic helper - extracting it (plus a shared AsyncSlot) would remove the duplicated lines per store and make the :: key convention a single point of truth.

Comment on lines +307 to +309
function invalidateAll() {
update(() => ({ graphs: new Map() }));
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The invalidateAll() and invalidateDataset() functions in all six stores have zero callers (except the graphStore.invalidateDataset). Worth a follow-up.

}

// ---------- invalidation ----------
function invalidateDataset(datasetName: string) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DiagramStore.invalidateDataset also evicts all graph-diagram lists on dataset-diagram-only mutations. Could be fixed in a follow up. Nothing blocking.

Comment on lines +52 to +54
await loadXsdPrimitives();
await datatypesStore.loadForGraph(datasetName, graphUri);
const xsd = await getXSDPrimitives();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It awaits two independent fetches sequentially and redundantly re-reads getXSDPrimitives(). Could be worth a follow-up. Non blocking.

@@ -144,7 +118,7 @@
$effect(async () => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicate readonly-recompute effect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants