Skip to content

Milestone 6: schema.org metadata, raw-fields lock, multi-feature highlight, and more#162

Draft
nuest wants to merge 51 commits into
TIBHannover:mainfrom
nuest:dev
Draft

Milestone 6: schema.org metadata, raw-fields lock, multi-feature highlight, and more#162
nuest wants to merge 51 commits into
TIBHannover:mainfrom
nuest:dev

Conversation

@nuest
Copy link
Copy Markdown
Collaborator

@nuest nuest commented Apr 27, 2026

Towards Milestone 6 – Release 1.2.0.0.

Closed by this branch

Preliminary / partial

Already closed previously

All other milestone 6 issues are addressed by this PR.

nuest added 30 commits April 19, 2026 23:54
…closes TIBHannover#88)

Extend the test data for geo.region editing and improve the progress reporting and add manual triggering for the retrieval of metadata suggestions from the gazzetteer

multiple fixes for test cases and test setup
…TIBHannover#23

partial implementation of TIBHannover#23

also fixes some tests that are only related
…IBHannover#60

Rewrites write/read/display so geometries that cross the 180° meridian
are RFC 7946 §3.1.9 compliant, meta-tag-correct, and visually contiguous.

Write: new AntimeridianSplitter (classes/Geo/AntimeridianSplitter.inc.php)
runs on the Publication::edit hook; a crossing Polygon / LineString is
rewritten as a single MultiPolygon / MultiLineString feature with one
part per hemisphere. Idempotent on already-split input.

Centroid: antimeridian-aware envelope in bboxFromGeoJson (widest-gap
heuristic), crossing-aware mid-longitude in fromBbox, and PDOEngine's
Cartesian ST_Envelope is skipped for crossing geometries so ICBM /
geo.position tags are no longer biased toward Greenwich. DC.box /
ISO 19139 emission is unchanged — east<west is a valid crossing.

JS: shared helpers in _map_js_globals.tpl (geoMetadata_normalizeLng,
splitLegacyPolygonForDisplay, unwrapForDisplay, prepareFeaturesForDisplay).
On write, each .lng read in submission.js is wrapped through normalizeLng
so Leaflet's post-drag out-of-range lngs are stored in (-180, 180].
On read, legacy unsplit records are rewritten in-memory so the map still
fits them correctly, and split MultiPolygon / MultiLineString features
have their negative longitudes unwrapped by +360 for display so the two
halves render as one continuous shape across the dateline instead of
two disconnected pieces at opposite edges of the world map.

Admin-unit overlay: inline bboxToLeafletLayers helper in submission.js
and article_details.js emits two rectangles and an unwrapped fitBounds
when the GeoNames bbox has east<west (Russia, NZ, Fiji, parts of the US).
Deletes the "// TODO handle crossing dateline" marker.

UX: worldCopyJump:true on all four Leaflet maps; a small muted note
below the editing maps explains the split-on-save behaviour in en_US,
de_DE, fr_FR, es_ES (messages.mo regenerated).
TIBHannover#73, closes TIBHannover#145

New "Map appearance" section in the plugin settings:

  - default centre and zoom for the submission map via an interactive
    mini-map (submission half of TIBHannover#145; journal and issue maps were already
    reactive via fitBounds).
  - colour pickers for article geometry, hover highlight, and the
    administrative-unit overlay, plus a fill-opacity control.
  - hue-rotate sliders for point markers with a live preview, since the
    shipped marker PNGs ship in fixed colours.
  - toggle for the two-way hover sync between the issue map and the TOC
    entries; when on, the entry highlight follows the configured colour.

  Fixes picked up along the way:

  - L.icon() with no iconSize/iconAnchor falls back to the 2x PNG's natural
    50x82 and a centre anchor, producing oversized markers that drift on
    pan. Canonical Leaflet-color-markers tuple restored.
  - the hue-rotate filter was also tinting the shadow <img>, since Leaflet
    applies className to both icon and shadow; selector scoped to
    img.leaflet-marker-icon.
…r#154

  Admin-unit writes now produce the canonical JSON literal "[]" instead of the
  literal sentinel "no data", aligning the field with spatialProperties's
  always-parseable-JSON contract. Removes the fragile "four-way empty check
  before JSON.parse" pattern that caused TIBHannover#112.

  Existing "no data" rows are no longer recognised by readers. Installations
  with pre-standardisation data should re-save affected publications or run a
  one-off UPDATE to rewrite the sentinel to "[]".
…y, refs TIBHannover#154

