Skip to content

Develop#311

Draft
namedgraph wants to merge 27 commits into
masterfrom
develop
Draft

Develop#311
namedgraph wants to merge 27 commits into
masterfrom
develop

Conversation

@namedgraph
Copy link
Copy Markdown
Member

No description provided.

namedgraph and others added 27 commits June 4, 2026 22:23
* Core SNAPSHOT bump

Jena version bump to 6.0.0

* POM update

* Tomcat base image bump

* JUnit bumped to v5

* Add mockito-junit-jupiter dependency

Required by ProxyRequestFilterTest after the JUnit 4 -> 5 migration:
@ExtendWith(MockitoExtension.class) lives in mockito-junit-jupiter,
not mockito-core.

* Bump docker-compose image versions

- nginx 1.23.3 -> 1.31.1
- atomgraph/fuseki 4.7.0 -> 6.1.0 (matches Jena 6 upgrade)
- varnish 7.3.0 -> 7.7.3

* CI: dump container logs on failure

* DEBUG: trace entrypoint with set -x (revert before merge)

* CI: dump Tomcat logs from linkeddatahub container on failure

* Servlet API bump

* Jena bump to 6.1.0

* CI: install Java 21 for Jena 6.1.0 CLI tools

Jena 6.1.0 binaries are compiled for Java 21; the runner default is
Java 17 which produced UnsupportedClassVersionError (class file 65.0
vs 61.0) on every turtle/riot/sparql invocation in the HTTP tests.

* Dependency bumps
Drops set -x and the stderr-merge that were left in to debug the
startup pipeline; they produced very noisy docker logs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ntrol booleans

- Move ldh:load-constructed-doc / ldh:set-constructed-doc from the
  shared imports/default.xsl to client/functions.xsl; they use
  ixsl:updating and are only called from client-side promise chains,
  so Saxon-HE was warning about the unlicensed extension on every
  server start.
- Add bs2:FormControl templates for xsd:boolean literals and for the
  constructor's blank-node boolean placeholder (rdf:type xsd:boolean).
- Restrict the lapp:Application settings form to dct:title /
  dct:description; render the remaining app properties + rdf:type as
  hidden inputs so PATCH preserves them. Suppress the add-property
  selector for app settings.
- Expose the active application URI as LinkedDataHub.application
  (set from the Link header) and read it back via lapp:application(),
  replacing the active-pane dataset lookup.
- Dedupe constructor-template properties by predicate URI when
  merging into the resource form so multiple matching spin:constructors
  don't produce duplicate placeholders.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Follow-up to 1c47f09 which only captured the imports/default.xsl
half of the change.

- Add ldh:load-constructed-doc / ldh:set-constructed-doc to
  client/functions.xsl (the moved-to home for the CSR-only helpers
  previously living in imports/default.xsl).
- Switch lapp:application() from the active-pane dataset lookup to
  LinkedDataHub.application on the window object, populated in
  client.xsl from the Link header on RDF document responses.
- Restrict the lapp:Application settings form to dct:title /
  dct:description; render the remaining app properties + rdf:type as
  hidden inputs so PATCH preserves them; suppress the add-property
  selector for app settings.
- Dedupe constructor-template properties by predicate URI when
  merging into the resource form so multiple matching spin:constructors
  don't produce duplicate placeholders.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Modal flows build their $context map before the document is fetched,
so they couldn't supply the existing per-resource $required xs:boolean.
Promote the rdf:RDF bs2:Form template's $required to a
function(element()) as xs:boolean predicate that gets evaluated per
child and rebound as the resource-level boolean tunnel. Default is an
always-false predicate so callers opt in to suppression.

ldh:render-form reads $context('required') and tunnels it; btn-edit
and btn-app-settings populate it (type-based and always-true
respectively); ldh:render-add-modal-form and
ldh:modal-form-submit-violation pass the dh:Container/dh:Item rule
explicitly. Resource-level template stays xs:boolean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Convert modal-form metadata fetches to async load/set pairs

The five modal/typeahead form rendering paths each fetched
type-metadata, property-metadata, constraints, and object-metadata
synchronously via document() inside their terminal render functions,
blocking the UI thread on 3-4 sequential round-trips per render.

Promote each fetch to an async load/set pair invoked as steps in the
existing ixsl:promise chains:
- ldh:load-type-metadata / ldh:set-type-metadata (set-type-metadata
  stripped of its sync work, now just extracts response body)
- ldh:load-constraints / ldh:set-constraints (new pair)
- Reuse the existing ldh:load-property-metadata and
  ldh:load-object-metadata in client/block.xsl, extended to accept
  pre-computed URIs from context (backward-compatible)

Each of the five chains (btn-edit, btn-app-settings, add-constructor,
typeahead-row-form, row-form-submit-violation) is extended with the
new load/set steps before its terminal render function. The render
functions are correspondingly stripped of sync work and now just
read metadata from context.

