@lemoncat7/dsh-partner 1.5.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -1468,28 +1468,56 @@ body[data-ds-dark-theme] :is(.dsh-partner-sidebar, .dsh-partner-workspace) {
1468
1468
  .dsh-partner-feature-form > p.is-success { color: var(--partner-success); background: color-mix(in srgb, var(--partner-success) 7%, transparent); }
1469
1469
  .dsh-partner-board-live { display: inline-flex; min-height: 36px; align-items: center; gap: 7px; padding: 0 10px; color: var(--partner-text-tertiary); font-size: var(--partner-font-caption); }
1470
1470
  .dsh-partner-board-live > i { width: 7px; height: 7px; border-radius: 50%; background: var(--partner-success); box-shadow: 0 0 0 4px color-mix(in srgb, var(--partner-success) 10%, transparent); }
1471
- .dsh-partner-board { display: grid; grid-template-columns: repeat(6, minmax(280px, 1fr)); gap: 10px; overflow-x: auto; padding: 1px 1px 10px; scroll-snap-type: x proximity; scrollbar-width: thin; }
1472
- .dsh-partner-board > section { display: grid; min-height: 430px; align-content: start; gap: 9px; padding: 11px; border: 1px solid var(--partner-border); border-radius: 14px; background: color-mix(in srgb, var(--partner-raised) 66%, transparent); scroll-snap-align: start; }
1471
+ .dsh-partner-board-tools { display: grid; grid-template-columns: minmax(220px, 1fr) minmax(140px, 180px) auto; align-items: center; gap: 8px; }
1472
+ .dsh-partner-board-search { position: relative; display: flex; min-width: 0; align-items: center; }
1473
+ .dsh-partner-board-search > span:not(.sr-only) { position: absolute; z-index: 1; left: 11px; display: grid; place-items: center; color: var(--partner-text-tertiary); pointer-events: none; }
1474
+ .dsh-partner-board-search > input,
1475
+ .dsh-partner-board-assignee > select { width: 100%; min-height: 38px; border: 1px solid var(--partner-border); border-radius: 10px; color: var(--partner-text); background-color: var(--partner-control); font: var(--partner-font-body)/1.4 var(--partner-font-family); transition: border-color 150ms ease, background-color 150ms ease, box-shadow 150ms ease; }
1476
+ .dsh-partner-board-search > input { padding: 8px 38px 8px 34px; }
1477
+ .dsh-partner-board-search > input::placeholder { color: var(--partner-text-tertiary); }
1478
+ .dsh-partner-board-search > input:hover,
1479
+ .dsh-partner-board-assignee > select:hover { border-color: color-mix(in srgb, var(--partner-text) 24%, var(--partner-border)); background-color: var(--partner-hover); }
1480
+ .dsh-partner-board-search > input:focus-visible,
1481
+ .dsh-partner-board-assignee > select:focus-visible { outline: 0; border-color: var(--partner-focus-ring); background-color: var(--partner-raised); box-shadow: 0 0 0 3px color-mix(in srgb, var(--partner-focus-ring) 16%, transparent); }
1482
+ .dsh-partner-board-search > button { position: absolute; z-index: 1; right: 4px; display: grid; width: 30px; min-height: 30px; place-items: center; padding: 0; border: 0; border-radius: 7px; color: var(--partner-text-tertiary); background: transparent; box-shadow: none; }
1483
+ .dsh-partner-board-search > button:hover { color: var(--partner-text); background: var(--partner-hover); }
1484
+ .dsh-partner-board-assignee > select { min-width: 0; padding: 8px 30px 8px 10px; }
1485
+ .dsh-partner-board-tools > small { justify-self: end; color: var(--partner-text-tertiary); font-size: var(--partner-font-caption); font-variant-numeric: tabular-nums; white-space: nowrap; }
1486
+ .dsh-partner-board-statuses { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; padding-bottom: 2px; }
1487
+ .dsh-partner-board-statuses > button { display: inline-flex; min-height: 32px; align-items: center; gap: 7px; padding: 0 9px; border: 1px solid transparent; border-radius: 9px; color: var(--partner-text-tertiary); background: transparent; box-shadow: none; font: var(--partner-font-caption)/1 var(--partner-font-family); cursor: pointer; transition: border-color 140ms ease, color 140ms ease, background-color 140ms ease; }
1488
+ .dsh-partner-board-statuses > button:hover { border-color: var(--partner-border); color: var(--partner-text); background: var(--partner-hover); }
1489
+ .dsh-partner-board-statuses > button.is-active { border-color: color-mix(in srgb, var(--partner-text) 18%, var(--partner-border)); color: var(--partner-text); background: var(--partner-selected); }
1490
+ .dsh-partner-board-statuses b { min-width: 18px; color: inherit; font-size: inherit; font-variant-numeric: tabular-nums; font-weight: 650; text-align: center; }
1491
+ .dsh-partner-board { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); align-items: start; gap: 10px; min-width: 0; }
1492
+ .dsh-partner-board[data-focused="true"] { grid-template-columns: minmax(0, 1fr); }
1493
+ .dsh-partner-board > section { display: grid; height: clamp(220px, 27vh, 280px); min-width: 0; grid-template-rows: auto minmax(0, 1fr); align-content: start; gap: 9px; padding: 11px 9px 9px 11px; border: 1px solid var(--partner-border); border-radius: 14px; background: color-mix(in srgb, var(--partner-raised) 66%, transparent); }
1494
+ .dsh-partner-board > section[data-empty="true"] { height: 132px; }
1495
+ .dsh-partner-board[data-focused="true"] > section { height: clamp(340px, 54vh, 560px); }
1496
+ .dsh-partner-board[data-focused="true"] > section[data-empty="true"] { height: 240px; }
1473
1497
  .dsh-partner-board > section > header { display: flex; min-height: 36px; align-items: center; justify-content: space-between; padding: 0 3px; }
