Move a Subject to another page - #1356
Merged
Merged
Conversation
Member
Author
Recording.2026-09-03.154423.mp4 |
alistair3149
marked this pull request as ready for review
September 3, 2026 20:32
alistair3149
requested review from
JeroenDeDauw and
malberts
and
a lite review from Copilot
and removed request for
Copilot
September 3, 2026 20:54
alistair3149
force-pushed
the
feature/1338-move-subject-to-page
branch
from
September 3, 2026 21:14
5563f10 to
9a05ba4
Compare
alistair3149
marked this pull request as draft
September 3, 2026 21:14
alistair3149
force-pushed
the
feature/1338-move-subject-to-page
branch
from
September 4, 2026 01:31
9a05ba4 to
5c41fec
Compare
alistair3149
marked this pull request as ready for review
September 4, 2026 02:03
Member
|
Bikeshed, but I feel strongly about this: the icon makes me think "drag", esp since we have drag capabilities there. First icon that comes to mind as replacment is "=>" Edit: done via |
Member
Section looks good |
Fixes #1338 A Subject created in flow from a relation field is stored on the page holding the Subject whose relation was being filled in, which is often not where it belongs. Relocating one meant deleting it and recreating it elsewhere, which mints a new id and breaks every relation pointing at the old one. ## What it does Every Subject row on the Data tab gains a Move action, before Delete in both the button strip and the overflow menu. It opens a dialog holding a page lookup, a checkbox for making the Subject the target page's Main Subject, and the notices each choice earns. The Subject keeps its id, so the relations targeting it keep resolving and the subject-page index follows it to its new page. A page that does not exist yet can be named in the lookup; it is created when the move is confirmed, so an abandoned dialog leaves nothing behind. `POST /neowiki/v0/subject/{subjectId}/move` is the write surface. ## Decisions worth challenging **The source page is written first.** A move is two page edits and there is no cross-page write primitive. The graph projection is page-scoped: every page write rewrites the nodes of the Subjects that page holds and tears down the ones it no longer does, so the page written last is the one that decides what the moved Subject's node looks like. Writing the source last strips the node the target write has just built and leaves a bare `:Subject` stub belonging to no page until the next rebuild, while the wiki database and the index both look correct. The cost of source-first is a window in which the Subject is on no page; a target write that fails is answered by writing the source page back exactly as it was read. **Move is offered on the main-subject row as well**, with a warning that the page will be left without a main subject. Withholding it would only have hidden the action behind a demote-then-move dance. **The promotion checkbox is never checked for you**, and once a target is chosen it names the Subject that promoting would demote, so an effect on a page the user is not looking at is stated rather than sprung. **Page search is MediaWiki's own** `/v1/search/title`, which already carries page ids and drops results the viewer may not read. It is scoped to the wiki's default search namespaces, so a page outside them has to be typed in full. NeoWiki adds no page-search endpoint of its own. **The target page is not restricted by namespace**, because creating a Subject is not either. Restricting only move would be inconsistent. ## Manual Browser Check On a wiki with the demo data, as a user who can edit: 1. Open `Rijksmuseum`, then the **Data** tab. Every row has a Move button between copy-link and delete; narrow the window past the mobile breakpoint and it is in the ⋯ menu instead, above Delete. 2. Move one of the *Rijksmuseum attendance* subjects. The dialog opens with Move disabled. Type `ACME` — matching pages appear, with **Use "ACME" as a new page** last, under a separator. 3. Pick `ACME Inc`. Tick the checkbox: it names *ACME Inc*'s current main subject as the one that would be demoted. Untick it and move. A green toast names the subject and its new page, and the row leaves the listing. 4. Open `ACME Inc`'s Data tab: the attendance subject is there as a child. Its ID is unchanged. 5. Move it back to `Rijksmuseum`. On the source row for the **main** subject, open Move: an inline warning says the page will be left without a main subject. 6. In the dialog, type a title no page has and pick **Use "…" as a new page**, then Move. The page is created and the subject lands on it; visit the page to confirm. 7. Type a title, pick the create option, then correct the text without re-picking. Move is offered only once a target is chosen again — it must not create the page you first typed. ## Testing 1903 vitest and 1979 PHPUnit tests pass, plus the `@group Database` endpoint tests. The new tests were each mutation-verified: every guard inverted and seen to fail by name. One of them mounts the real graph and asserts the moved Subject has exactly one hosting page node and keeps its schema label, which is what the source-first ordering buys. Exercised end to end against a dev wiki: a Subject moved between pages and back, its relations still resolving, both pages carrying the edit summary, and every refusal path (400, 403, 404, 409, missing CSRF) answered as documented. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012KQMvby9ED7qd7E2XC6csE
JeroenDeDauw
force-pushed
the
feature/1338-move-subject-to-page
branch
from
September 6, 2026 22:50
5c41fec to
583af10
Compare
Member
|
I rebased this PR |
This was referenced Sep 7, 2026
JeroenDeDauw
added a commit
that referenced
this pull request
Sep 7, 2026
Follows-up to #1356 The Move action on the Data tab used `cdxIconMove`, the four-way arrow that is also the browser's drag cursor, one button away from the row's drag handle in a list that is dragged to reorder. A glyph that says "drag me" sat on the button that relocates a Subject to another page. It now uses `cdxIconArticleRedirect`, a page with an arrow leading away from it: the container-plus-arrow shape mail and file tools use for "move to", with a page as the container. The dialog's confirm button and the overflow-menu entry carry the same icon, and the ResourceLoader icon list follows. Considered, omitted: a custom page-with-arrow glyph without the redirect association, and moving the action into a labelled overflow menu on desktop.
JeroenDeDauw
added a commit
that referenced
this pull request
Sep 7, 2026
* Order the row actions by what they do to the row Follows-up to #1356 The Data tab's row actions ran Promote, Edit, Copy link, Move, Delete, then the drag handle. Copy link, which changes nothing, sat between actions that do; the rarely used Promote led the strip where the most used action, Edit, belongs; and the handle, which is grabbed rather than clicked, followed Delete with nothing between them. The strip now runs Copy link, Edit, Promote, Move, Delete: the one action that leaves the row as it is first, then the two that change it in place, then the two that take it out of the listing, with Delete last. The main row keeps its pin as the indicator beside the title. The overflow menu follows the same order, and the drag handle stands a little apart from the buttons. Considered, omitted: moving the drag handle to the row's left edge, the wider list convention, which would put it beside the expand chevron and the main row's pin. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Keep the order tests in the block that already sets them up The two order tests arrived in a describe of their own with a copy of the move-action block's setup, and left the two move-before-delete tests they subsume in place. They now sit in that block, and the subsumed tests are gone. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1338
A Subject created in flow from a relation field is stored on the page holding the Subject whose
relation was being filled in, which is often not where it belongs. Relocating one meant deleting it
and recreating it elsewhere, which mints a new id and breaks every relation pointing at the old one.
What it does
Every Subject row on the Data tab gains a Move action, before Delete in both the button strip and
the overflow menu. It opens a dialog holding a page lookup, a checkbox for making the Subject the
target page's Main Subject, and the notices each choice earns. The Subject keeps its id, so the
relations targeting it keep resolving and the subject-page index follows it to its new page.
A page that does not exist yet can be named in the lookup; it is created when the move is confirmed,
so an abandoned dialog leaves nothing behind.
POST /neowiki/v0/subject/{subjectId}/moveis the write surface.Decisions worth challenging
The source page is written first. A move is two page edits and there is no cross-page write
primitive. The graph projection is page-scoped: every page write rewrites the nodes of the Subjects
that page holds and tears down the ones it no longer does, so the page written last is the one that
decides what the moved Subject's node looks like. Writing the source last strips the node the target
write has just built and leaves a bare
:Subjectstub belonging to no page until the next rebuild,while the wiki database and the index both look correct. The cost of source-first is a window in
which the Subject is on no page; a target write that fails is answered by writing the source page
back exactly as it was read.
Move is offered on the main-subject row as well, with a warning that the page will be left
without a main subject. Withholding it would only have hidden the action behind a demote-then-move
dance.
The promotion checkbox is never checked for you, and once a target is chosen it names the
Subject that promoting would demote, so an effect on a page the user is not looking at is stated
rather than sprung.
Page search is MediaWiki's own
/v1/search/title, which already carries page ids and dropsresults the viewer may not read. It is scoped to the wiki's default search namespaces, so a page
outside them has to be typed in full. NeoWiki adds no page-search endpoint of its own.
The target page is not restricted by namespace, because creating a Subject is not either.
Restricting only move would be inconsistent.
Manual Browser Check
On a wiki with the demo data, as a user who can edit:
Rijksmuseum, then the Data tab. Every row has a Move button between copy-link anddelete; narrow the window past the mobile breakpoint and it is in the ⋯ menu instead, above
Delete.
ACME— matching pages appear, with Use "ACME" as a new page last, under a separator.ACME Inc. Tick the checkbox: it names ACME Inc's current main subject as the one thatwould be demoted. Untick it and move. A green toast names the subject and its new page, and the
row leaves the listing.
ACME Inc's Data tab: the attendance subject is there as a child. Its ID is unchanged.Rijksmuseum. On the source row for the main subject, open Move: an inlinewarning says the page will be left without a main subject.
is created and the subject lands on it; visit the page to confirm.
only once a target is chosen again — it must not create the page you first typed.
Testing
1903 vitest and 1979 PHPUnit tests pass, plus the
@group Databaseendpoint tests. The new testswere each mutation-verified: every guard inverted and seen to fail by name. One of them mounts the
real graph and asserts the moved Subject has exactly one hosting page node and keeps its schema
label, which is what the source-first ordering buys.
Exercised end to end against a dev wiki: a Subject moved between pages and back, its relations still
resolving, both pages carrying the edit summary, and every refusal path (400, 403, 404, 409, missing
CSRF) answered as documented.
Production notes
The write order is the one thing worth a reviewer's attention. An earlier arrangement passed every test — wiki database and subject-page index both correct — while leaving the moved Subject a bare
:Subjectstub in Neo4j. Only querying the graph after a live move caught it, which is whyMoveSubjectApiTestnow asserts on the projection and not just on the slots.