Page MenuHomePhabricator

Caption column: support {title} variable in default (link Caption ← Title) (!50)
Closed, ResolvedPublic

Description

Scope. Let the user fill the Caption column from the Title column via a {title} variable in the per-column default value, with a one-click "link" affordance between the two headers when they sit next to each other.

What it solves. "Many times the caption is the title (or the title plus a few words)." Today filling a caption per row is fully manual; the user wants a column-level recipe like Photo of {title} that resolves to the right caption per file.

What's wanted

  1. {title} variable in caption defaults. The Caption column's per-column default value (already settable from the column header chevron menu — see HeaderMenuPopover in src/table.jsx:4047) gains support for a {title} token. When the default is applied to a row (via the existing "Apply to blank cells / Apply to all selected / Overwrite selected / Overwrite all" split-button at src/table.jsx:4280-4354), {title} is replaced by that row's title.
  1. Free-form prefix and suffix. No separate "prefix" / "suffix" inputs — they're just the literal text the user types around the token. e.g. default = Photo of {title} — taken by me → row with title Sunset over Lake resolves to Photo of Sunset over Lake — taken by me. The whole default field is a template string.
  1. Strip the auto-numbering placeholder from {title}. The auto-sequence task (T425984) introduces a trailing # that gets resolved to a concrete integer at publish time. The {title} substitution must NOT include that #. Strip a trailing \s*#\s*$ before substitution (regardless of whether T425984 has shipped — the convention is forward-compatible). Same applies to whatever final form T425984 lands on; if the placeholder character changes, this code stays the single point of stripping.
  1. Inter-header link icon (the "linking icon" the user described). When Title (title) and Caption (description) sit adjacent in the visible column order (in either direction — Title→Caption or Caption→Title), render a small chain icon centered on the boundary between their two header cells. Clicking it:
    • Opens the Caption column's HeaderMenuPopover (existing chevron menu).
    • Pre-expands the "Set default value" panel.
    • If the current default is empty, pre-fills it with {title}. If non-empty, leaves it alone (don't clobber a user's existing string) but still opens the panel so the user sees the field and can edit.
    • Tooltip: "Link Caption ← Title".
    • Visible only when adjacent — when the columns aren't neighbors, the icon doesn't render at all.
  1. Caption header dropdown is the always-available fallback. The Caption column header chevron already opens HeaderMenuPopover. Add a dedicated menu item — "Insert {title} variable" — above (or alongside) "Set default value", that does the same pre-fill as the link-icon click. This is the path users take when the columns aren't adjacent (e.g. Caption is far to the right with other columns in between).

Where the code lives

  • Header rendering / column adjacency check. src/table.jsx:786 — the visibleColumns.map((c, ci) => <HeaderCell ...>) loop. Adjacency = check visibleColumns[ci] and visibleColumns[ci+1] against the { "title", "description" } pair.
  • Header link icon visual. New element rendered between two adjacent HeaderCells. Two practical placements:
    • Inside the right-hand HeaderCell, anchored at its left edge (negative margin).
    • As a sibling absolutely-positioned element overlaying the column boundary. Either approach is fine; the icon itself is Icon name="link" (already in src/icons.jsx:42). 14-16 px, opacity ~0.55 idle, 1.0 on hover, with a tooltip via title="...". Click opens Caption's HeaderMenuPopover (programmatically set headerMenu state in Table to { colKey: 'description', anchorEl: <icon ref> }).
  • Default-value editor for description. src/table.jsx:4233-4242 — currently the default branch (just an <input>). Two tweaks:
    • Add a "Insert {title}" chip/button next to the input that appends {title} at the cursor (or at the end if focus isn't in the input). Mirrors the existing "Me" / "{{own}}" quick-insert pattern at src/table.jsx:4189-4196 (author) and src/table.jsx:4223-4231 (source).
    • Below the input, a small live-preview line: Preview: <expanded value from a sample row>. Helps the user see what their template will produce.
  • Token expansion at apply-time. Currently applyDefault / overwriteWithDefault in Table (src/table.jsx:912-935) write def into it[k] directly. For Caption, route through a new helper expandCaptionTemplate(template, item) → string that:
    • Returns template unchanged if template doesn't contain {title}.
    • Otherwise replaces {title} with stripSequencePlaceholder(item.title) where stripSequencePlaceholder removes a trailing \s*#\s*$.
    • Returns the resulting string (may be empty if template was just {title} and the row has no title — that's fine, "apply to blanks" already only fills when the destination is blank, so this is a no-op for blank-blank rows).
  • Header menu item insertion. src/table.jsx:4251-4432 (<ul className="hdr-pop__menu">). Add a new <li> for "Insert {title} variable" gated to col.key === 'description'. Clicking it: expands the default-value panel and appends {title} to value. (Reuse the same onChange already wired to setColumnDefaults.)
  • No new persistence layer. The default value lives in columnDefaults['description'] which is already persisted via setPref('columnDefaults', ...) (see src/api/user-store.js:770). Just stays a string; the {title} token is data, not metadata.

UX details

  • Per-column default of {title} for Caption is treated as "no default" by hasDefault indicator dot in the header (src/table.jsx:1288)? No — keep treating it as having a default (the dot is a generic "this column has a default" marker; users will quickly learn that the dot for Caption means "templated").
  • Clicking the link icon when a default already exists: open the popover, expand the panel, scroll the input into view — no overwrite. If the existing default doesn't contain {title}, the popover surfaces the "Insert {title}" chip so the user can append it.
  • The token {title} is the only one in v1. If we later want {filename}, {author}, etc., the same expansion helper grows; out of scope here.
  • Case-sensitive match for {title} — keep it simple. We can normalize or accept {Title} later if needed.

Acceptance

  • Caption header chevron → "Set default value" → typing Photo of {title} and clicking "Apply to blank cells" fills every blank caption with Photo of <that-row's-title>.
  • A row whose title ends with the T425984 sequence placeholder (e.g. Sunset over Lake #) resolves the variable to Sunset over Lake (no trailing #, no trailing whitespace).
  • A row whose title is empty resolves the variable to the empty string; the rest of the template still renders.
  • When Caption and Title are adjacent (regardless of direction), a chain icon appears between the two header cells; clicking it opens the Caption header menu with the default-value panel expanded.
  • When Caption and Title are NOT adjacent, the icon does not appear; the "Insert {title} variable" item in the Caption header dropdown is the access path.
  • The default-value editor for Caption shows a one-click "Insert {title}" chip and a small live preview of the expanded result for a sample row.
  • {title} substitution is one-shot at apply time — editing a title later does NOT retroactively update existing captions (consistent with the existing "default value + apply scope" model). The user re-clicks "Apply / Overwrite" if they want a refresh.
  • No regressions to other columns' default-value editors or to the Caption column's existing per-row editing.

Out of scope

  • Live two-way binding (caption auto-updates when title changes after the first apply). The existing model is one-shot fill; this task stays consistent with it.
  • Other variables besides {title} (e.g. {filename}, {author}, {date}). Easy to grow later — keep the expansion helper extensible but only {title} is wired now.
  • Reverse direction ({caption} substituting into Title). The user explicitly asked Caption ← Title.
  • Per-row override: if the user clicks "Apply to blank cells" with a {title} template and one row has a custom non-blank caption, that row stays untouched (existing apply-to-blanks semantics).

Source: User feedback session (T426424).

Related: T425984 (auto-sequence # placeholder — informs the strip-rule for {title} expansion), and the existing column-header menu plumbing at src/table.jsx:4029 (HeaderMenuPopover).

Event Timeline

Daanvr moved this task from To do to Doing on the Tool-upload-workbench board.

Grooming pass (AI)

Description rewritten with investigation findings (see task description above). Original preserved here verbatim:

The user hsould be enabled to link the caption column and the title column. many times they are the same or the caption is the title plus a few words. Thjerefore the user should be able to add the title value as a variable. that can be frefixed or sufixed with a string. The numbering somtimes automaticaly aplied to titles should not be part of the value used for the variable. If the columns are next to each other there should be a linking icon between them. clicking it would apend the varaible to caption. this dynamic should also be availabe throug the caption column header dropdown as a backup also when the columns are not next to each other.

Daanvr renamed this task from link caption and title to Caption column: support {title} variable in default (link Caption ← Title).Fri, May 15, 3:57 PM
Daanvr updated the task description. (Show Details)
Daanvr renamed this task from Caption column: support {title} variable in default (link Caption ← Title) to Caption column: support {title} variable in default (link Caption ← Title) (!50).Fri, May 15, 4:14 PM
Daanvr moved this task from Doing to Reviewing on the Tool-upload-workbench board.

wel, the link button between the two columns sould be at the row level instead of the header level. it sould simple ad the value od the title to the cel content. no menu or anything needed.
it sould be possible ot also acces it throug the caption column header dropdown.

Addressed feedback on !50:

  1. Removed the inter-header chain icon between adjacent Title and Caption headers (the click-opens-popover-with-template-seeded-default flow).
  2. Added a per-row chain icon on the Caption cell, visible on row hover when Title is the immediate left or right neighbour. One click writes the row's title (with the trailing T425984 # placeholder stripped) into the description field — no menu, no template, no confirmation. Disabled when the title is empty.
  3. Replaced the Caption header dropdown's "Insert {title} variable" item with a simpler Fill blanks from Title action that walks every row and fills blank caption cells with that row's title in one click.

The advanced {title}-template plumbing (chip + live preview in the default-value editor, expandCaptionTemplate resolution at apply-time) is preserved for users who want a recipe like Photo of {title}.

Verification (curl + bundle grep on the deployed preview):

  • Preview redeployed at https://upload-workbench.toolforge.org/mr-50/ (deploy:mr success on pipeline 187535, asset paths under /mr-50/).
  • Bundle contains the new strings: Fill blanks from Title, tbl__td-titlelink, Copy this row's title into the caption, Add a title first to copy it into the caption.
  • Bundle no longer contains the removed strings: Insert {title} variable (dropdown item), tbl__th-linkpair (header icon).
  • CSS bundle contains the new .tbl__td-titlelink selectors with --left/--right/--shift modifiers and the row-hover trigger; no longer contains .tbl__th-linkpair.

Hover behaviour and click-to-fill are not directly verifiable from curl — please poke the preview in a browser to confirm the icon appears at the expected boundary on row hover and that clicking copies title→caption.

New commit pushed to feat/T426424-link-caption-title; preview redeployed at /mr-50/.