1474
1498
  .dsh-partner-board > section > header strong { font-size: var(--partner-font-label); font-weight: 620; }
1475
1499
  .dsh-partner-board > section > header b { display: grid; min-width: 22px; height: 22px; place-items: center; padding: 0 5px; border-radius: 7px; color: var(--partner-text-tertiary); background: var(--partner-selected); font-size: var(--partner-font-caption); }
1476
- .dsh-partner-board > section > div { display: grid; gap: 8px; }
1477
- .dsh-partner-board > section > p { margin: 12px 0; color: var(--partner-text-tertiary); font-size: var(--partner-font-body); text-align: center; }
1478
- .dsh-partner-task-card { position: relative; display: grid; overflow: hidden; border: 1px solid var(--partner-separator); border-radius: 11px; background: var(--partner-raised); box-shadow: var(--partner-shadow-sm); transition: border-color .16s ease, box-shadow .18s ease, transform .16s var(--partner-ease-out); }
1500
+ .dsh-partner-board-column-list { display: grid; min-height: 0; grid-auto-rows: max-content; align-content: start; gap: 7px; overflow-y: auto; padding: 1px 3px 6px 0; overscroll-behavior: contain; scrollbar-gutter: stable; scrollbar-width: thin; }
1501
+ .dsh-partner-board > section > p { align-self: center; margin: 0 0 22px; color: var(--partner-text-tertiary); font-size: var(--partner-font-body); text-align: center; }
1502
+ .dsh-partner-task-card { position: relative; display: grid; min-height: 82px; overflow: hidden; border: 1px solid var(--partner-separator); border-radius: 11px; background: var(--partner-raised); box-shadow: var(--partner-shadow-sm); transition: border-color .16s ease, box-shadow .18s ease, transform .16s var(--partner-ease-out); }
1479
1503
  .dsh-partner-task-card:hover { border-color: color-mix(in srgb, var(--partner-text) 22%, var(--partner-border)); box-shadow: var(--partner-shadow-md); transform: translateY(-1px); }
1480
1504
  .dsh-partner-task-card:focus-within { border-color: var(--partner-focus-ring); box-shadow: 0 0 0 2px color-mix(in srgb, var(--partner-focus-ring) 18%, transparent), var(--partner-shadow-md); }
1481
1505
  .dsh-partner-task-card[data-blocked="true"] { border-left-color: color-mix(in srgb, var(--partner-warning) 55%, var(--partner-border)); }
