feat(tasks-ui): one task window everywhere, cards are their own detail entry
Round-three review feedback: - NO PER-CARD DETAIL BUTTON: the ellipsis control is gone from graph cards and tree rows — the card IS the affordance, and clicking it opens the detail window (the transcript jump moved inside as the primary button). Fold aggregates keep click-to-expand. - ONE TASK WINDOW: every task surface (board row, agent node task line, the node detail list, and creating a task) now opens the same non-fullscreen DRAGGABLE window (TaskWindow.tsx + its TaskPopover shell): markdown description by default, 编辑 switches the same card to multi-line editing, plus owner reassignment, complete/reopen and a two-step delete. The board lost its overflow menu and its Modal entirely; create uses the same window in create mode. - REUSE: TaskPopover (4 call sites), MultilineField (the plugin's own multi-line input — the host primitive set has none), OwnerPicker, TaskCreateButton, and the shared glyph/TaskLine helpers across both modes. - 3 new copy keys across zh/en/ja and the 18 third-language dictionaries. Tests: the node-click spec now asserts the detail window (and that the jump button inside it navigates), a new spec pins 'no nested control inside a card', and two more cover the shared window: markdown-first view then multi-line edit posting an 'edit' with the current revision, and immediate owner reassignment. Full suite 1406 passed / 133 files.
This commit is contained in:
@@ -143,14 +143,29 @@ export function primaryTask(tasks: readonly TasksNodeTask[]): TasksNodeTask | un
|
||||
* status word, and a `+N` tail when the agent owns more. Renders nothing
|
||||
* without tasks, so non-team nodes keep the three-line shape.
|
||||
*/
|
||||
export function TaskLine(props: { tasks: readonly TasksNodeTask[] | undefined }): ReactNode {
|
||||
export function TaskLine(props: {
|
||||
tasks: readonly TasksNodeTask[] | undefined
|
||||
onOpenTask(taskId: string, anchor: HTMLElement): void
|
||||
}): ReactNode {
|
||||
const tasks = props.tasks ?? []
|
||||
const primary = primaryTask(tasks)
|
||||
if (primary === undefined) return null
|
||||
return (
|
||||
<span
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
className={css.taskLine}
|
||||
title={tasks.map(task => `${task.subject}(${t(taskStatusKey(task.status))})`).join('\n')}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation()
|
||||
props.onOpenTask(primary.id, event.currentTarget)
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key !== 'Enter' && event.key !== ' ') return
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
props.onOpenTask(primary.id, event.currentTarget)
|
||||
}}
|
||||
>
|
||||
<span className={css.taskGlyph} aria-hidden="true"><IconChecklistOutline14 size={9} /></span>
|
||||
<span className={css.taskSubject}>{primary.subject}</span>
|
||||
|
||||
Reference in New Issue
Block a user