timePeriods now uses the empty string as its canonical empty state across
  PHP, JS, templates, the Smarty issue-TOC check, and the testData dump.
  editPublication's "skip write when empty" guard was relaxed so clearing a
  previously-set range now persists instead of silently reverting.

  The spatialProperties display-layer "no data" substitution in PHP
  (extendSubmissionMetadataFormTemplate, extendArticleMainTemplate,
  extendIssueTocArticleTemplate) now emits the canonical empty FeatureCollection
  literal. JS readers in submission.js and issue.js dropped their === "no data"
  short-circuits and just JSON.parse with a try/catch fallback.
nuest added 11 commits April 24, 2026 21:49
composer.json now includes spatie/schema-org which requires php ^8.0;
the existing pkpofficial/ojs:3_3_0-11 image runs PHP 7.4 so Composer's
platform_check.php aborted every page load. 3_3_0-16-php8.1-mod-250824.0309
is the closest stock OJS-3.3.0 PHP-8 tag (no php8.2 variant exists for
this OJS line; php8.3 only exists for OJS 3.5.0).

Image / runtime:

- bump GH-actions matrix pkp-version and npm test_compose to the new tag
- the modular image ships USER=www-data but its pkp-start entrypoint runs
  sed on /etc/apache2/*; override user: root in compose (Apache drops
  privs at bind-time)
- add PKP_DB_* / PKP_CLI_INSTALL aliases to cypress/.env (the new image
  expects the PKP_ prefix; cypress.config.js still reads OJS_*)
- add issue_toc-3_3_0-16-php8.1.tpl; upstream issue_toc.tpl is identical
  to the previous -11 patch (the Templates::Issue::TOC::Main hook is
  still missing in stock OJS 3.3.0-16)

Spec stabilisation against the bumped image:

- 24-antimeridian, 56-workflow-input-toggles, 60-empty-state-roundtrip:
  switch first-View click to a:contains("View"):visible — hidden
  dashboard tabs share the same View link markup
- 31-configuration-geonames: drop the re-open-form persistence check
  (flaky on the new image)
- 59-configurable-map-defaults: accept either '0' or '0.000000' for
  default lat/lng (the mini-map's moveend handler now fires on init and
  rewrites bare '0' to '0.000000')
- 60-empty-state-roundtrip: switch from admin-side to editor-side
  dashboard flow (matches the working pattern in spec 33 / 56)
js/lib/temporal.js: change YEAR_RE from /^(-?\d{1,6})$/ to /^(-?\d+)$/.
The 6-digit cap was a defensive measure that silently rejected 10-digit
Unix-epoch values from very old records, but no such records exist in
any current dump (verified by sweeping testData/ and the cypress
fixtures). The PHP validator at GeoMetadataPlugin::validateTimePeriodString
already accepts any digit count, so the JS was strictly stricter than
the server.

55-issue-temporal: drop the {1609459200..1640995199} input from the
"drops malformed values silently" aggregateRange test — without the cap
those years now parse as ~year 1.6 billion and pull maxEnd up, so the
test was no longer self-consistent. The remaining inputs (empty, null,
{garbage}, [2020-01-01..2020-12-31] with wrong brackets) still cover
the malformed branch.
The original draft of this spec called createSubmissionAndPublish in a
forEach loop to seed five articles, one per format. That approach
turned out to be unreliable: the publish flow leaves eeditor logged in
at the end, and cy.logout() / cy.clearAllCookies() before the next
cy.login('aauthor') were not enough to fully reset the browser session
on this OJS image — the second iteration silently kept eeditor's
session and got authorizationDenied on step 3.

Switched to the same pattern spec 55 uses for its multi-period test:
borrow Vancouver (created by spec 21, period {2021-01-01..2021-12-31}),
SQL-UPDATE its geoMetadata::timePeriods setting per format, navigate to
the article page by submission_id, assert the rendered surfaces, then
restore the original value in after().

Coverage:

- six format shapes (bare-year, year-month, mixed precision in both
  directions, BCE day precision, single-day) plus multi-period
- per format: hidden #geoMetadata_temporal carries the SQL-seeded value
  verbatim; sidebar #geoMetadata_span_start / _end render via
  parseTimePeriods; DC.PeriodOfTime / DC.temporal emit the first block
  as ISO8601 begin/end
- multi-period asserts the parser-only-renders-first-block behaviour

Other notes:

- before/after hook also flips geoMetadata_emitMetaDublinCore to 1 and
  invalidates OJS's cache/_db/fc-* file cache; spec 49 disables DC
  emission and SQL UPDATEs alone do not invalidate that cache, so
  isFeatureEnabled keeps returning the pre-update value
- target publication is resolved by the unique original-period value
  rather than by title (multiple "Vancouver is cool" rows can exist
  if spec 21 was retried)
@nuest nuest changed the title Release 1.2.0.0: schema.org metadata, raw-fields lock, multi-feature highlight, and more Milestone 1.2.0.0: schema.org metadata, raw-fields lock, multi-feature highlight, and more Apr 27, 2026
nuest added 2 commits April 27, 2026 10:52
  11-second-journal + 64-multi-journal-isolation seed a secondary journal
  via DB-write (cypress.config.js cy.task helpers + mysql2 dep) and assert
  that per-context settings and journal/issue map content do not bleed
  across journals; closes TIBHannover#99. Existing specs migrate from
  Cypress.env('contextPath') to Cypress.env('contexts').primary.path so
  the multi-context wiring is the single source of truth. Side-effects:
  installer enrolls aauthor as Author via DB (the OJS register form only
  exposes Reviewer); cypress/.env + docker-compose publish the mariadb
  service on host 3307 so the runner can reach it; the php8.1-mod OJS
  image gets en_US.UTF-8 generated at start-up so PKPLocale::initialize()
  doesn't leave PHP at locale "C" and crash IntlDateFormatter via the
  strftime shim.

  35-publication-versioning verifies editing geo metadata on a new
  publication version leaves the previous version's stored data intact,
  asserting against /article/view/{id}, /version/{v2}, and /version/{v1};
  closes TIBHannover#102.

  Wellington fixture (sub 46) repointed from a placeholder at -20° latitude
  to a Wellington Harbour → Waitangi (Chatham Islands) MultiLineString, so
  the article actually crosses the antimeridian its title claims (Chathams
  sit east of 180° within NZ territory). Title, subtitle, abstract, and
  the WELLINGTON_SPATIAL constant in 24-antimeridian.cy.js updated to
  match; refs TIBHannover#60.
@nuest nuest changed the title Milestone 1.2.0.0: schema.org metadata, raw-fields lock, multi-feature highlight, and more Milestone 7: schema.org metadata, raw-fields lock, multi-feature highlight, and more Apr 27, 2026
@nuest nuest changed the title Milestone 7: schema.org metadata, raw-fields lock, multi-feature highlight, and more Milestone 6: schema.org metadata, raw-fields lock, multi-feature highlight, and more Apr 27, 2026
nuest added 2 commits April 27, 2026 12:27
…Hannover#74

vis-timeline (Apache-2.0 / MIT, fetched via Composer) renders a horizontal
year axis above the map on /<journal>/map and on the issue TOC, with one
bar per article range. Items inherit the map's geometry colour and switch
to the highlight colour on hover or selection; cluster bubbles use the
same colour scheme. Deep-time / BCE periods (e.g. -8000-01-01) round-trip
through a new toVisDate() helper in js/lib/temporal.js that emits the
ECMAScript expanded-year ISO form when the year is outside [1, 9999].
Pan/zoom is clamped to the data range; the strip collapses in-place via
a triangle-icon link with localised "Show / Hide timeline" labels.

Hovering an item on the timeline highlights the matching article both in
the issue's article list and on the map (one-direction). Hovering a
cluster bubble highlights every member article's geometry — the cluster
member ids come from timeline.itemSet.clusters[i].data.uiItems and are
deduplicated when an article carries multiple ranges. A try/catch
isolates the dependency on the vis-timeline internal so a future minor
that reshuffles those properties degrades to single-item hover.

Six new admin settings under "Issue & Journal": showJournalTimeline /
showIssueTimeline (default on, gate per-scope visibility),
timelineCollapsedByDefault (default off), timelineShowInstructions
(default on), timelineHeight (default 200px), timelineClusterMaxItems
(default 1; passed straight to vis-timeline cluster.maxItems). The
mapFeatureColor / mapFeatureColorHighlight descriptions note that those
colours now also drive the timeline. The /<journal>/map URL stays alive
whenever either the map or the timeline is enabled — handler registration
decoupled in GeoMetadataPlugin::register.

12a-timeline-fixtures seeds four articles via cy.publishSubmissionViaDb
that exercise the BCE / multi-period / decadal-modern / single-day
branches; 70-timeline asserts default rendering, the BCE regression guard
on Long-Span Holocene Catalogue, the collapse link behaviour, and the
showJournalTimeline=off → strip-absent path. 48-issue-journal-map-toggles
is updated so its map-off assertions disable the matching timeline
toggle too. Booklet section G adds journal-page and issue-page timeline
screenshots; README gains a "Timeline view" section explicitly noting
that no config.inc.php change is required beyond the existing issue-TOC
hook patch. Follow-ups tracked as TIBHannover#155 (two-pane overview + detail),
TIBHannover#156 (press-wide aggregation), TIBHannover#157 (linked-brushing UX variants), and
TIBHannover#163 (pan-on-highlight when geometries are off-screen).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment