Skip to content

fix: check for a new view version on a view display's "refresh now" - #657

Merged
tkuhn merged 2 commits into
masterfrom
fix/654-refresh-view-version
Aug 28, 2026
Merged

fix: check for a new view version on a view display's "refresh now"#657
tkuhn merged 2 commits into
masterfrom
fix/654-refresh-view-version

Conversation

@tkuhn

@tkuhn tkuhn commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Closes #654.

The problem

"refresh now" on a view display only marked the view's query result as outdated. The view definition was never re-checked, on either of the two paths it can arrive by:

  • View.get(id)'s memo (latestResolvedViews) is only re-resolved once a minute, in the background;
  • a display built from the get-view-displays query holds an exact version (View.get(latestViewIri, false)), which is never re-checked client-side at all.

So a view whose definition had just been superseded kept rendering as the old version until the page's structure happened to be refreshed.

The change

View.refreshLatestVersion(String id) — goes back to the API instead of trusting what is memoized:

  • drops every memoized resolution leading to the shown version, not just the one keyed by it (a built-in view is looked up by the id hard-coded for it, not by the version that id resolves to);
  • forgets the lookups behind them — QueryApiAccess.forgetLatestVersion + ApiCache.clearCache on get-latest-version-of-np, or on get-latest-governed-version for a space-governed view;
  • re-resolves synchronously and re-memoizes.

QueryApiAccess.forgetLatestVersion — drops the up-to-a-minute-old memo in latestVersionMap.

ViewDisplayMenu — "refresh now" calls it. An unchanged view takes the existing in-place rebuild path, untouched. A newer version escalates to resource.forceRefresh(0) plus a page re-render, the same route the page-level "refresh now" takes: the version in use comes from the page's structure, and a new version can change the query, columns, actions and width — more than QueryResult.rebuild can patch, since it reuses the old viewDisplay/queryRef and has no npId to rebuild query params from.

Also folds the twice-duplicated view-id → nanopub-id regex into View.toNanopubId.

Testing

mvn test: 1215 tests, 0 failures. Two new tests in ViewTest — a superseding version is picked up, and memos reaching the view by another id are dropped — against three header-view TriG fixtures (header views are the one display type without a query, so loading one pulls in nothing else).

Not verified end to end: the escalation branch only fires when a view is genuinely superseded, which would mean publishing a new view nanopub.

Left open

A header view still has no "refresh now" at all (queryRef == null hides the entry). Now that the entry also refreshes the definition, a header view does have something to refresh — but that is a menu-visibility change beyond this issue.

🤖 Generated with Claude Code

tkuhn and others added 2 commits August 28, 2026 09:34
"refresh now" only marked the view's query result as outdated, so a view
whose definition had just been superseded kept rendering as the old
version. The definition was never re-checked on either path: the memo in
View.get is only re-resolved once a minute in the background, and a
display built from get-view-displays holds an exact version that is never
re-checked client-side at all.

View.refreshLatestVersion goes back to the API instead: it drops every
memoized resolution leading to the shown version — not just the one keyed
by it, since a built-in view is looked up by a hard-coded id — along with
the lookups behind them, and re-resolves synchronously.

When a newer version is found, the menu escalates from the in-place
rebuild to a structure refresh plus a page re-render, the route the
page-level "refresh now" takes: the version in use comes from the page's
structure, and a new version can change the query, columns, actions and
width, which is more than the piece on screen can be patched into. An
unchanged view takes the in-place path as before.

Closes #654

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A query-form view renders a QueryFormPanel, which is not a QueryResult, so
findParent(QueryResult.class) came back null, nothing could be rebuilt, and
the handler fell into its "no Ajax, nothing to rebuild" fallback: a full
page re-render. That is the one display type this happened to — every other
kind builds a QueryResult that can be swapped in place — and it is what made
these views flicker on every refresh.

There is nothing on screen to bring up to date for them: the form collects
parameters and the results live on the page it submits to. The query has
been marked outdated for that next submit and the view definition has been
re-checked, so the refresh is done; repainting the page on top of that
changes nothing visible.

Measured on a live space page with two query-form views and two regular
ones: before, the query-form views navigated to a fresh page render on the
click; after, no navigation, while the regular views keep refreshing in
place as before.

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

tkuhn commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Folded in a second fix: a query-form view's "refresh now" re-rendered the whole page (66e35d9).

QueryFormPanel is a plain Panel, not a QueryResult, so findParent(QueryResult.class) came back null, nothing could be rebuilt, and the handler dropped into its pre-existing "no Ajax, nothing to rebuild" fallback — setResponsePage(...). That is the one display type it happened to; every other kind builds a QueryResult that can be swapped in place. It reproduces on master, so it is not a regression from the version check in this PR.

For a query-form view there is nothing on screen to bring up to date: the form collects parameters and the results live on the page it submits to. The query is marked outdated for that next submit and the view definition is re-checked, so the refresh is complete; repainting the page on top of that changes nothing visible.

Measured on a live space page carrying two query-form views (🔍 Basic Search, 🧪 Test Search With Actions) and two regular ones (📢 Status Updates, 🗄 Archive URLs), driving the menu click headlessly and watching for a main-frame navigation:

before after
query-form views navigates to a fresh page render no navigation
regular views no navigation no navigation

Full suite still green: 1215 tests, 0 failures.

@tkuhn
tkuhn merged commit 8f37964 into master Aug 28, 2026
8 checks passed
@tkuhn
tkuhn deleted the fix/654-refresh-view-version branch August 28, 2026 11:21
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.

"refresh now" on a view display should also check whether view itself has new version

1 participant