ldh:modal-form-submit-violation was sync; converted to start a
promise chain and terminate in a new ldh:render-modal-form-violation.

To uniformly identify the resource being edited across all three
modal flows in the submit-violation re-render path, the Container/Item
creation modal now also carries @about on its wrapper div (the new
resource URL), matching btn-edit and btn-app-settings. The submit
handlers read $block/@about directly without a fallback.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Sync modal @about and slug UI across Container/Item violation re-render

Two small follow-ups to the modal-form refactor so the
Container/Item creation modal renders identically before and after a
constraint-violation re-render:

- subject-slug onkeyup handler now also keeps the modal-constructor
  div's @about attribute in sync with the new URI (alongside the
  existing 'su' input value and form @action sync), so the submit
  handler's $block/@about discriminator stays correct after the user
  edits the slug.

- bs2:FormControl slug-style template (imports/default.xsl) now matches
  Container/Item resources by either @Rdf:nodeID (initial SPIN
  construction: blank node) or @Rdf:about (violation response: carries
  the submitted URI). The same body works for both because $action
  carries the resource URL in either case; without this the violation
  re-render fell through to the generic full-URI control.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Run modal-form metadata load/set pairs in parallel via ixsl:all

The async load/set pair conversion in 3ba3dc6 made each metadata
fetch a self-contained step but left them threaded sequentially.
Independent fetches (shapes, constructors, type-metadata,
property-metadata, constraints, object-metadata) read disjoint context
keys, so they can fan out via ixsl:all and converge through a single
merge step. New helper ldh:fire-load-set-parallel#2 in functions.xsl
encapsulates the pattern; new ldh:reset-cursor#0 + ixsl:finally replace
duplicated end-of-chain cursor cleanup.

Refactored sites:
- form.xsl:1415 (typeahead-row-form): 21 hops -> 5, two parallel
  batches around set-typeahead-form-resource as SHACL+SPIN merge barrier
- modal.xsl:820 (add-constructor):    18 hops -> 5
- modal.xsl:1103 (app-settings):      21 hops -> 6, type-metadata pair
  uses an identity load-fn to preserve the GET request already baked
  by load-edited-resource

Wall-clock per flow: ~4-6 sequential round-trips -> ~2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Run row/edit metadata load/set pairs in parallel via ixsl:all

Mirrors the modal-form refactor from 2443668 across the remaining
form chains: btn-edit row-form, row-form constraint-violation re-render,
and the two parallel modal chains (btn-edit + btn-app-settings, and
modal-form violation re-render). The serial then-chain is replaced with
ldh:fire-load-set-parallel over the load/request/response/set tuples;
cursor reset moves into ixsl:finally so it runs on both success and
failure paths.

Adds ldh:fetch-and-load-edited-resource as the shared seed for chains
whose first hop is the edited-resource GET; downstream parallel pairs
pass an identity load-fn for type-metadata because the seed already
baked the GET-style type-metadata-request into context.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Drop FormPreSubmit @name strip on empty RDF/POST inputs

The template removed @name='ol'/'ou'/'ob' from inputs whose value was
empty at submit time, but it mutated the live DOM. When a submit failed
constraint validation and the form was re-rendered, the @name attributes
stayed stripped; a follow-up submit with newly filled values silently
dropped those inputs because parse-rdf-post filters by @name. Net effect:
after any first-submit validation error, the next submit produced an
empty <rdf:RDF/> request, the server accepted it, and the row-form
success handler crashed in $new-block (required exactly-one, got zero).

ldh:parse-rdf-post already filters empty non-'su' values inline via
$value-inputs[@name = 'su' or not(ixsl:get(., 'value') = '')], so this
template was redundant on top of being destructive.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Mark admin subdomain link as external

The admin subdomain link in the user dropdown opens in a new tab; tag it
with class="external" so it picks up the same affordance (icon, styling)
as other external links.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The bs2:FormControl/TypeControl/PropertyControl-mode templates that hid
non-title/description properties of lapp:Application instances were
firing whenever an Application was rendered as a form, including the
generic Create-button constructor flow where the user needs every
editable property exposed.

Introduce ldh:AppSettingsForm mode (peer to ldh:DocumentForm) for the
btn-app-settings render path; the mode itself is the discriminator, so
the suppression / type-hidden / no-PropertyControl behaviour only
applies when the form is entered through that flow. Refactor
bs2:FormControl into a dual match+name template with $body /
$type-hidden / $show-property-control params (mirroring bs2:Form's
existing match+name shape) so ldh:AppSettingsForm can reuse the
fieldset shell with the right overrides while letting the default body
preserve the merged-properties iteration, constraint-aware sort, and
violations/constructor/type-constraints/type-shapes with-params that
per-property templates need. Thread render-fn through the
modal-form-submit-violation chain so settings-flow PATCH violations
re-render in ldh:AppSettingsForm mode too.

