feat(history): drop the Linked images caption from the history dialogs (D47 ruling)
The maintainer extended the D47 trim to the history page's two media dialogs. All images for this positive and Repeat run are named by their own dialog title, as in the concept (app.js a1282-1304), so their embedded collection no longer shows the "Linked images" heading or the "N loaded · N linked images" count. A stranded focus returns to the dialog's close button. The Images page keeps its caption. The history concept comparison now records each dialog's caption count in both documents, and TESTING.md D47 covers the dialogs.
This commit is contained in:
+9
-5
@@ -846,10 +846,13 @@ Recorded deviations on this page:
|
||||
because the legacy gallery let people change layout and density and nothing else on the
|
||||
page offers it, and the selected-image side panel, the one shared inspector the Images
|
||||
page uses (spec §3.3), so an image's details stay reachable without opening the viewer.
|
||||
The All images and Repeat run dialogs keep their collection caption. With no
|
||||
saved variant the page shows every image of the positive under "All images for this
|
||||
positive, including unassigned images. …" and no empty copy (a state the concept
|
||||
never reaches).
|
||||
The same ruling covers the page's two media dialogs, All images for this positive and
|
||||
Repeat run: as in the concept (app.js a1282-1304), each is named by its own dialog
|
||||
title, with no "Linked images" heading or "N loaded · N linked images" count, and a
|
||||
stranded focus returns to the dialog's close button (maintainer ruling, 2026-10-21).
|
||||
The Images page keeps its caption. With no saved variant the page shows every image
|
||||
of the positive under "All images for this positive, including unassigned images. …"
|
||||
and no empty copy (a state the concept never reaches).
|
||||
|
||||
The run dot reads `GET /prompt_manager/library/{positive_id}/history/pairs/{pair_id}/newest`
|
||||
(see "Chronological Library history"), and each lane's "N runs" is the pair's
|
||||
@@ -874,7 +877,8 @@ Images collection, so its height is not compared). D25: each compared block moun
|
||||
production class or margin. Behaviors are compared in both documents: a red dot changes
|
||||
the negative block and the gallery, Compare toggles `aria-pressed`, All images opens a
|
||||
dialog with the positive's four images, the run dot opens a dialog (D26: Recorded run
|
||||
where the concept shows Repeat run), the heading send previews the selected pair, and
|
||||
where the concept shows Repeat run), neither dialog has a collection caption (D47), the
|
||||
heading send previews the selected pair, and
|
||||
← Prompt library navigates. `history comparison detects mutations` injects
|
||||
`.ca-tools .variant-dot { width: 20px }` and removes Compare negatives. The older
|
||||
`history-canonical-comparison.mjs` stays for `workspace-visual.spec.mjs`'s recorded
|
||||
|
||||
@@ -144,13 +144,15 @@ const negativeText=page=>page.locator('article.surface .prompt-section.negative
|
||||
const galleryOf=async page=>({context:await page.locator('.history-gallery .panel-heading .small').textContent(),
|
||||
cards:await galleryCards(page).locator('.image-open').evaluateAll(nodes=>nodes.map(node=>node.getAttribute('aria-label')))});
|
||||
|
||||
/** A dialog the page opens: its accessible name and how many media cards it shows once loaded; then closed. */
|
||||
/** A dialog the page opens: its accessible name, how many media cards it shows once loaded and its captions; then closed. */
|
||||
async function dialogOf(page,trigger,{name,cards}) {
|
||||
await trigger.click();
|
||||
const dialog=page.getByRole('dialog',{name,exact:true});
|
||||
await expect(dialog).toBeVisible();
|
||||
if(cards)await expect(dialog.locator('.media-card')).toHaveCount(cards);
|
||||
const result=cards?{name,cards:await dialog.locator('.media-card').count()}:{name};
|
||||
// D47: neither document's media dialog carries a collection caption ("Linked images", "N loaded · …").
|
||||
const captions=await dialog.locator('.section-caption').count();
|
||||
const result=cards?{name,cards:await dialog.locator('.media-card').count(),captions}:{name,captions};
|
||||
await page.keyboard.press('Escape');await expect(dialog).toHaveCount(0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -832,6 +832,11 @@ test('run dot appears only for pairs with more than one run and opens its run',a
|
||||
await clean.click();const repeat=modalDialog(page,'Repeat run');await expect(repeat).toBeVisible();
|
||||
await expect(repeat.locator('#modal-body > p.small')).toHaveText('Same positive and negative, another execution.');
|
||||
await expect(repeat.locator('#modal-body > .spaced-15 article[data-image-key]')).toHaveCount(1);
|
||||
// D47: as in the concept (a1291-1304), the dialog title names the image; no collection heading or count repeats it.
|
||||
await expect(repeat.locator('.section-caption')).toHaveCount(0);
|
||||
await expect(repeat.getByRole('heading',{name:'Linked images',exact:true})).toHaveCount(0);
|
||||
await expect(repeat.getByText(/ loaded · /)).toHaveCount(0);
|
||||
expect(await repeat.evaluate(node=>[...node.querySelectorAll('h1, h2')].filter(item=>!item.closest('aside')).map(item=>item.textContent))).toEqual(['Repeat run']);
|
||||
expect(reads.at(-1).get('pair_id')).toBe(String(f.clean_pair));expect(reads.at(-1).get('limit')).toBe('1');
|
||||
await page.keyboard.press('Escape');await expect(repeat).toHaveCount(0);await expect(clean).toBeFocused();
|
||||
});
|
||||
@@ -1008,10 +1013,15 @@ test('shared gallery uses concept cards, image opens the viewer, empty copy',asy
|
||||
await page.keyboard.press('Escape');await expect(viewer).toBeHidden();await expect(openButton).toBeFocused();
|
||||
await expect(section.locator(':scope > .panel-heading')).toHaveCSS('justify-content','space-between');
|
||||
await expect(section).toHaveCSS('margin-top','24px');
|
||||
// The D47 ruling covers the shared gallery only: the All images dialog's collection keeps its own caption.
|
||||
// D47 (maintainer ruling 2026-10-21) covers the history page's dialogs too: the All images dialog is named by its
|
||||
// own title, with no "Linked images" heading or "N loaded · N linked images" count, as the concept's (a1282-1290).
|
||||
await variantsPanel(page).getByRole('button',{name:'All images for this positive',exact:true}).click();
|
||||
const all=page.getByRole('dialog',{name:'All images for this positive',exact:true});
|
||||
await expect(all.locator('.section-caption')).toContainText(/ loaded · /);
|
||||
await expect(all.locator('article[data-image-key]').first()).toBeVisible();
|
||||
await expect(all.locator('.section-caption')).toHaveCount(0);
|
||||
await expect(all.getByRole('heading',{name:'Linked images',exact:true})).toHaveCount(0);
|
||||
await expect(all.getByText(/ loaded · /)).toHaveCount(0);
|
||||
expect(await all.evaluate(node=>[...node.querySelectorAll('h1, h2')].filter(item=>!item.closest('aside')).map(item=>item.textContent))).toEqual(['All images for this positive']);
|
||||
await page.keyboard.press('Escape');await expect(all).toHaveCount(0);
|
||||
// At 390px the heading stays inside the gallery and the page never scrolls sideways.
|
||||
await page.setViewportSize({width:390,height:844});
|
||||
|
||||
@@ -97,8 +97,9 @@ function deliverFavorite(key, favorite) {
|
||||
}
|
||||
|
||||
/**
|
||||
* `caption: false` (the history page's shared gallery, D47) leaves out the embedded collection's "Linked images" heading
|
||||
* and count, whose page heading already names it; `focusTarget` then takes focus where that heading did.
|
||||
* `caption: false` (the history page's shared gallery and its All images and Repeat run dialogs, D47) leaves out the
|
||||
* embedded collection's "Linked images" heading and count, whose page heading or dialog title already names it;
|
||||
* `focusTarget` then takes focus where that heading did.
|
||||
*/
|
||||
export function mountImages(main, api, parentScope, {embedded = false, fetchPage, emptyText, caption: showCaption = true, focusTarget = null} = {}) {
|
||||
const scope = createScope();
|
||||
@@ -221,7 +222,7 @@ export function mountImages(main, api, parentScope, {embedded = false, fetchPage
|
||||
const showsEmpty = !embedded || typeof emptyText === 'string';
|
||||
const empty = el('div', embedded ? emptyText : 'No matching images. Try another search or category.', 'empty');
|
||||
empty.hidden = true;
|
||||
// D47: the history page's shared gallery is named by its own "Shared gallery" heading, so it has no caption.
|
||||
// D47: the history page's shared gallery and dialogs are named by their own heading or title, so they have no caption.
|
||||
if (showCaption) collection.append(caption);
|
||||
collection.append(grid);
|
||||
if (showsEmpty) collection.append(empty);
|
||||
|
||||
@@ -765,7 +765,9 @@ export function mountLibrary(main,api,parentScope,{positiveId}={}) {
|
||||
const dialogScope=createScope();imagesDialogScope=dialogScope;
|
||||
const grid=el('div',undefined,className);
|
||||
openContentDialog({scope:content,title,nodes:intro?[el('p',intro,'small'),grid]:[grid],trigger,onClose:()=>{dialogScope.dispose();if(imagesDialogScope===dialogScope) imagesDialogScope=null;}});
|
||||
mountImages(grid,api,dialogScope,{embedded:true,fetchPage});
|
||||
// D47: the dialog's own title names its images, as in the concept (a1282-1304), so the collection has no
|
||||
// "Linked images" heading or count; a stranded focus returns to the dialog's close button.
|
||||
mountImages(grid,api,dialogScope,{embedded:true,caption:false,focusTarget:grid.closest('dialog')?.querySelector('.dialog-header > button') ?? null,fetchPage});
|
||||
}
|
||||
const imagesPage=(id,query,signal)=>api.get(`/prompt_manager/library/${id}/images?${query}`,{signal});
|
||||
/** Concept "All images for this positive" (a1282-1290): every image of the positive, Load more bounded. */
|
||||
|
||||
Reference in New Issue
Block a user