1482
- .dsh-partner-task-summary { display: grid !important; min-height: 66px !important; grid-template-columns: minmax(0, 1fr) 16px; align-items: center !important; gap: 10px !important; padding: 11px 12px !important; border: 0 !important; border-radius: 0 !important; appearance: none; color: var(--partner-text) !important; background: transparent !important; box-shadow: none !important; font-family: var(--partner-font-family); text-align: left; cursor: pointer; }
1506
+ .dsh-partner-task-summary { display: grid !important; min-height: 82px !important; grid-template-columns: minmax(0, 1fr) 16px; align-items: center !important; gap: 8px !important; padding: 10px 10px 10px 11px !important; border: 0 !important; border-radius: 0 !important; appearance: none; color: var(--partner-text) !important; background: transparent !important; box-shadow: none !important; font-family: var(--partner-font-family); text-align: left; cursor: pointer; }
1483
1507
  .dsh-partner-task-summary:hover { background: var(--partner-hover) !important; }
1484
1508
  .dsh-partner-task-summary:focus-visible { outline: 0; }
1485
- .dsh-partner-task-summary > span { display: grid; min-width: 0; gap: 6px; }
1486
- .dsh-partner-task-summary strong { overflow: hidden; padding-right: 12px; font-size: var(--partner-font-label); font-weight: 620; text-overflow: ellipsis; white-space: nowrap; }
1487
- .dsh-partner-task-summary small { overflow: hidden; color: var(--partner-text-tertiary); font-size: var(--partner-font-caption); text-overflow: ellipsis; white-space: nowrap; }
1509
+ .dsh-partner-task-summary > span { display: grid; min-width: 0; gap: 4px; }
1510
+ .dsh-partner-task-card-title { display: flex; min-width: 0; align-items: flex-start; justify-content: space-between; gap: 8px; }
1511
+ .dsh-partner-task-card-title > strong { display: -webkit-box; min-width: 0; overflow: hidden; color: var(--partner-text); font-size: var(--partner-font-body); font-weight: 620; line-height: 1.38; overflow-wrap: anywhere; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
1512
+ .dsh-partner-task-card-title > em { flex: none; margin-top: 1px; padding: 2px 5px; border: 1px solid var(--partner-separator); border-radius: 6px; color: var(--partner-text-tertiary); background: var(--partner-control); font-size: 10px; font-style: normal; font-weight: 620; line-height: 1.25; }
1513
+ .dsh-partner-task-card[data-priority="high"] .dsh-partner-task-card-title > em { border-color: color-mix(in srgb, var(--partner-warning) 35%, var(--partner-separator)); color: var(--partner-warning); background: color-mix(in srgb, var(--partner-warning) 7%, var(--partner-control)); }
1514
+ .dsh-partner-task-card[data-priority="urgent"] .dsh-partner-task-card-title > em { border-color: color-mix(in srgb, var(--partner-danger) 34%, var(--partner-separator)); color: var(--partner-danger); background: color-mix(in srgb, var(--partner-danger) 7%, var(--partner-control)); }
1515
+ .dsh-partner-task-card-owner { overflow: hidden; color: var(--partner-text-tertiary); font-size: var(--partner-font-caption); text-overflow: ellipsis; white-space: nowrap; }
1516
+ .dsh-partner-task-relations { display: flex; min-width: 0; align-items: center; flex-wrap: wrap; gap: 4px; }
1517
+ .dsh-partner-task-relations > small { padding: 2px 6px; border-radius: 6px; color: var(--partner-text-secondary); background: var(--partner-selected); font-size: 10px; font-variant-numeric: tabular-nums; line-height: 1.3; }
1518
+ .dsh-partner-task-relations > small[data-blocked="true"] { color: var(--partner-warning); background: color-mix(in srgb, var(--partner-warning) 8%, var(--partner-selected)); }
1488
1519
  .dsh-partner-task-summary > svg { color: var(--partner-text-tertiary); transition: transform .16s var(--partner-ease-out), color .16s ease; }
1489
1520
  .dsh-partner-task-summary:hover > svg { color: var(--partner-text); transform: translateX(2px); }
1490
- .dsh-partner-priority { position: absolute; top: 17px; right: 12px; width: 6px; height: 6px; border-radius: 50%; background: var(--partner-text-tertiary); }
1491
- .dsh-partner-priority.is-high { background: var(--partner-warning); }
1492
- .dsh-partner-priority.is-urgent { background: var(--partner-danger); box-shadow: 0 0 0 3px color-mix(in srgb, var(--partner-danger) 12%, transparent); }
1493
1521
  .dsh-partner-task-detail { display: grid; gap: 13px; }
1494
1522
  .dsh-partner-task-description { display: grid; gap: 6px; padding: 12px; border: 1px solid var(--partner-separator); border-radius: 10px; background: color-mix(in srgb, var(--partner-raised) 78%, transparent); }
1495
1523
  .dsh-partner-task-description strong { font-size: var(--partner-font-body); font-weight: 620; }
@@ -1587,6 +1615,8 @@ body[data-ds-dark-theme] :is(.dsh-partner-sidebar, .dsh-partner-workspace) {
1587
1615
  @media (max-width: 820px) {
1588
1616
  .dsh-partner-feature-hero { align-items: start; flex-direction: column; gap: 12px; }
1589
1617
  .dsh-partner-feature-hero > div { width: 100%; flex-wrap: wrap; }
1618
+ .dsh-partner-board-tools { grid-template-columns: minmax(0, 1fr) minmax(130px, 168px); }
1619
+ .dsh-partner-board-tools > small { grid-column: 1 / -1; justify-self: start; }
1590
1620
  .dsh-partner-feature-form, .dsh-partner-task-form, .dsh-partner-schedule-form { grid-template-columns: 1fr 1fr; }
1591
1621
  .dsh-partner-schedule-list > article { grid-template-columns: minmax(0, 1fr) auto 30px; }
1592
1622
  .dsh-partner-schedule-list > article > button:not(.is-icon):not(.dsh-partner-feature-switch) { grid-column: 1 / -1; }
@@ -1605,6 +1635,12 @@ body[data-ds-dark-theme] :is(.dsh-partner-sidebar, .dsh-partner-workspace) {
1605
1635
  .dsh-partner-skill-installed > article > .is-icon { grid-column: 3; }
1606
1636
  .dsh-partner-feature-block > header { align-items: flex-start; flex-direction: column; }
1607
1637
  .dsh-partner-feature-block > header > div { width: 100%; flex-wrap: wrap; justify-content: flex-start; }
1638
+ .dsh-partner-board-tools { grid-template-columns: 1fr; }
1639
+ .dsh-partner-board-assignee, .dsh-partner-board-tools > small { grid-column: 1; }
1640
+ .dsh-partner-board-assignee > select { min-height: 42px; }
1641
+ .dsh-partner-board-statuses { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
1642
+ .dsh-partner-board-statuses > button { min-width: 0; justify-content: center; padding-inline: 6px; }
1643
+ .dsh-partner-board > section, .dsh-partner-board[data-focused="true"] > section { height: min(430px, 58vh); }
1608
1644
  .dsh-partner-feature-form, .dsh-partner-task-form, .dsh-partner-schedule-form { grid-template-columns: 1fr; padding: 14px; }
1609
1645
  :is(.dsh-partner-feature-form, .dsh-partner-task-form, .dsh-partner-schedule-form) > label { grid-column: 1 !important; }
1610
1646
  .dsh-partner-task-form-dependencies > div { grid-template-columns: 1fr; }
@@ -3410,8 +3446,48 @@ function TaskBoardPanel() {
3410
3446
  const [loading, setLoading] = (0, import_react6.useState)(true);
3411
3447
  const [error, setError] = (0, import_react6.useState)();
3412
3448
  const [syncedAt, setSyncedAt] = (0, import_react6.useState)();
3413
- const selectedTask = board.tasks.find((item) => item.id === selectedTaskId);
3449
+ const [query, setQuery] = (0, import_react6.useState)("");
3450
+ const [statusFilter, setStatusFilter] = (0, import_react6.useState)("all");
3451
+ const [assigneeFilter, setAssigneeFilter] = (0, import_react6.useState)("all");
3452
+ const deferredQuery = (0, import_react6.useDeferredValue)(query.trim().toLocaleLowerCase());
3414
3453
  const tasksById = (0, import_react6.useMemo)(() => new Map(board.tasks.map((item) => [item.id, item])), [board.tasks]);
3454
+ const directoryById = (0, import_react6.useMemo)(() => new Map(directory.map((item) => [item.id, item])), [directory]);
3455
+ const activeDelegationByTaskId = (0, import_react6.useMemo)(() => {
3456
+ const result = /* @__PURE__ */ new Map();
3457
+ for (const delegation of delegations) {
3458
+ if ((delegation.status === "queued" || delegation.status === "running") && !result.has(delegation.taskId)) result.set(delegation.taskId, delegation);
3459
+ }
3460
+ return result;
3461
+ }, [delegations]);
3462
+ const selectedTask = selectedTaskId ? tasksById.get(selectedTaskId) : void 0;
3463
+ const dependentsById = (0, import_react6.useMemo)(() => {
3464
+ const result = /* @__PURE__ */ new Map();
3465
+ for (const task of board.tasks) for (const dependencyId of task.dependencyTaskIds) result.set(dependencyId, (result.get(dependencyId) ?? 0) + 1);
3466
+ return result;
3467
+ }, [board.tasks]);
3468
+ const scopedTasks = (0, import_react6.useMemo)(() => board.tasks.filter((task) => {
3469
+ if (assigneeFilter !== "all" && (task.assigneeCompanionId ?? "unassigned") !== assigneeFilter) return false;
3470
+ if (!deferredQuery) return true;
3471
+ const dependencies = task.dependencyTaskIds.map((id) => tasksById.get(id)?.title ?? "");
3472
+ return [task.title, task.description, task.resultAbstract, task.resultSummary, directoryById.get(task.assigneeCompanionId ?? "")?.name, ...dependencies].some((value) => value?.toLocaleLowerCase().includes(deferredQuery));
3473
+ }), [assigneeFilter, board.tasks, deferredQuery, directoryById, tasksById]);
3474
+ const statusCounts = (0, import_react6.useMemo)(() => {
3475
+ const result = new Map(COLUMNS.map((column) => [column.id, 0]));
3476
+ for (const task of scopedTasks) result.set(task.status, (result.get(task.status) ?? 0) + 1);
3477
+ return result;
3478
+ }, [scopedTasks]);
3479
+ const visibleColumns = statusFilter === "all" ? COLUMNS : COLUMNS.filter((column) => column.id === statusFilter);
3480
+ const tasksByStatus = (0, import_react6.useMemo)(() => {
3481
+ const priorityRank = { urgent: 3, high: 2, normal: 1, low: 0 };
3482
+ const result = new Map(COLUMNS.map((column) => [column.id, []]));
3483
+ for (const task of scopedTasks) {
3484
+ if (statusFilter !== "all" && task.status !== statusFilter) continue;
3485
+ result.get(task.status)?.push(task);
3486
+ }
3487
+ for (const tasks of result.values()) tasks.sort((left, right) => priorityRank[right.priority] - priorityRank[left.priority] || right.updatedAt - left.updatedAt);
3488
+ return result;
3489
+ }, [scopedTasks, statusFilter]);
3490
+ const visibleTaskCount = statusFilter === "all" ? scopedTasks.length : statusCounts.get(statusFilter) ?? 0;
3415
3491
  const loadingRef = (0, import_react6.useRef)(false);
3416
3492
  const load = (0, import_react6.useCallback)(async () => {
3417
3493
  if (loadingRef.current) return;
@@ -3540,7 +3616,7 @@ function TaskBoardPanel() {
3540
3616
  tasks: board.tasks,
3541
3617
  activities: board.activities.filter((item) => item.taskId === selectedTask.id),
3542
3618
  directory,
3543
- execution: delegations.find((item) => item.taskId === selectedTask.id && (item.status === "queued" || item.status === "running")),
3619
+ execution: activeDelegationByTaskId.get(selectedTask.id),
3544
3620
  busy: busy === selectedTask.id,
3545
3621
  update: (change) => {
3546
3622
  void update(selectedTask, change);
@@ -3563,50 +3639,99 @@ function TaskBoardPanel() {
3563
3639
  },
3564
3640
  selectedTask.id
3565
3641
  ) }),
3566
- loading ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CollectionSkeleton, { rows: 6 }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dsh-partner-board", "aria-label": "\u4EFB\u52A1\u770B\u677F", children: COLUMNS.map((column) => {
3567
- const tasks = board.tasks.filter((item) => item.status === column.id);
3568
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { "data-status": column.id, children: [
3569
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { children: [
3570
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: column.label }),
3571
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("b", { children: tasks.length })
3642
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CollectionSkeleton, { rows: 6 }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
3643
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dsh-partner-board-tools", children: [
3644
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "dsh-partner-board-search", children: [
3645
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "sr-only", children: "\u641C\u7D22\u4EFB\u52A1" }),
3646
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives3.IconSearchOutline16, { size: 16 }) }),
3647
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { value: query, onChange: (event) => setQuery(event.target.value), placeholder: "\u641C\u7D22\u4EFB\u52A1\u3001\u8D1F\u8D23\u4EBA\u6216\u524D\u7F6E\u4EFB\u52A1" }),
3648
+ query && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", onClick: () => setQuery(""), "aria-label": "\u6E05\u9664\u4EFB\u52A1\u641C\u7D22", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives3.IconCloseOutline16, { size: 14 }) })
3572
3649
  ] }),
3573
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { children: tasks.map((task) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3574
- TaskCard,
3575
- {
3576
- task,
3577
- tasksById,
3578
- directory,
3579
- execution: delegations.find((item) => item.taskId === task.id && (item.status === "queued" || item.status === "running")),
3580
- open: () => setSelectedTaskId(task.id)
3581
- },
3582
- task.id
3583
- )) }),
3584
- tasks.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { children: "\u6682\u65E0\u4EFB\u52A1" })
3585
- ] }, column.id);
3586
- }) })
3650
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "dsh-partner-board-assignee", children: [
3651
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "sr-only", children: "\u6309\u8D1F\u8D23\u4EBA\u7B5B\u9009" }),
3652
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("select", { value: assigneeFilter, onChange: (event) => setAssigneeFilter(event.target.value), children: [
3653
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "all", children: "\u5168\u90E8\u4F19\u4F34" }),
3654
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "unassigned", children: "\u672A\u6307\u6D3E" }),
3655
+ directory.map((item) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("option", { value: item.id, children: [
3656
+ "@",
3657
+ item.name
3658
+ ] }, item.id))
3659
+ ] })
3660
+ ] }),
3661
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("small", { "aria-live": "polite", children: [
3662
+ "\u663E\u793A ",
3663
+ visibleTaskCount,
3664
+ " / ",
3665
+ board.tasks.length
3666
+ ] })
3667
+ ] }),
3668
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("nav", { className: "dsh-partner-board-statuses", "aria-label": "\u6309\u4EFB\u52A1\u72B6\u6001\u7B5B\u9009", children: [
3669
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { type: "button", className: statusFilter === "all" ? "is-active" : "", "aria-pressed": statusFilter === "all", onClick: () => setStatusFilter("all"), children: [
3670
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "\u5168\u90E8" }),
3671
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("b", { children: scopedTasks.length })
3672
+ ] }),
3673
+ COLUMNS.map((column) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { type: "button", className: statusFilter === column.id ? "is-active" : "", "aria-pressed": statusFilter === column.id, onClick: () => setStatusFilter(column.id), children: [
3674
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: column.label }),
3675
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("b", { children: statusCounts.get(column.id) ?? 0 })
3676
+ ] }, column.id))
3677
+ ] }),
3678
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dsh-partner-board", "data-focused": statusFilter !== "all", "aria-label": "\u4EFB\u52A1\u770B\u677F", children: visibleColumns.map((column) => {
3679
+ const tasks = tasksByStatus.get(column.id) ?? [];
3680
+ const columnTitleId = `dsh-partner-board-${column.id}`;
3681
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { "data-status": column.id, "data-empty": tasks.length === 0, "aria-labelledby": columnTitleId, children: [
3682
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { children: [
3683
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { id: columnTitleId, children: column.label }),
3684
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("b", { children: tasks.length })
3685
+ ] }),
3686
+ tasks.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dsh-partner-board-column-list", children: tasks.map((task) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3687
+ TaskCard,
3688
+ {
3689
+ task,
3690
+ tasksById,
3691
+ directoryById,
3692
+ dependentCount: dependentsById.get(task.id) ?? 0,
3693
+ execution: activeDelegationByTaskId.get(task.id),
3694
+ open: () => setSelectedTaskId(task.id)
3695
+ },
3696
+ task.id
3697
+ )) }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { children: query || assigneeFilter !== "all" ? "\u6CA1\u6709\u5339\u914D\u4EFB\u52A1" : "\u6682\u65E0\u4EFB\u52A1" })
3698
+ ] }, column.id);
3699
+ }) })
3700
+ ] })
3587
3701
  ] });