Anchor the shell's @Rdf:about / @Rdf:nodeID dispatch and the
AppSettingsForm suppression template's value-bearing children to
bs2:FormControl mode explicitly rather than mode="#current", since
those leaf renderers live only in bs2:FormControl and the named-template
entry path means #current can now be a wrapper mode.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes the bs2:TypeControl override that hid the type select for
ldh:View blocks, so the rdf:type control behaves the same way as for
generic resources.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When a new instance form is submitted with no triples (e.g. user
removed rdf:type and left other fields blank), $resources/rdf:RDF/* is
empty, so applying bs2:Row returns no element and the cardinality=1
assertion on $new-block throws. Guard the success handler so an empty
submitted graph removes the block from the DOM instead.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Captures phased path from deprecated org.apache.jena.ontology to
org.apache.jena.ontapi across Core, Web-Client, and LDH, with a
Phase 0 spike to de-risk import resolution and inference materialization
before the cascade.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Renderers may double-wrap a resource with two nested div.block elements
sharing the same @about; remove the outer wrapper when present so no
empty shell remains after deletion.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Plan doc kept locally only; not part of the repo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…oad-set

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Relative `document('../translations.rdf')` calls in imports/{nfo,sioc,sp}.xsl
and admin/layout.xsl, and `document('translations.rdf')` in document.xsl,
resolved against the SEF root (xsl/client.xsl) under SaxonJS 3, producing
404s on /static/com/atomgraph/linkeddatahub/translations.rdf. Surfaced when
expanding nodes in GraphMode, where ac:label(.) dispatches into these
templates on described resources.

Switch all eight sites to the absolute resolve-uri(..., lapp:origin())
pattern already used elsewhere; declare missing lapp ENTITY + xmlns in
imports/{nfo,sioc,sp}.xsl.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…mous bnodes

- block/view.xsl: introduce a persistent {container-id}-graph-host that holds
  the 3d-force-graph canvas for the lifetime of the view block. ViewModeChoice
  replace-content is skipped in GraphMode so the WebGL context and simulation
  state survive search/filter re-runs; visibility toggles between graph-host
  and container-results. Result count is rendered post-RenderViewMode and
  short-circuits the COUNT request when the full result set fits one page.
- 3d-force-graph.xsl: emit stub nodes for distinct unresolved @Rdf:nodeID
  targets; emit synthetic bnodes (via generate-id) for anonymous nested
  rdf:Description; respect show-stubs on @Rdf:nodeID links; skip node click
  + right-click handlers on bnodes (no dereferenceable URI).
- navigation.xsl: preserve the user's chosen view mode across re-runs of the
  same search container instead of defaulting to ListMode.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bottom-right "Fullscreen" button toggles a .graph-3d-maximized class
on the canvas (position: fixed, viewport-sized) so the browser address
bar stays visible. Esc exits maximize when any maximized canvas is
present; the body keydown template is guarded by a descendant predicate
so it doesn't swallow Esc anywhere else. Both paths resync the
ForceGraph3D renderer width/height to the new container size.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Body-level keydown handler guarded by descendant::div[…modal] so Esc
is a no-op when no modal is open and stays available to other widgets.
priority="1" wins over the graph3d.xsl body keydown if both predicates
ever hold simultaneously — modal dismissal takes precedence.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Admin templates lived in admin/layout.xsl, admin/acl/layout.xsl, and
admin/acl/imports/* (SSR-only). After CSR navigation the base end-user
templates fired instead, so the admin create dropdown showed end-user
classes and admin form/navbar behavior was lost.

Moved overrides into the shared modules, gated by the admin-subdomain
predicate (lapp:origin()) where they apply to all rdf:RDF/rdf:Description
patterns; vocab-typed templates need no guard since their match patterns
are namespace-specific:

  document.xsl   bs2:Row (admin class list), bs2:Create (no NamedIndividual)
  resource.xsl   bs2:FormControl (show-subject default)
  layout.xsl     bs2:NavBarNavList (notifications + agent menu)
  imports/acl.xsl    acl:Authorization label, acl:mode FormControl,
                     lacl:AuthorizationRequest form
  imports/cert.xsl   cert:PublicKey label

Wired imports/{acl,cert}.xsl into both client.xsl and layout.xsl import
lists. Updated static/xsl/admin/layout.xsl to import the base layout
directly. Deleted the now-empty admin SSR sidecars.

foaf is a slash-vocab so ac:document-uri leaves the term URI intact; the
admin bs2:Row override fetches the foaf namespace doc explicitly to hit
the SaxonJS documentPool cache instead of XHR-ing the term URI (which
the browser blocks as cross-origin).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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

Successfully merging this pull request may close these issues.

1 participant