3588
3702
  }
3589
- function TaskCard({ task, tasksById, directory, execution, open }) {
3703
+ function TaskCard({ task, tasksById, directoryById, dependentCount, execution, open }) {
3590
3704
  const dependencies = task.dependencyTaskIds.map((id) => tasksById.get(id)).filter((item) => item !== void 0);
3591
3705
  const blockers = dependencies.filter((item) => item.status !== "done");
3592
- const assignee = directory.find((item) => item.id === task.assigneeCompanionId);
3706
+ const completedDependencies = dependencies.length - blockers.length;
3707
+ const assignee = directoryById.get(task.assigneeCompanionId ?? "");
3593
3708
  const executionState = execution ? delegationState(execution) : void 0;
3594
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("article", { className: "dsh-partner-task-card", "data-blocked": blockers.length > 0, children: [
3595
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: `dsh-partner-priority is-${task.priority}` }),
3596
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { type: "button", className: "dsh-partner-task-summary", "aria-haspopup": "dialog", onClick: open, children: [
3597
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { children: [
3709
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("article", { className: "dsh-partner-task-card", "data-blocked": blockers.length > 0, "data-priority": task.priority, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { type: "button", className: "dsh-partner-task-summary", "aria-haspopup": "dialog", onClick: open, children: [
3710
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { children: [
3711
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "dsh-partner-task-card-title", children: [
3598
3712
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { title: task.title, children: task.title }),
3599
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("small", { children: [
3600
- assignee ? `@${assignee.name}` : "\u672A\u6307\u6D3E",
3601
- " \xB7 ",
3602
- dependencies.length ? `${dependencies.length} \u9879\u524D\u7F6E${blockers.length ? `\uFF0C${blockers.length} \u9879\u672A\u5B8C\u6210` : "\u5747\u5DF2\u5B8C\u6210"}` : "\u65E0\u524D\u7F6E\u4F9D\u8D56",
3603
- task.resultSummary ? " \xB7 \u5DF2\u6709\u7ED3\u679C" : "",
3604
- executionState ? ` \xB7 ${executionState.label}` : ""
3605
- ] })
3713
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("em", { children: priorityLabel(task.priority) })
3606
3714
  ] }),
3607
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives3.IconChevronRightOutline14, { size: 14 })
3608
- ] })
3609
- ] });
3715
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("small", { className: "dsh-partner-task-card-owner", children: [
3716
+ assignee ? `@${assignee.name}` : "\u672A\u6307\u6D3E",
3717
+ task.resultSummary ? " \xB7 \u5DF2\u6709\u7ED3\u679C" : "",
3718
+ executionState ? ` \xB7 ${executionState.label}` : ""
3719
+ ] }),
3720
+ (dependencies.length > 0 || dependentCount > 0) && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "dsh-partner-task-relations", children: [
3721
+ dependencies.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("small", { "data-blocked": blockers.length > 0, children: [
3722
+ "\u524D\u7F6E ",
3723
+ completedDependencies,
3724
+ "/",
3725
+ dependencies.length
3726
+ ] }),
3727
+ dependentCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("small", { children: [
3728
+ "\u5B8C\u6210\u540E\u89E3\u9501 ",
3729
+ dependentCount
3730
+ ] })
3731
+ ] })
3732
+ ] }),
3733
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives3.IconChevronRightOutline14, { size: 14 })
3734
+ ] }) });
3610
3735
  }
3611
3736
  function TaskDetail({ task, tasks, activities, directory, execution, busy, update, delegate, review, accept, reject, remove }) {
3612
3737
  const [rejecting, setRejecting] = (0, import_react6.useState)(false);