@allbluecn/web-app 0.18.2 → 0.19.0
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/package.json +66 -51
- package/src/__tests__/components/auth/auth-layout.test.tsx +13 -1
- package/src/__tests__/{knowledge-public → knowledge/public}/canonical-id.test.ts +1 -1
- package/src/__tests__/{knowledge-public → knowledge/public}/favicon.test.ts +1 -1
- package/src/__tests__/{knowledge-public → knowledge/public}/github-sync.test.ts +1 -1
- package/src/__tests__/{knowledge-public → knowledge/public}/share-merge.test.ts +7 -7
- package/src/__tests__/security/xss-sanitize.test.ts +9 -8
- package/src/components/ai/__tests__/chat-thread-id-stability.test.tsx +125 -0
- package/src/components/ai/ai-chat-prompt.tsx +8 -2
- package/src/components/ai/ai-prompt-input/index.tsx +2 -1
- package/src/components/ai/global-harness-sidebar/__tests__/global-ai-prompts.test.ts +1 -2
- package/src/components/ai/global-harness-sidebar/index.tsx +22 -10
- package/src/components/bug/__tests__/board-subgroups.test.tsx +512 -0
- package/src/components/bug/__tests__/board-view.test.tsx +350 -0
- package/src/components/bug/__tests__/bug-list-loading-defer.test.tsx +85 -0
- package/src/components/bug/__tests__/bug-toolbar.test.tsx +7 -1
- package/src/components/bug/__tests__/comment-reactions.test.tsx +182 -0
- package/src/components/bug/__tests__/date-and-lightbox.test.tsx +96 -0
- package/src/components/bug/__tests__/export-entry.test.tsx +217 -0
- package/src/components/bug/__tests__/filters-compat.test.tsx +157 -0
- package/src/components/bug/__tests__/fix-request-race.test.tsx +396 -0
- package/src/components/bug/__tests__/peek-modes.test.tsx +365 -0
- package/src/components/bug/__tests__/saved-views.test.tsx +309 -0
- package/src/components/bug/__tests__/story-bugs-panel.test.tsx +146 -0
- package/src/components/bug/__tests__/subgroup-header.test.tsx +150 -0
- package/src/components/bug/__tests__/toolbar-shell.test.tsx +369 -0
- package/src/components/bug/__tests__/use-paged-bug-groups.test.tsx +58 -0
- package/src/components/bug/__tests__/view-type.test.tsx +247 -0
- package/src/components/bug/bug-list-view.tsx +310 -13
- package/src/components/bug/bug-panel-header.tsx +84 -8
- package/src/components/bug/bug-toolbar.tsx +268 -116
- package/src/components/bug/create-bug-dialog.tsx +1 -1
- package/src/components/bug/detail/__tests__/activity-timeline.test.tsx +1 -0
- package/src/components/bug/detail/__tests__/bug-detail-collab.test.tsx +236 -0
- package/src/components/bug/detail/__tests__/repro-report-card.test.tsx +2 -1
- package/src/components/bug/detail/activity-timeline.tsx +1 -1
- package/src/components/bug/detail/bug-detail-body.tsx +316 -18
- package/src/components/bug/detail/comment-item.tsx +7 -2
- package/src/components/bug/detail/comment-reactions.tsx +138 -0
- package/src/components/bug/detail/error-context.tsx +29 -9
- package/src/components/bug/detail/props-section.tsx +31 -3
- package/src/components/bug/detail/repro-report-card.tsx +1 -1
- package/src/components/bug/display/constants.ts +4 -2
- package/src/components/bug/display/display-dropdown.tsx +76 -280
- package/src/components/bug/display/types.ts +24 -8
- package/src/components/bug/display/use-paged-bug-groups.ts +183 -32
- package/src/components/bug/filters/{filter-value-input.tsx → field-configs.tsx} +218 -106
- package/src/components/bug/filters/index.tsx +14 -5
- package/src/components/bug/inline-editors/assignee-editor.tsx +2 -2
- package/src/components/bug/inline-editors/labels-editor.tsx +1 -1
- package/src/components/bug/inline-editors/severity-editor.tsx +37 -18
- package/src/components/bug/inline-editors/state-editor.tsx +1 -1
- package/src/components/bug/peek-panel.tsx +153 -35
- package/src/components/bug/select-bug-dialog.tsx +500 -0
- package/src/components/bug/story-bugs-panel.tsx +1090 -0
- package/src/components/bug/types.ts +9 -2
- package/src/components/bug/views/board-view.tsx +661 -0
- package/src/components/bug/views/bug-list/batch-toolbar.tsx +25 -34
- package/src/components/bug/views/bug-list/group.tsx +28 -13
- package/src/components/bug/views/bug-list/index.tsx +223 -59
- package/src/components/bug/views/bug-list/row.tsx +7 -1
- package/src/components/bug/views/create-view-dialog.tsx +160 -0
- package/src/components/bug/views/view-list-section.tsx +140 -0
- package/src/components/bug/views/view-selector-button.tsx +145 -0
- package/src/components/bug/views/view-switcher.tsx +8 -6
- package/src/components/bug/views/view-types.ts +162 -0
- package/src/components/collab/__tests__/activity-attribution.test.tsx +211 -0
- package/src/components/collab/__tests__/canvas-collab-panel.test.tsx +118 -0
- package/src/components/collab/__tests__/collab-presence-header.test.tsx +335 -0
- package/src/components/collab/__tests__/entity-presence-badge.test.tsx +226 -0
- package/src/components/collab/activity-attribution.tsx +221 -0
- package/src/components/collab/canvas-collab-panel.tsx +104 -0
- package/src/components/collab/collab-presence-header.tsx +220 -0
- package/src/components/collab/entity-presence-badge.tsx +130 -0
- package/src/components/collab/field-editing-pill.tsx +137 -0
- package/src/components/command/command-palette.tsx +6 -6
- package/src/components/design/canvas/document/__tests__/canvas-tree-fixture-snapshot.ts +589 -0
- package/src/components/design/canvas/document/__tests__/canvas-tree-reconcile.test.ts +159 -0
- package/src/components/design/canvas/panels/toolbar.tsx +3 -2
- package/src/components/design/canvas/plugins/presence/__tests__/canvas-collab-wiring.test.tsx +660 -0
- package/src/components/design/canvas/plugins/presence/__tests__/layout.test.ts +292 -0
- package/src/components/design/canvas/plugins/presence/__tests__/presence-overlay.test.tsx +139 -0
- package/src/components/design/canvas/plugins/presence/layout.ts +222 -0
- package/src/components/design/canvas/plugins/presence/presence-layer.tsx +353 -0
- package/src/components/design/canvas/plugins/presence/presence-overlay.tsx +155 -0
- package/src/components/design/canvas/plugins/presence/viewer-badge.tsx +80 -0
- package/src/components/design/canvas/react/__tests__/hooks.test.tsx +4 -4
- package/src/components/design/editor/collaboration/__tests__/design-agent-panel-regenerate.test.tsx +3 -1
- package/src/components/design/editor/collaboration/__tests__/design-agent-panel-stream.test.tsx +3 -1
- package/src/components/design/editor/collaboration/design-agent-panel.tsx +3 -0
- package/src/components/design/editor/collaboration/design-comment-review-panel.tsx +5 -5
- package/src/components/design/editor/dashboard/create-design-dialog.tsx +1 -1
- package/src/components/design/editor/dashboard/design-dashboard.tsx +1 -10
- package/src/components/design/editor/layout/__tests__/collab-param-wiring.test.tsx +153 -0
- package/src/components/design/editor/layout/__tests__/no-page-save-toast.test.tsx +8 -0
- package/src/components/design/editor/layout/design-editor-layout.tsx +28 -1
- package/src/components/design/editor/layout/design-navigation.tsx +0 -4
- package/src/components/design/editor/layout/hooks/__tests__/use-design-auto-save-collab.test.tsx +130 -0
- package/src/components/design/editor/layout/hooks/use-design-auto-save.ts +18 -1
- package/src/components/design/editor/share/share-comment-panel.tsx +37 -20
- package/src/components/design/editor/share/share-layout.tsx +3 -0
- package/src/components/design/editor/share/share-nav-bar.tsx +7 -1
- package/src/components/design/editor/share/share-theme-toggle.tsx +10 -15
- package/src/components/design/editor/tiptap/node/paragraph-node/paragraph-node.scss +1 -1
- package/src/components/harness/__tests__/composer-draft.test.ts +126 -0
- package/src/components/harness/composer/composer-editor.tsx +64 -6
- package/src/components/harness/composer/harness-composer.tsx +1 -1
- package/src/components/harness/harness-layout.tsx +1 -1
- package/src/components/harness/harness-workbench-page.tsx +6 -1
- package/src/components/harness/turn-group.tsx +1 -1
- package/src/components/hotkeys/shortcut-badge.tsx +4 -4
- package/src/components/knowledge/dialog/knowledge-form-dialog.tsx +1 -1
- package/src/components/knowledge/editor/__tests__/knowledge-doc-editor-collab.test.tsx +542 -0
- package/src/components/knowledge/editor/doc-header.tsx +7 -49
- package/src/components/knowledge/editor/knowledge-doc-editor.tsx +264 -51
- package/src/components/knowledge/editor/mindmap-doc-editor.tsx +3 -19
- package/src/components/knowledge/knowledge-homepage.tsx +3 -3
- package/src/components/knowledge/knowledge-toolbar.tsx +8 -8
- package/src/components/{knowledge-public → knowledge/public}/bookmark-form-dialog.tsx +4 -4
- package/src/components/{knowledge-public → knowledge/public}/knowledge-card.tsx +1 -15
- package/src/components/{knowledge-public → knowledge/public}/knowledge-form-dialog.tsx +9 -9
- package/src/components/{knowledge-public → knowledge/public}/legal-compliance-editor.tsx +35 -28
- package/src/components/{knowledge-public → knowledge/public}/sharers-avatar-group.tsx +3 -2
- package/src/components/layout/layout-responsive-provider.tsx +79 -0
- package/src/components/layout/sidebar-03/__tests__/presence-avatar-stack.test.tsx +148 -0
- package/src/components/layout/sidebar-03/app-sidebar.tsx +9 -3
- package/src/components/layout/sidebar-03/index.tsx +19 -4
- package/src/components/layout/sidebar-03/nav-main.tsx +28 -10
- package/src/components/layout/sidebar-03/presence-avatar-stack.tsx +112 -0
- package/src/components/layout/sidebar-03/user-menu.tsx +3 -3
- package/src/components/project/create-project-dialog.tsx +1 -1
- package/src/components/project/invite-member-dialog.tsx +1 -1
- package/src/components/project/project-activity-list.tsx +2 -2
- package/src/components/project/project-member-manager.tsx +2 -2
- package/src/components/reui/__tests__/kanban-drop-indicator.test.ts +88 -0
- package/src/components/reui/__tests__/kanban-keyboard.test.ts +262 -0
- package/src/components/reui/event-calendar/event-calendar-agenda-view.tsx +236 -0
- package/src/components/reui/event-calendar/event-calendar-content.tsx +80 -0
- package/src/components/reui/event-calendar/event-calendar-dnd.tsx +1062 -0
- package/src/components/reui/event-calendar/event-calendar-event.tsx +555 -0
- package/src/components/reui/event-calendar/event-calendar-i18n.tsx +291 -0
- package/src/components/reui/event-calendar/event-calendar-lib.tsx +677 -0
- package/src/components/reui/event-calendar/event-calendar-month-view.tsx +1287 -0
- package/src/components/reui/event-calendar/event-calendar-nav.tsx +615 -0
- package/src/components/reui/event-calendar/event-calendar-recurrence.tsx +592 -0
- package/src/components/reui/event-calendar/event-calendar-resource-view.tsx +810 -0
- package/src/components/reui/event-calendar/event-calendar-time-grid.tsx +1366 -0
- package/src/components/reui/event-calendar/event-calendar-types.tsx +240 -0
- package/src/components/reui/event-calendar/event-calendar.tsx +1916 -0
- package/src/components/reui/gantt/__tests__/gantt-row-window.test.ts +243 -0
- package/src/components/reui/gantt/__tests__/gantt-view-virtualize.test.tsx +243 -0
- package/src/components/reui/gantt/gantt-bar.tsx +439 -0
- package/src/components/reui/gantt/gantt-dnd.tsx +1000 -0
- package/src/components/reui/gantt/gantt-i18n.tsx +287 -0
- package/src/components/reui/gantt/gantt-lib.tsx +695 -0
- package/src/components/reui/gantt/gantt-nav.tsx +446 -0
- package/src/components/reui/gantt/gantt-recurrence.tsx +402 -0
- package/src/components/reui/gantt/gantt-row-window.ts +119 -0
- package/src/components/reui/gantt/gantt-types.tsx +283 -0
- package/src/components/reui/gantt/gantt-view.tsx +4466 -0
- package/src/components/reui/gantt/gantt.tsx +1822 -0
- package/src/components/reui/gantt/use-gantt-row-window.ts +159 -0
- package/src/components/reui/icon-stack.tsx +90 -0
- package/src/components/reui/kanban-keyboard.ts +268 -0
- package/src/components/reui/kanban.tsx +1227 -0
- package/src/components/settings/personal-team/account/account-client.tsx +3 -2
- package/src/components/settings/personal-team/team/invitation-cards/invitation-history-list.tsx +5 -5
- package/src/components/settings/personal-team/team/team-client.tsx +2 -1
- package/src/components/settings/personal-team/team/team-member-list.tsx +4 -4
- package/src/components/share/share-presence-bar.tsx +182 -0
- package/src/components/shared-kit/auth/auth-client.ts +5 -0
- package/src/components/shared-kit/avatars/__tests__/avatar-shape.test.ts +44 -0
- package/src/components/shared-kit/avatars/__tests__/user-avatar.test.tsx +46 -0
- package/src/components/{tags/tags-collection.ts → shared-kit/avatars/avatar-shape.ts} +14 -20
- package/src/components/shared-kit/avatars/notion-avatar.tsx +62 -11
- package/src/components/shared-kit/avatars/user-avatar.tsx +7 -4
- package/src/components/shared-kit/list-kit/__tests__/batch-toolbar-shell.test.tsx +133 -0
- package/src/components/shared-kit/list-kit/__tests__/frozen-header.test.ts +89 -0
- package/src/components/shared-kit/list-kit/__tests__/level-badge.test.tsx +85 -0
- package/src/components/shared-kit/list-kit/__tests__/toolbar-shell.test.tsx +178 -0
- package/src/components/shared-kit/list-kit/batch-toolbar-shell.tsx +111 -0
- package/src/components/shared-kit/list-kit/csv-download.ts +46 -0
- package/src/components/shared-kit/list-kit/display/__tests__/dropdown.test.tsx +215 -0
- package/src/components/shared-kit/list-kit/display/dropdown.tsx +582 -0
- package/src/components/shared-kit/list-kit/display/types.ts +64 -0
- package/src/components/shared-kit/list-kit/display/values.ts +60 -0
- package/src/components/shared-kit/list-kit/filters/__tests__/create-filters-module.test.tsx +181 -0
- package/src/components/shared-kit/list-kit/filters/__tests__/types.test.ts +133 -0
- package/src/components/shared-kit/list-kit/filters/index.tsx +757 -0
- package/src/components/shared-kit/list-kit/filters/types.ts +68 -0
- package/src/components/shared-kit/list-kit/frozen-header.ts +45 -0
- package/src/components/shared-kit/list-kit/icon-semantics.ts +50 -0
- package/src/components/shared-kit/list-kit/kanban/__tests__/drop-layout.test.ts +139 -0
- package/src/components/shared-kit/list-kit/kanban/__tests__/frozen-header.test.ts +111 -0
- package/src/components/shared-kit/list-kit/kanban/__tests__/instance-key.test.ts +130 -0
- package/src/components/shared-kit/list-kit/kanban/__tests__/kanban-board-view.test.tsx +901 -0
- package/src/components/shared-kit/list-kit/kanban/__tests__/manual-order.test.ts +35 -0
- package/src/components/shared-kit/list-kit/kanban/drop-commit.ts +212 -0
- package/src/components/shared-kit/list-kit/kanban/drop-layout.ts +98 -0
- package/src/components/shared-kit/list-kit/kanban/frozen-header.ts +88 -0
- package/src/components/shared-kit/list-kit/kanban/instance-key.ts +83 -0
- package/src/components/shared-kit/list-kit/kanban/kanban-board-view.tsx +1414 -0
- package/src/components/shared-kit/list-kit/kanban/manual-order.ts +39 -0
- package/src/components/shared-kit/list-kit/level-badge.tsx +71 -0
- package/src/components/shared-kit/list-kit/toolbar-shell.tsx +103 -0
- package/src/components/shared-kit/loading/__tests__/use-deferred-flag.test.tsx +115 -0
- package/src/components/shared-kit/loading/use-deferred-flag.ts +35 -0
- package/src/components/shared-kit/peek/dock-slot.ts +62 -0
- package/src/components/shared-kit/peek/peek-mode.ts +34 -0
- package/src/components/shared-kit/theme/animated-theme-toggler.tsx +13 -7
- package/src/components/shared-kit/theme/theme-toggle.tsx +7 -18
- package/src/components/shared-kit/views/view-icon.tsx +49 -0
- package/src/components/story/__tests__/peek-panel-patch-sync.test.tsx +215 -0
- package/src/components/story/__tests__/story-list-loading-defer.test.tsx +88 -0
- package/src/components/story/__tests__/story-list-view-peek-sync.test.tsx +242 -0
- package/src/components/story/__tests__/story-list-view-restore.test.tsx +45 -3
- package/src/components/story/__tests__/story-list-view-ssr.test.tsx +0 -1
- package/src/components/story/ai/__tests__/action-registry.test.ts +11 -11
- package/src/components/story/ai/action-registry.ts +5 -7
- package/src/components/story/ai/handlers/stream-text.ts +1 -3
- package/src/components/story/ai/story-ai-toolbar.tsx +58 -16
- package/src/components/story/ai/use-toolbar-overflow.ts +4 -7
- package/src/components/story/columns.tsx +2 -2
- package/src/components/story/constants.ts +17 -1
- package/src/components/story/create-story-dialog.tsx +8 -7
- package/src/components/story/detail/__tests__/associated-attachments-panel.test.tsx +38 -4
- package/src/components/story/detail/__tests__/categories.test.tsx +52 -26
- package/src/components/story/detail/__tests__/story-collab.test.tsx +897 -0
- package/src/components/story/detail/activity-tabs.tsx +5 -4
- package/src/components/story/detail/activity-timeline.tsx +15 -3
- package/src/components/story/detail/comment-input.tsx +2 -2
- package/src/components/story/detail/comment-item.tsx +6 -3
- package/src/components/story/detail/comment-thread.tsx +1 -0
- package/src/components/story/detail/reaction-bar.tsx +1 -1
- package/src/components/story/detail/story-detail-body.tsx +501 -76
- package/src/components/story/detail/story-detail-toolbar/__tests__/related-test-cases.test.tsx +173 -10
- package/src/components/story/detail/story-detail-toolbar/associated-attachments-panel.tsx +144 -8
- package/src/components/story/detail/story-detail-toolbar/categories.tsx +82 -38
- package/src/components/story/detail/story-detail-toolbar/children.tsx +254 -174
- package/src/components/story/detail/story-detail-toolbar/dependency-panel.tsx +140 -58
- package/src/components/story/detail/story-detail-toolbar/index.tsx +613 -0
- package/src/components/story/detail/story-detail-toolbar/related-test-cases.tsx +1010 -87
- package/src/components/story/detail/story-detail-toolbar/scroll-hint.tsx +57 -0
- package/src/components/story/detail/story-detail-toolbar/use-panel-frozen-groups.ts +97 -0
- package/src/components/story/detail/story-properties.tsx +9 -5
- package/src/components/story/display/__tests__/display-dropdown-helpers.test.ts +17 -1
- package/src/components/story/display/__tests__/display-dropdown.test.tsx +9 -0
- package/src/components/story/display/__tests__/flatten-story-groups.test.ts +42 -0
- package/src/components/story/display/__tests__/group-fields.test.ts +81 -1
- package/src/components/story/display/__tests__/group-resolver.test.ts +153 -1
- package/src/components/story/display/__tests__/use-collapsed-subgroups.test.ts +158 -0
- package/src/components/story/display/__tests__/use-display-options.test.ts +32 -3
- package/src/components/story/display/__tests__/use-fit-count.test.ts +198 -0
- package/src/components/story/display/__tests__/use-paged-story-groups.test.ts +77 -3
- package/src/components/story/display/constants.ts +23 -2
- package/src/components/story/display/display-dropdown.tsx +95 -397
- package/src/components/story/display/flatten-story-groups.ts +39 -0
- package/src/components/story/display/group-fields.ts +32 -1
- package/src/components/story/display/group-resolver.tsx +128 -5
- package/src/components/story/display/types.ts +23 -42
- package/src/components/story/display/use-collapsed-subgroups.ts +109 -0
- package/src/components/story/display/use-display-options.ts +21 -5
- package/src/components/story/display/use-fit-count.ts +124 -0
- package/src/components/story/display/use-paged-story-groups.ts +174 -31
- package/src/components/story/filters/field-configs.tsx +263 -0
- package/src/components/story/filters/index.tsx +14 -5
- package/src/components/story/inline-editors/__tests__/labels-editor.test.tsx +2 -0
- package/src/components/story/inline-editors/__tests__/priority-editor.test.tsx +15 -0
- package/src/components/story/inline-editors/assignee-editor.tsx +7 -5
- package/src/components/story/inline-editors/date-editor.tsx +7 -2
- package/src/components/story/inline-editors/inline-trigger.tsx +17 -4
- package/src/components/story/inline-editors/labels-editor.tsx +243 -35
- package/src/components/story/inline-editors/parent-story-editor.tsx +1 -1
- package/src/components/story/inline-editors/priority-editor.tsx +6 -4
- package/src/components/story/inline-editors/state-editor.tsx +6 -4
- package/src/components/story/inline-editors/story-select-dialog.tsx +56 -19
- package/src/components/story/peek-panel.tsx +234 -51
- package/src/components/story/relations/__tests__/design-select-dialog.test.tsx +131 -0
- package/src/components/story/relations/attachment-manage-dialog.tsx +1 -1
- package/src/components/story/relations/design-select-dialog.tsx +285 -0
- package/src/components/story/relations/knowledge-select-dialog.tsx +3 -3
- package/src/components/story/relations/link-manage-dialog.tsx +2 -2
- package/src/components/story/story-list-view.tsx +175 -17
- package/src/components/story/story-panel-header.tsx +18 -11
- package/src/components/story/story-toolbar.tsx +177 -126
- package/src/components/story/transfer-story-popover.tsx +1 -1
- package/src/components/story/types.ts +11 -2
- package/src/components/story/views/__tests__/calendar-view.test.tsx +262 -0
- package/src/components/story/views/__tests__/kanban-drop-subgroup.test.ts +68 -0
- package/src/components/story/views/__tests__/kanban-peek-sync.test.tsx +184 -0
- package/src/components/story/views/__tests__/kanban-view-membership-sync.test.tsx +179 -0
- package/src/components/story/views/__tests__/timeline-view.test.tsx +453 -0
- package/src/components/story/views/__tests__/view-icon.test.tsx +45 -0
- package/src/components/story/views/__tests__/view-types.test.ts +0 -8
- package/src/components/story/views/calendar/__tests__/mappers.test.ts +201 -0
- package/src/components/story/views/calendar/__tests__/slot-draft.test.ts +78 -0
- package/src/components/story/views/calendar/drag-blocked.ts +41 -0
- package/src/components/story/views/calendar/i18n.ts +91 -0
- package/src/components/story/views/calendar/mappers.ts +119 -0
- package/src/components/story/views/calendar/slot-draft.ts +48 -0
- package/src/components/story/views/calendar-view.tsx +490 -223
- package/src/components/story/views/create-view-dialog.tsx +6 -6
- package/src/components/story/views/kanban-view.tsx +618 -0
- package/src/components/story/views/{__tests__ → story-list/__tests__}/use-flat-rows.test.ts +1 -1
- package/src/components/story/views/story-list/batch-preview-dialog.tsx +3 -3
- package/src/components/story/views/story-list/batch-toolbar.tsx +17 -34
- package/src/components/story/views/story-list/group.tsx +4 -2
- package/src/components/story/views/story-list/index.tsx +142 -34
- package/src/components/story/views/story-list/row.tsx +4 -0
- package/src/components/story/views/{use-flat-rows.ts → story-list/use-flat-rows.ts} +2 -2
- package/src/components/story/views/timeline/__tests__/mappers.test.ts +742 -0
- package/src/components/story/views/timeline/__tests__/sentinel-geometry.test.ts +76 -0
- package/src/components/story/views/timeline/__tests__/use-date-commit.test.tsx +372 -0
- package/src/components/story/views/timeline/i18n.ts +96 -0
- package/src/components/story/views/timeline/mappers.ts +506 -0
- package/src/components/story/views/timeline/sentinel-geometry.ts +43 -0
- package/src/components/story/views/timeline/use-date-commit.ts +169 -0
- package/src/components/story/views/timeline-view.tsx +593 -222
- package/src/components/story/views/view-list-section.tsx +4 -4
- package/src/components/story/views/view-selector-button.tsx +9 -10
- package/src/components/story/views/view-switcher.tsx +7 -1
- package/src/components/story/views/view-types.ts +1 -5
- package/src/components/testcase/__tests__/batch-toolbar.test.tsx +245 -0
- package/src/components/testcase/__tests__/board-view.test.tsx +241 -0
- package/src/components/testcase/__tests__/case-row.test.tsx +24 -10
- package/src/components/testcase/__tests__/constants.test.ts +151 -0
- package/src/components/testcase/__tests__/create-dialog-scope.test.tsx +173 -0
- package/src/components/testcase/__tests__/detail-properties.test.tsx +19 -0
- package/src/components/testcase/__tests__/display-options.test.tsx +154 -0
- package/src/components/testcase/__tests__/export-entry.test.tsx +279 -0
- package/src/components/testcase/__tests__/filters.test.tsx +280 -0
- package/src/components/testcase/__tests__/list-view-scope.test.tsx +290 -0
- package/src/components/testcase/__tests__/list-view.test.tsx +552 -7
- package/src/components/testcase/__tests__/manual-move.test.ts +69 -0
- package/src/components/testcase/__tests__/peek-panel.test.tsx +89 -8
- package/src/components/testcase/__tests__/toolbar.test.tsx +302 -0
- package/src/components/testcase/__tests__/view-fallback.test.tsx +272 -0
- package/src/components/testcase/__tests__/view-management.test.tsx +179 -0
- package/src/components/testcase/ai/generate-dialog.tsx +1 -1
- package/src/components/testcase/constants.ts +83 -0
- package/src/components/testcase/create-testcase-dialog.tsx +76 -8
- package/src/components/testcase/detail/__tests__/select-cases-dialog.test.tsx +163 -0
- package/src/components/testcase/detail/case-detail-body.tsx +311 -30
- package/src/components/testcase/detail/select-cases-dialog.tsx +465 -0
- package/src/components/testcase/detail/story-link-editor.tsx +1 -1
- package/src/components/testcase/display/display-dropdown.tsx +147 -0
- package/src/components/testcase/display/field-configs.ts +80 -0
- package/src/components/testcase/display/use-testcase-display-options.ts +59 -0
- package/src/components/testcase/filters/field-configs.tsx +748 -0
- package/src/components/testcase/filters/index.tsx +35 -127
- package/src/components/testcase/inline-editors/assignee-editor.tsx +6 -6
- package/src/components/testcase/inline-editors/folder-editor.tsx +9 -9
- package/src/components/testcase/inline-editors/priority-editor.tsx +47 -31
- package/src/components/testcase/inline-editors/state-editor.tsx +14 -12
- package/src/components/testcase/inline-editors/type-editor.tsx +31 -20
- package/src/components/testcase/list/case-row.tsx +60 -2
- package/src/components/testcase/list/grouped-list.tsx +3 -2
- package/src/components/testcase/list-view.tsx +633 -137
- package/src/components/testcase/peek-panel.tsx +69 -11
- package/src/components/testcase/plans/plan-list.tsx +6 -1
- package/src/components/testcase/step-editor.tsx +34 -3
- package/src/components/testcase/testcase-toolbar.tsx +349 -94
- package/src/components/testcase/views/batch-toolbar.tsx +203 -0
- package/src/components/testcase/views/board-view.tsx +546 -0
- package/src/components/testcase/views/create-view-dialog.tsx +26 -14
- package/src/components/testcase/views/move.ts +56 -0
- package/src/components/testcase/views/view-selector-button.tsx +82 -30
- package/src/components/testcase/views/view-switcher.tsx +12 -5
- package/src/components/testcase/views/view-types.ts +50 -27
- package/src/components/tiptap/mindmap/lib/__tests__/shortcuts.test.ts +5 -4
- package/src/components/tiptap/mindmap/lib/shortcuts.ts +4 -3
- package/src/components/tiptap/node/doc-card-node-view.tsx +2 -1
- package/src/components/tiptap/notion-like/editor-extensions.ts +231 -0
- package/src/components/tiptap/notion-like/notion-like-editor.tsx +29 -156
- package/src/components/tiptap/ui/ai-menu/ai-menu.tsx +6 -1
- package/src/components/tiptap/ui/doc-reference-interaction/doc-reference-interaction.tsx +2 -1
- package/src/components/ui/checkbox.tsx +4 -4
- package/src/components/ui/popover.tsx +1 -1
- package/src/components/workspace/dialogs/edit-workspace-dialog.tsx +1 -1
- package/src/components/workspace/kb/workspace-kb-manage-dialog.tsx +1 -1
- package/src/components/workspace/kb/workspace-quick-doc-dialog.tsx +1 -1
- package/src/components/workspace/members/workspace-member-item.tsx +2 -2
- package/src/components/workspace/members/workspace-members-manager.tsx +2 -2
- package/src/config/sidebar-routes.tsx +11 -13
- package/src/design-engine/document/serialize-leafer-json.ts +2 -1
- package/src/design-engine/engine/__tests__/engine-split.test.ts +1 -1
- package/src/design-engine/engine/__tests__/engine.test.ts +20 -0
- package/src/design-engine/engine/app.ts +5 -0
- package/src/design-engine/engine/engine-base.ts +17 -0
- package/src/design-engine/engine/engine-doc.ts +32 -0
- package/src/hooks/__tests__/use-commands.test.tsx +17 -5
- package/src/hooks/use-commands.ts +4 -4
- package/src/hooks/use-toolbar-search.ts +7 -2
- package/src/lib/__tests__/datetime-local.test.ts +46 -0
- package/src/lib/__tests__/datetime.test.ts +7 -0
- package/src/lib/__tests__/layout-responsive.test.ts +123 -0
- package/src/lib/__tests__/sidebar-utils.test.ts +4 -4
- package/src/lib/ai/story-ai-stream.ts +1 -1
- package/src/lib/ai/use-selected-model.ts +15 -5
- package/src/lib/changelog/sdk-versions.ts +22 -22
- package/src/lib/collab/__tests__/bindings-fields.test.ts +496 -0
- package/src/lib/collab/__tests__/bindings-steps.test.ts +332 -0
- package/src/lib/collab/__tests__/presence-store.test.ts +414 -0
- package/src/lib/collab/__tests__/provider-handle-contract.test.ts +89 -0
- package/src/lib/collab/__tests__/provider.test.ts +504 -0
- package/src/lib/collab/__tests__/use-presence-list-refresh.test.tsx +309 -0
- package/src/lib/collab/__tests__/use-presence-report.test.ts +356 -0
- package/src/lib/collab/__tests__/use-share-presence.test.ts +555 -0
- package/src/lib/collab/__tests__/user-color.test.ts +53 -0
- package/src/lib/collab/bindings/__tests__/canvas-local.test.ts +583 -0
- package/src/lib/collab/bindings/__tests__/canvas-presence.test.ts +378 -0
- package/src/lib/collab/bindings/__tests__/canvas-remote.test.ts +454 -0
- package/src/lib/collab/bindings/__tests__/canvas-tree-perf.test.ts +134 -0
- package/src/lib/collab/bindings/canvas-local.ts +415 -0
- package/src/lib/collab/bindings/canvas-presence.ts +420 -0
- package/src/lib/collab/bindings/canvas-remote.ts +226 -0
- package/src/lib/collab/bindings/fields.ts +463 -0
- package/src/lib/collab/bindings/steps.ts +332 -0
- package/src/lib/collab/env.ts +33 -0
- package/src/lib/collab/module-map.ts +131 -0
- package/src/lib/collab/presence-store.ts +350 -0
- package/src/lib/collab/provider.ts +378 -0
- package/src/lib/collab/use-collab-doc.ts +100 -0
- package/src/lib/collab/use-presence-list-refresh.ts +142 -0
- package/src/lib/collab/use-presence-report.ts +176 -0
- package/src/lib/collab/use-self-profile-broadcast.ts +113 -0
- package/src/lib/collab/use-share-presence.ts +561 -0
- package/src/lib/collab/user-color.ts +40 -0
- package/src/lib/collections/index.ts +0 -1
- package/src/lib/collections/reference/bookmark-categories-collection.ts +1 -1
- package/src/lib/commands/__tests__/registry.test.ts +2 -5
- package/src/lib/commands/registry.ts +0 -3
- package/src/lib/commands/types.ts +1 -1
- package/src/lib/datetime.ts +20 -3
- package/src/lib/hooks/__tests__/use-synced-state.test.tsx +54 -0
- package/src/lib/hooks/use-story-panel-open.ts +134 -0
- package/src/lib/hooks/use-synced-state.ts +17 -0
- package/src/lib/hotkeys/__tests__/registry.test.ts +1 -1
- package/src/lib/hotkeys/registry.ts +0 -3
- package/src/lib/layout-responsive.ts +140 -0
- package/src/lib/pacer.ts +10 -1
- package/src/lib/peek-dock.ts +32 -0
- package/src/lib/plugin-runtime/__tests__/plugin-tool-schema-parity.test.ts +140 -0
- package/src/lib/plugin-runtime/plugin-client-tools.ts +28 -46
- package/src/lib/plugin-runtime/plugin-tool-defs.ts +152 -0
- package/src/lib/project-module-meta.ts +1 -8
- package/src/lib/rate-limit.ts +15 -6
- package/src/lib/sanitize.ts +122 -10
- package/src/lib/share-events.ts +20 -11
- package/src/lib/sidebar-utils.ts +1 -1
- package/src/lib/theme/__tests__/theme-mode.test.ts +96 -0
- package/src/lib/theme/theme-mode.ts +77 -0
- package/src/paraglide/messages/_index.js +5312 -1591
- package/src/paraglide/messages/en.js +1880 -685
- package/src/paraglide/messages/zh.js +1877 -682
- package/src/providers/index.tsx +4 -1
- package/src/providers/theme-mode-provider.tsx +135 -0
- package/src/routeTree.gen.ts +78 -101
- package/src/routes/$lang/docs/$/route.lazy.tsx +7 -2
- package/src/routes/-tests/chat-body-validation.test.ts +61 -3
- package/src/routes/__tests__/-edition-routing.test.tsx +12 -8
- package/src/routes/_nav/-components/nav-not-found.tsx +2 -2
- package/src/routes/_nav/bugs/$bugId/route.lazy.tsx +16 -2
- package/src/routes/_nav/bugs/$bugId/route.tsx +11 -2
- package/src/routes/_nav/dashboard/-components/avatar-group.tsx +2 -2
- package/src/routes/_nav/knowledge/$kbId/doc/$docId/route.lazy.tsx +31 -17
- package/src/routes/_nav/knowledge/$kbId/doc/$docId/route.tsx +12 -1
- package/src/routes/_nav/knowledge/$kbId/index.lazy.tsx +4 -2
- package/src/routes/_nav/knowledge/$kbId/route.lazy.tsx +7 -3
- package/src/routes/_nav/knowledge/bookmarks/$id.lazy.tsx +6 -6
- package/src/routes/_nav/knowledge/bookmarks/index.lazy.tsx +10 -10
- package/src/routes/_nav/knowledge/compliance/$id.lazy.tsx +9 -9
- package/src/routes/_nav/knowledge/compliance/edit/$id.lazy.tsx +1 -1
- package/src/routes/_nav/knowledge/compliance/index.lazy.tsx +8 -8
- package/src/routes/_nav/knowledge/dictionaries/$id.lazy.tsx +4 -4
- package/src/routes/_nav/knowledge/dictionaries/index.lazy.tsx +6 -6
- package/src/routes/_nav/knowledge/index.lazy.tsx +1 -1
- package/src/routes/_nav/knowledge/laws/$id.lazy.tsx +9 -9
- package/src/routes/_nav/knowledge/laws/edit/$id.lazy.tsx +1 -1
- package/src/routes/_nav/knowledge/laws/index.lazy.tsx +11 -11
- package/src/routes/_nav/knowledge/summary/index.lazy.tsx +1 -1
- package/src/routes/_nav/projects/$projectId/index.lazy.tsx +14 -6
- package/src/routes/_nav/route.lazy.tsx +11 -6
- package/src/routes/_nav/settings/account/route.tsx +3 -2
- package/src/routes/_nav/stories/$storyId/route.lazy.tsx +52 -8
- package/src/routes/_nav/stories/$storyId/route.tsx +11 -0
- package/src/routes/_nav/stories/-components/story-detail-skeleton.tsx +1 -1
- package/src/{components/tags/pages/tag-detail-page.tsx → routes/_nav/tasks/$taskId/route.lazy.tsx} +20 -10
- package/src/routes/_nav/tasks/$taskId/route.tsx +43 -0
- package/src/routes/_nav/tasks/-components/ai-task-detail.tsx +307 -0
- package/src/routes/_nav/tasks/-components/ai-task-list.tsx +217 -0
- package/src/routes/_nav/tasks/-components/ai-task-status-badge.tsx +46 -0
- package/src/routes/_nav/tasks/-components/assigned-list.tsx +157 -0
- package/src/routes/_nav/tasks/-components/create-ai-task-dialog.tsx +228 -0
- package/src/routes/_nav/tasks/-components/source-ai-exec-dialog.tsx +175 -0
- package/src/routes/_nav/tasks/-components/task-constants.ts +115 -0
- package/src/routes/_nav/tasks/-components/use-task-filter.ts +64 -0
- package/src/routes/_nav/tasks/-tests/create-ai-task-dialog.test.tsx +175 -0
- package/src/routes/_nav/tasks/-tests/task-filter.test.ts +134 -0
- package/src/routes/_nav/tasks/-tests/task-styles.test.tsx +119 -0
- package/src/routes/_nav/tasks/index.lazy.tsx +114 -0
- package/src/routes/_nav/tasks/index.tsx +47 -0
- package/src/routes/_nav/{tags → tasks}/route.tsx +3 -3
- package/src/routes/_nav/test-cases/$caseId/route.lazy.tsx +3 -1
- package/src/routes/_nav/test-cases/$caseId/route.tsx +11 -2
- package/src/routes/api/chat.ts +23 -19
- package/src/routes/api/design/prototype/route.ts +2 -4
- package/src/routes/{_nav/acceptance-criteria/route.tsx → api/internal/collab-reindex.ts} +11 -8
- package/src/routes/api/knowledge/sync-github.ts +1 -1
- package/src/routes/design-files/$projectId/$artboardId/$filename.ts +9 -0
- package/src/routes/invite/$token/route.lazy.tsx +2 -2
- package/src/routes/share/$versionId/route.lazy.tsx +8 -0
- package/src/routes/share/compliance/$id/route.lazy.tsx +2 -2
- package/src/routes/share/compliance/$id/route.tsx +1 -1
- package/src/routes/share/law/$id/route.lazy.tsx +2 -2
- package/src/routes/share/law/$id/route.tsx +1 -1
- package/src/server/__tests__/bug-groups-two-level.test.ts +263 -0
- package/src/server/__tests__/builtin-project.test.ts +45 -1
- package/src/server/__tests__/csv-export.test.ts +319 -0
- package/src/server/__tests__/share-version.test.ts +7 -2
- package/src/server/__tests__/task-assigned-query.test.ts +232 -0
- package/src/server/__tests__/task-context-builder.test.ts +175 -0
- package/src/server/__tests__/task-executor.test.ts +349 -0
- package/src/server/__tests__/task-priority-map.test.ts +41 -0
- package/src/server/__tests__/task-serverfn-crud.test.ts +639 -0
- package/src/server/__tests__/task-serverfn-queries.test.ts +403 -0
- package/src/server/__tests__/testcase-board.test.ts +301 -0
- package/src/server/__tests__/testcase-bulk.test.ts +155 -0
- package/src/server/__tests__/testcase-list-scope.test.ts +215 -0
- package/src/server/ai-gateway/__tests__/chat-handler-prompt-key.test.ts +106 -0
- package/src/server/ai-gateway/__tests__/chat-stream-builder-sandbox.test.ts +9 -3
- package/src/server/ai-gateway/__tests__/conformance.test.ts +4 -3
- package/src/server/ai-gateway/adapter.ts +4 -2
- package/src/server/ai-gateway/chat-handler.ts +13 -5
- package/src/server/ai-gateway/chat-stream-builder.ts +12 -7
- package/src/server/ai-gateway/sandbox/__tests__/harness-sandbox.test.ts +88 -0
- package/src/server/ai-gateway/sandbox/harness-sandbox.ts +1 -1
- package/src/server/ai-gateway/story-handler.ts +7 -2
- package/src/server/ai-gateway/tools/plugin-lifecycle-defs.ts +8 -99
- package/src/server/ai-gateway/tools/plugin-tools.ts +6 -10
- package/src/server/ai-task/assigned-query.ts +167 -0
- package/src/server/ai-task/context-builder.ts +182 -0
- package/src/server/ai-task/executor.ts +296 -0
- package/src/server/ai-task/priority-map.ts +37 -0
- package/src/server/ai-task/types.ts +15 -0
- package/src/server/bug-report/__tests__/report-handler.test.ts +55 -4
- package/src/server/bug-report/report-handler.ts +54 -8
- package/src/server/builtin-project.ts +24 -0
- package/src/server/cloudflare/prisma-wasm-base64-stub.ts +5 -0
- package/src/server/collab/__tests__/collab-permissions.test.ts +412 -0
- package/src/server/collab/__tests__/knowledge-additions.test.ts +121 -0
- package/src/server/collab/__tests__/reindex-endpoint.test.ts +168 -0
- package/src/server/collab/__tests__/resolve.test.ts +249 -0
- package/src/server/collab/__tests__/touch-snapshot.test.ts +58 -0
- package/src/server/collab/__tests__/write-guard-sdk.test.ts +501 -0
- package/src/server/collab/__tests__/write-guard.test.ts +373 -0
- package/src/server/collab/knowledge-additions.ts +37 -0
- package/src/server/collab/reindex-endpoint.ts +75 -0
- package/src/server/collab/resolve.ts +122 -0
- package/src/server/collab/seed.ts +408 -0
- package/src/server/collab/ticket-utils.ts +107 -0
- package/src/server/collab/touch-snapshot.ts +55 -0
- package/src/server/collab/write-guard.ts +258 -0
- package/src/server/collab-permissions.ts +248 -0
- package/src/server/csv.ts +61 -0
- package/src/server/{knowledge-public → knowledge/public}/github-sync.ts +12 -2
- package/src/server/{knowledge-public → knowledge/public}/share-merge.ts +31 -8
- package/src/server/lib/__tests__/sequence-number-retry.test.ts +160 -0
- package/src/server/lib/rate-limit.ts +13 -2
- package/src/server/lib/sequence-number-retry.ts +85 -0
- package/src/server/mcp/__tests__/tools.test.ts +10 -0
- package/src/server/mcp/tools.ts +26 -2
- package/src/server/middlewares/auth-rate-limit.ts +18 -9
- package/src/server/notifications/event-bus.ts +3 -0
- package/src/server/serverFns/__tests__/collab-snapshot.test.ts +665 -0
- package/src/server/serverFns/__tests__/collab.test.ts +459 -0
- package/src/server/serverFns/__tests__/knowledge-delete.test.ts +167 -0
- package/src/server/serverFns/__tests__/ownership-merge.test.ts +34 -2
- package/src/server/serverFns/__tests__/read-write-merge.test.ts +2 -2
- package/src/server/serverFns/__tests__/story-crud-archive-detail.test.ts +12 -2
- package/src/server/serverFns/__tests__/story-crud.test.ts +51 -11
- package/src/server/serverFns/__tests__/story-tree.test.ts +66 -34
- package/src/server/serverFns/__tests__/story-types.test.ts +14 -9
- package/src/server/serverFns/__tests__/update-bug-guard.test.ts +325 -0
- package/src/server/serverFns/__tests__/update-document-guard.test.ts +285 -0
- package/src/server/serverFns/__tests__/update-page-guard.test.ts +276 -0
- package/src/server/serverFns/__tests__/update-story-guard.test.ts +436 -0
- package/src/server/serverFns/__tests__/update-testcase-guard.test.ts +293 -0
- package/src/server/serverFns/bug/__tests__/bug-comments.test.ts +25 -0
- package/src/server/serverFns/bug/__tests__/bug-crud.test.ts +315 -15
- package/src/server/serverFns/bug/__tests__/bug-groups.test.ts +36 -18
- package/src/server/serverFns/bug/__tests__/bug-list-query.test.ts +21 -0
- package/src/server/serverFns/bug/__tests__/bug-reactions.test.ts +335 -0
- package/src/server/serverFns/bug/__tests__/bug-reorder.test.ts +165 -0
- package/src/server/serverFns/bug/__tests__/bug-story.test.ts +4 -1
- package/src/server/serverFns/bug/bug-comments.ts +5 -0
- package/src/server/serverFns/bug/bug-crud.ts +321 -72
- package/src/server/serverFns/bug/bug-display-options.ts +11 -0
- package/src/server/serverFns/bug/bug-export.ts +137 -0
- package/src/server/serverFns/bug/bug-group-query.ts +16 -5
- package/src/server/serverFns/bug/bug-groups.ts +39 -15
- package/src/server/serverFns/bug/bug-list-query.ts +8 -1
- package/src/server/serverFns/bug/bug-reactions.ts +123 -0
- package/src/server/serverFns/bug/bug-reorder.ts +64 -0
- package/src/server/serverFns/bug/bug-story-bulk.ts +280 -0
- package/src/server/serverFns/bug/bug-story.ts +47 -39
- package/src/server/serverFns/bug/index.ts +6 -0
- package/src/server/serverFns/collab-presence.ts +119 -0
- package/src/server/serverFns/collab-snapshot.ts +201 -0
- package/src/server/serverFns/collab.ts +153 -0
- package/src/server/serverFns/design/__tests__/designs.test.ts +0 -2
- package/src/server/serverFns/design/designs.ts +0 -64
- package/src/server/serverFns/design/detail.ts +36 -2
- package/src/server/serverFns/design/pages.ts +73 -10
- package/src/server/serverFns/iteration/iteration-crud.ts +25 -1
- package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/create.ts +3 -3
- package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/detail.ts +2 -2
- package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/list.ts +3 -2
- package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/refresh-favicon.ts +1 -1
- package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/share.ts +1 -1
- package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/sync-github.ts +1 -1
- package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/update.ts +5 -4
- package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/create.ts +1 -1
- package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/detail.ts +2 -2
- package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/list.ts +3 -2
- package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/share.ts +1 -1
- package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/update.ts +3 -2
- package/src/server/serverFns/{knowledge-public → knowledge/public}/dictionary/create.ts +1 -1
- package/src/server/serverFns/{knowledge-public → knowledge/public}/dictionary/detail.ts +2 -2
- package/src/server/serverFns/{knowledge-public → knowledge/public}/dictionary/list.ts +3 -2
- package/src/server/serverFns/{knowledge-public → knowledge/public}/dictionary/share.ts +1 -1
- package/src/server/serverFns/{knowledge-public → knowledge/public}/dictionary/update.ts +3 -2
- package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/create.ts +1 -1
- package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/detail.ts +2 -2
- package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/list.ts +3 -2
- package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/share.ts +1 -1
- package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/update.ts +3 -2
- package/src/server/serverFns/knowledge.ts +135 -19
- package/src/server/serverFns/project/module-overview.ts +1 -2
- package/src/server/serverFns/share/version.ts +7 -1
- package/src/server/serverFns/story/__tests__/bulk.test.ts +6 -0
- package/src/server/serverFns/story/__tests__/create-story-internal.test.ts +112 -3
- package/src/server/serverFns/story/__tests__/story-assoc.test.ts +77 -6
- package/src/server/serverFns/story/__tests__/story-crud-date-key.test.ts +187 -0
- package/src/server/serverFns/story/__tests__/story-gantt-deps.test.ts +163 -0
- package/src/server/serverFns/story/__tests__/story-groups.test.ts +4 -0
- package/src/server/serverFns/story/__tests__/story-list-query.test.ts +20 -0
- package/src/server/serverFns/story/__tests__/story-search.test.ts +5 -0
- package/src/server/serverFns/story/__tests__/story-transfer.test.ts +64 -1
- package/src/server/serverFns/story/index.ts +2 -2
- package/src/server/serverFns/story/story-assoc.ts +44 -14
- package/src/server/serverFns/story/story-crud/archive.ts +52 -28
- package/src/server/serverFns/story/story-crud/bulk.ts +14 -4
- package/src/server/serverFns/story/story-crud/create-story-internal.ts +39 -21
- package/src/server/serverFns/story/story-crud.ts +283 -116
- package/src/server/serverFns/story/story-dependencies.ts +31 -0
- package/src/server/serverFns/story/story-groups.ts +15 -11
- package/src/server/serverFns/story/story-list-query.ts +16 -4
- package/src/server/serverFns/story/story-search.ts +9 -6
- package/src/server/serverFns/story/story-transfer.ts +99 -42
- package/src/server/serverFns/story/story-tree.ts +70 -48
- package/src/server/serverFns/story-display-options.ts +21 -10
- package/src/server/serverFns/story-view.ts +2 -2
- package/src/server/serverFns/tasks/task-crud.ts +264 -0
- package/src/server/serverFns/tasks/task-queries.ts +172 -0
- package/src/server/serverFns/testcase/__tests__/generation.test.ts +3 -0
- package/src/server/serverFns/testcase/__tests__/stats.test.ts +18 -4
- package/src/server/serverFns/testcase/__tests__/testcase-board.test.ts +113 -0
- package/src/server/serverFns/testcase/__tests__/testcase-crud.test.ts +62 -14
- package/src/server/serverFns/testcase/__tests__/testcase-groups.test.ts +32 -10
- package/src/server/serverFns/testcase/bulk.ts +195 -0
- package/src/server/serverFns/testcase/generation.ts +10 -0
- package/src/server/serverFns/testcase/stats.ts +22 -8
- package/src/server/serverFns/testcase/testcase-board.ts +198 -0
- package/src/server/serverFns/testcase/testcase-crud.ts +165 -33
- package/src/server/serverFns/testcase/testcase-display-options.ts +166 -0
- package/src/server/serverFns/testcase/testcase-export.ts +125 -0
- package/src/server/serverFns/testcase/testcase-filter-views.ts +36 -9
- package/src/server/serverFns/testcase/testcase-groups.ts +27 -23
- package/src/server/serverFns/testcase/testcase-reorder.ts +66 -0
- package/src/server/story/__tests__/date-key.test.ts +57 -0
- package/src/server/story/date-key.ts +36 -0
- package/src/server/story/types.ts +3 -7
- package/src/server/testcase/__tests__/list-query.test.ts +269 -0
- package/src/server/testcase/list-query.ts +145 -0
- package/src/server-entry.ts +32 -0
- package/src/shared/bug/__tests__/constants.test.ts +44 -0
- package/src/shared/bug/constants.ts +37 -1
- package/src/start.ts +7 -2
- package/src/styles/globals.css +24 -3
- package/src/types/project.ts +2 -3
- package/vite.shared.ts +110 -3
- package/src/__tests__/tag-badge.test.tsx +0 -41
- package/src/components/bug/__tests__/bug-list-table.test.tsx +0 -289
- package/src/components/bug/bug-list-table.tsx +0 -187
- package/src/components/bug/columns.tsx +0 -193
- package/src/components/bug/filters/add-filter-dropdown.tsx +0 -70
- package/src/components/bug/filters/applied-filters.tsx +0 -214
- package/src/components/bug/filters/filter-condition.tsx +0 -151
- package/src/components/bug/filters/filter-row.tsx +0 -104
- package/src/components/bug/filters/filter-toggle.tsx +0 -61
- package/src/components/bug/filters/filter-types.ts +0 -146
- package/src/components/story/detail/story-detail-toolbar.tsx +0 -382
- package/src/components/story/filters/add-filter-dropdown.tsx +0 -70
- package/src/components/story/filters/applied-filters.tsx +0 -225
- package/src/components/story/filters/filter-condition.tsx +0 -152
- package/src/components/story/filters/filter-row.tsx +0 -116
- package/src/components/story/filters/filter-toggle.tsx +0 -60
- package/src/components/story/filters/filter-types.ts +0 -120
- package/src/components/story/filters/filter-value-input.tsx +0 -182
- package/src/components/story/views/kanban-board.tsx +0 -464
- package/src/components/story/views/kanban-card.tsx +0 -100
- package/src/components/tags/__tests__/tags.test.ts +0 -388
- package/src/components/tags/nav-tag.tsx +0 -121
- package/src/components/tags/pages/tag-settings-page.tsx +0 -32
- package/src/components/tags/pages/tags-index-page.tsx +0 -32
- package/src/components/tags/tag-badge.tsx +0 -56
- package/src/components/tags/tag-color-classes.ts +0 -61
- package/src/components/tags/tag-color-picker.tsx +0 -54
- package/src/components/tags/tag-components-index.ts +0 -23
- package/src/components/tags/tag-manager.tsx +0 -208
- package/src/components/tags/tag-selector.tsx +0 -164
- package/src/components/testcase/__tests__/table-view.test.tsx +0 -328
- package/src/components/testcase/plans/add-to-plan-bar.tsx +0 -64
- package/src/components/testcase/table/columns.tsx +0 -170
- package/src/components/testcase/table/table-view.tsx +0 -152
- package/src/lib/tag-colors.ts +0 -35
- package/src/routes/_nav/tags/$id/route.lazy.tsx +0 -23
- package/src/routes/_nav/tags/$id/route.tsx +0 -20
- package/src/routes/_nav/tags/index.lazy.tsx +0 -23
- package/src/routes/_nav/tags/index.tsx +0 -20
- package/src/routes/_nav/tags/settings/route.lazy.tsx +0 -23
- package/src/routes/_nav/tags/settings/route.tsx +0 -23
- package/src/server/serverFns/tags.ts +0 -138
- /package/src/components/{knowledge-public → knowledge/public}/bookmark-card.tsx +0 -0
- /package/src/components/{knowledge-public → knowledge/public}/category-icon.tsx +0 -0
- /package/src/components/{knowledge-public → knowledge/public}/chip-utils.ts +0 -0
- /package/src/components/{knowledge-public → knowledge/public}/knowledge-card-grid.tsx +0 -0
- /package/src/components/{knowledge-public → knowledge/public}/knowledge-filters.tsx +0 -0
- /package/src/components/{knowledge-public → knowledge/public}/knowledge-search-bar.tsx +0 -0
- /package/src/components/{knowledge-public → knowledge/public}/markdown-editor.tsx +0 -0
- /package/src/components/{knowledge-public → knowledge/public}/markdown-view.tsx +0 -0
- /package/src/components/{knowledge-public → knowledge/public}/tag-filter.tsx +0 -0
- /package/src/components/{story/detail → shared-kit/comments}/emoji-picker.tsx +0 -0
- /package/src/components/story/{schemas/story-create.ts → story-create-schema.ts} +0 -0
- /package/src/server/{knowledge-public → knowledge/public}/canonical-id.ts +0 -0
- /package/src/server/{knowledge-public → knowledge/public}/favicon.ts +0 -0
- /package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/categories.ts +0 -0
- /package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/delete.ts +0 -0
- /package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/favorite.ts +0 -0
- /package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/unshare.ts +0 -0
- /package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/delete.ts +0 -0
- /package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/public.ts +0 -0
- /package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/unshare.ts +0 -0
- /package/src/server/serverFns/{knowledge-public → knowledge/public}/dictionary/delete.ts +0 -0
- /package/src/server/serverFns/{knowledge-public → knowledge/public}/dictionary/unshare.ts +0 -0
- /package/src/server/serverFns/{knowledge-public → knowledge/public}/entity-tags.ts +0 -0
- /package/src/server/serverFns/{knowledge-public → knowledge/public}/favorite.ts +0 -0
- /package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/delete.ts +0 -0
- /package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/public.ts +0 -0
- /package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/unshare.ts +0 -0
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
// AllBlue - 理想之海
|
|
3
|
-
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
-
//
|
|
5
|
-
// This program is free software: you can redistribute it and/or modify
|
|
6
|
-
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
-
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
-
// (at your option) any later version.
|
|
9
|
-
//
|
|
10
|
-
// This program is distributed in the hope that it will be useful,
|
|
11
|
-
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
-
// GNU Affero General Public License for more details.
|
|
14
|
-
//
|
|
15
|
-
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
-
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
|
|
18
|
-
// 表格视图(规格 A3,仿 story-list-table 裁剪):TanStack Table v9 排序 +
|
|
19
|
-
// 列钉住(identifier/title)+ @tanstack/react-virtual 行虚拟化 + 无限滚动哨兵。
|
|
20
|
-
// 行点击为选中(与列表视图同一 selectedId 口径,任务 10 peek 消费),行内
|
|
21
|
-
// story 链接 stopPropagation 不劫持选中。分组不适用于表格(与需求页表格同口径:
|
|
22
|
-
// groupBy 仅作用于列表视图的 GroupedList)。
|
|
23
|
-
import { useMemo, useRef, useState } from "react";
|
|
24
|
-
import { flexRender, useTable, type SortingState } from "@tanstack/react-table";
|
|
25
|
-
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
26
|
-
import { ArrowDown, ArrowUp, ChevronDown } from "lucide-react";
|
|
27
|
-
import { InfiniteScrollSentinel } from "@/components/infinite-scroll-sentinel";
|
|
28
|
-
import type { TestCaseSummary } from "@/server/serverFns/testcase/types";
|
|
29
|
-
import { createTestCaseColumns, testCaseTableFeatures } from "./columns";
|
|
30
|
-
import { cn } from "@/lib/utils";
|
|
31
|
-
import { m } from "@/paraglide/messages.js";
|
|
32
|
-
|
|
33
|
-
const ROW_HEIGHT = 44;
|
|
34
|
-
|
|
35
|
-
interface TableViewProps {
|
|
36
|
-
cases: TestCaseSummary[];
|
|
37
|
-
hasMore: boolean;
|
|
38
|
-
selectedId: string | null;
|
|
39
|
-
onSelect: (id: string) => void;
|
|
40
|
-
/** 行点击(peek 滑出口径,可选;缺省回落 onSelect) */
|
|
41
|
-
onOpenCase?: (id: string) => void;
|
|
42
|
-
onLoadMore: () => void | Promise<void>;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function TableView({ cases, hasMore, selectedId, onSelect, onOpenCase, onLoadMore }: TableViewProps) {
|
|
46
|
-
const [sorting, setSorting] = useState<SortingState>([]);
|
|
47
|
-
const columns = useMemo(() => createTestCaseColumns(), []);
|
|
48
|
-
|
|
49
|
-
const table = useTable({
|
|
50
|
-
features: testCaseTableFeatures,
|
|
51
|
-
data: cases,
|
|
52
|
-
columns,
|
|
53
|
-
state: { sorting },
|
|
54
|
-
onSortingChange: setSorting,
|
|
55
|
-
initialState: {
|
|
56
|
-
columnPinning: { start: ["identifier", "title"], end: [] },
|
|
57
|
-
},
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const { rows } = table.getRowModel();
|
|
61
|
-
const parentRef = useRef<HTMLDivElement>(null);
|
|
62
|
-
|
|
63
|
-
const rowVirtualizer = useVirtualizer({
|
|
64
|
-
count: rows.length,
|
|
65
|
-
getScrollElement: () => parentRef.current,
|
|
66
|
-
estimateSize: () => ROW_HEIGHT,
|
|
67
|
-
overscan: 12,
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
const virtualRows = rowVirtualizer.getVirtualItems();
|
|
71
|
-
const totalHeight = rowVirtualizer.getTotalSize();
|
|
72
|
-
const paddingTop = virtualRows.length > 0 ? virtualRows[0].start : 0;
|
|
73
|
-
const paddingBottom = virtualRows.length > 0 ? totalHeight - virtualRows[virtualRows.length - 1].end : 0;
|
|
74
|
-
|
|
75
|
-
const headerGroups = table.getHeaderGroups();
|
|
76
|
-
const totalWidth = table.getTotalSize();
|
|
77
|
-
|
|
78
|
-
return (
|
|
79
|
-
<div ref={parentRef} className="h-full min-h-0 overflow-auto rounded-lg border bg-card">
|
|
80
|
-
<div style={{ width: totalWidth, minWidth: "100%" }}>
|
|
81
|
-
{/* 表头 */}
|
|
82
|
-
<div className="sticky top-0 z-10 flex h-9 items-center border-b bg-muted/50 backdrop-blur">
|
|
83
|
-
{headerGroups[0].headers.map((header) => {
|
|
84
|
-
const canSort = header.column.getCanSort();
|
|
85
|
-
const sortDir = header.column.getIsSorted();
|
|
86
|
-
return (
|
|
87
|
-
<div
|
|
88
|
-
key={header.id}
|
|
89
|
-
style={{ width: header.getSize() }}
|
|
90
|
-
className="flex h-full items-center gap-1 px-3 text-xs font-medium text-muted-foreground"
|
|
91
|
-
>
|
|
92
|
-
{flexRender(header.column.columnDef.header, header.getContext())}
|
|
93
|
-
{canSort && (
|
|
94
|
-
<button
|
|
95
|
-
type="button"
|
|
96
|
-
onClick={header.column.getToggleSortingHandler()}
|
|
97
|
-
className="text-muted-foreground/60 hover:text-foreground"
|
|
98
|
-
>
|
|
99
|
-
{sortDir === "asc" ? <ArrowUp className="size-3" />
|
|
100
|
-
: sortDir === "desc" ? <ArrowDown className="size-3" />
|
|
101
|
-
: <ChevronDown className="size-3" />}
|
|
102
|
-
</button>
|
|
103
|
-
)}
|
|
104
|
-
</div>
|
|
105
|
-
);
|
|
106
|
-
})}
|
|
107
|
-
</div>
|
|
108
|
-
|
|
109
|
-
{/* 虚拟化行 */}
|
|
110
|
-
<div>
|
|
111
|
-
{paddingTop > 0 && <div style={{ height: paddingTop }} />}
|
|
112
|
-
{virtualRows.map((virtualRow) => {
|
|
113
|
-
const row = rows[virtualRow.index];
|
|
114
|
-
const selected = selectedId === row.original.id;
|
|
115
|
-
return (
|
|
116
|
-
<div
|
|
117
|
-
key={row.original.id}
|
|
118
|
-
data-testid="table-row"
|
|
119
|
-
data-case-id={row.original.id}
|
|
120
|
-
data-selected={selected ? "true" : "false"}
|
|
121
|
-
onClick={() => (onOpenCase ? onOpenCase(row.original.id) : onSelect(row.original.id))}
|
|
122
|
-
style={{ height: ROW_HEIGHT }}
|
|
123
|
-
className={cn(
|
|
124
|
-
"flex w-full cursor-pointer items-center border-b border-border/40 text-sm transition-colors hover:bg-muted/40",
|
|
125
|
-
selected && "bg-accent/60 hover:bg-accent/60",
|
|
126
|
-
)}
|
|
127
|
-
>
|
|
128
|
-
{row.getVisibleCells().map((cell) => (
|
|
129
|
-
<div
|
|
130
|
-
key={cell.id}
|
|
131
|
-
style={{ width: cell.column.getSize() }}
|
|
132
|
-
className="flex h-full items-center overflow-hidden px-3"
|
|
133
|
-
>
|
|
134
|
-
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
135
|
-
</div>
|
|
136
|
-
))}
|
|
137
|
-
</div>
|
|
138
|
-
);
|
|
139
|
-
})}
|
|
140
|
-
{paddingBottom > 0 && <div style={{ height: paddingBottom }} />}
|
|
141
|
-
<InfiniteScrollSentinel loadedAllLabel={m.story_loadedAll()} onLoadMore={onLoadMore} hasMore={hasMore} rootRef={parentRef} />
|
|
142
|
-
</div>
|
|
143
|
-
|
|
144
|
-
{rows.length === 0 && (
|
|
145
|
-
<div className="flex h-40 items-center justify-center text-sm text-muted-foreground">
|
|
146
|
-
{m.testcase_listView_empty()}
|
|
147
|
-
</div>
|
|
148
|
-
)}
|
|
149
|
-
</div>
|
|
150
|
-
</div>
|
|
151
|
-
);
|
|
152
|
-
}
|
package/src/lib/tag-colors.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
// AllBlue - 理想之海
|
|
3
|
-
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
-
//
|
|
5
|
-
// This program is free software: you can redistribute it and/or modify
|
|
6
|
-
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
-
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
-
// (at your option) any later version.
|
|
9
|
-
//
|
|
10
|
-
// This program is distributed in the hope that it will be useful,
|
|
11
|
-
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
-
// GNU Affero General Public License for more details.
|
|
14
|
-
//
|
|
15
|
-
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
-
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
|
|
18
|
-
const TAG_COLORS = [
|
|
19
|
-
{ bg: "bg-blue-100 dark:bg-blue-900/30", text: "text-blue-700 dark:text-blue-300", border: "border-blue-200 dark:border-blue-700", selected: "border-blue-500", check: "text-blue-700 dark:text-blue-300", label: "蓝色" },
|
|
20
|
-
{ bg: "bg-emerald-100 dark:bg-emerald-900/30", text: "text-emerald-700 dark:text-emerald-300", border: "border-emerald-200 dark:border-emerald-700", selected: "border-emerald-500", check: "text-emerald-700 dark:text-emerald-300", label: "绿色" },
|
|
21
|
-
{ bg: "bg-violet-100 dark:bg-violet-900/30", text: "text-violet-700 dark:text-violet-300", border: "border-violet-200 dark:border-violet-700", selected: "border-violet-500", check: "text-violet-700 dark:text-violet-300", label: "紫色" },
|
|
22
|
-
{ bg: "bg-amber-100 dark:bg-amber-900/30", text: "text-amber-700 dark:text-amber-300", border: "border-amber-200 dark:border-amber-700", selected: "border-amber-500", check: "text-amber-700 dark:text-amber-300", label: "琥珀" },
|
|
23
|
-
{ bg: "bg-rose-100 dark:bg-rose-900/30", text: "text-rose-700 dark:text-rose-300", border: "border-rose-200 dark:border-rose-700", selected: "border-rose-500", check: "text-rose-700 dark:text-rose-300", label: "玫红" },
|
|
24
|
-
{ bg: "bg-cyan-100 dark:bg-cyan-900/30", text: "text-cyan-700 dark:text-cyan-300", border: "border-cyan-200 dark:border-cyan-700", selected: "border-cyan-500", check: "text-cyan-700 dark:text-cyan-300", label: "青色" },
|
|
25
|
-
{ bg: "bg-orange-100 dark:bg-orange-900/30", text: "text-orange-700 dark:text-orange-300", border: "border-orange-200 dark:border-orange-700", selected: "border-orange-500", check: "text-orange-700 dark:text-orange-300", label: "橙色" },
|
|
26
|
-
{ bg: "bg-pink-100 dark:bg-pink-900/30", text: "text-pink-700 dark:text-pink-300", border: "border-pink-200 dark:border-pink-700", selected: "border-pink-500", check: "text-pink-700 dark:text-pink-300", label: "粉色" },
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
function hashColorIndex(name: string) {
|
|
30
|
-
let hash = 0;
|
|
31
|
-
for (let i = 0; i < name.length; i++) hash = ((hash << 5) - hash) + name.charCodeAt(i);
|
|
32
|
-
return Math.abs(hash) % TAG_COLORS.length;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export { TAG_COLORS, hashColorIndex };
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
// AllBlue - 理想之海
|
|
3
|
-
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
-
//
|
|
5
|
-
// This program is free software: you can redistribute it and/or modify
|
|
6
|
-
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
-
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
-
// (at your option) any later version.
|
|
9
|
-
//
|
|
10
|
-
// This program is distributed in the hope that it will be useful,
|
|
11
|
-
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
-
// GNU Affero General Public License for more details.
|
|
14
|
-
//
|
|
15
|
-
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
-
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
|
|
18
|
-
import { createLazyFileRoute } from '@tanstack/react-router'
|
|
19
|
-
import { TagDetailPage } from '@/components/tags/pages/tag-detail-page'
|
|
20
|
-
|
|
21
|
-
export const Route = createLazyFileRoute('/_nav/tags/$id')({
|
|
22
|
-
component: TagDetailPage,
|
|
23
|
-
})
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
// AllBlue - 理想之海
|
|
3
|
-
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
-
//
|
|
5
|
-
// This program is free software: you can redistribute it and/or modify
|
|
6
|
-
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
-
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
-
// (at your option) any later version.
|
|
9
|
-
//
|
|
10
|
-
// This program is distributed in the hope that it will be useful,
|
|
11
|
-
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
-
// GNU Affero General Public License for more details.
|
|
14
|
-
//
|
|
15
|
-
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
-
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
|
|
18
|
-
import { createFileRoute } from '@tanstack/react-router'
|
|
19
|
-
|
|
20
|
-
export const Route = createFileRoute('/_nav/tags/$id')({})
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
// AllBlue - 理想之海
|
|
3
|
-
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
-
//
|
|
5
|
-
// This program is free software: you can redistribute it and/or modify
|
|
6
|
-
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
-
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
-
// (at your option) any later version.
|
|
9
|
-
//
|
|
10
|
-
// This program is distributed in the hope that it will be useful,
|
|
11
|
-
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
-
// GNU Affero General Public License for more details.
|
|
14
|
-
//
|
|
15
|
-
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
-
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
|
|
18
|
-
import { createLazyFileRoute } from '@tanstack/react-router'
|
|
19
|
-
import { TagsIndexPage } from '@/components/tags/pages/tags-index-page'
|
|
20
|
-
|
|
21
|
-
export const Route = createLazyFileRoute('/_nav/tags/')({
|
|
22
|
-
component: TagsIndexPage,
|
|
23
|
-
})
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
// AllBlue - 理想之海
|
|
3
|
-
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
-
//
|
|
5
|
-
// This program is free software: you can redistribute it and/or modify
|
|
6
|
-
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
-
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
-
// (at your option) any later version.
|
|
9
|
-
//
|
|
10
|
-
// This program is distributed in the hope that it will be useful,
|
|
11
|
-
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
-
// GNU Affero General Public License for more details.
|
|
14
|
-
//
|
|
15
|
-
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
-
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
|
|
18
|
-
import { createFileRoute } from '@tanstack/react-router'
|
|
19
|
-
|
|
20
|
-
export const Route = createFileRoute('/_nav/tags/')({})
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
// AllBlue - 理想之海
|
|
3
|
-
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
-
//
|
|
5
|
-
// This program is free software: you can redistribute it and/or modify
|
|
6
|
-
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
-
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
-
// (at your option) any later version.
|
|
9
|
-
//
|
|
10
|
-
// This program is distributed in the hope that it will be useful,
|
|
11
|
-
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
-
// GNU Affero General Public License for more details.
|
|
14
|
-
//
|
|
15
|
-
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
-
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
|
|
18
|
-
import { createLazyFileRoute } from '@tanstack/react-router'
|
|
19
|
-
import { TagSettingsPage } from '@/components/tags/pages/tag-settings-page'
|
|
20
|
-
|
|
21
|
-
export const Route = createLazyFileRoute('/_nav/tags/settings')({
|
|
22
|
-
component: TagSettingsPage,
|
|
23
|
-
})
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
// AllBlue - 理想之海
|
|
3
|
-
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
-
//
|
|
5
|
-
// This program is free software: you can redistribute it and/or modify
|
|
6
|
-
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
-
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
-
// (at your option) any later version.
|
|
9
|
-
//
|
|
10
|
-
// This program is distributed in the hope that it will be useful,
|
|
11
|
-
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
-
// GNU Affero General Public License for more details.
|
|
14
|
-
//
|
|
15
|
-
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
-
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
|
|
18
|
-
import { createFileRoute } from '@tanstack/react-router'
|
|
19
|
-
import { listTagsFn } from '@/server/serverFns/tags'
|
|
20
|
-
|
|
21
|
-
export const Route = createFileRoute('/_nav/tags/settings')({
|
|
22
|
-
loader: () => listTagsFn(),
|
|
23
|
-
})
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
// AllBlue - 理想之海
|
|
3
|
-
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
-
//
|
|
5
|
-
// This program is free software: you can redistribute it and/or modify
|
|
6
|
-
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
-
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
-
// (at your option) any later version.
|
|
9
|
-
//
|
|
10
|
-
// This program is distributed in the hope that it will be useful,
|
|
11
|
-
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
-
// GNU Affero General Public License for more details.
|
|
14
|
-
//
|
|
15
|
-
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
-
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
|
|
18
|
-
import { createServerFn } from '@tanstack/react-start'
|
|
19
|
-
import { getRequest } from '@tanstack/react-start/server'
|
|
20
|
-
import { z } from 'zod'
|
|
21
|
-
import { getPrisma } from '@allbluecn/database/get-prisma'
|
|
22
|
-
import { getServerSeam } from '@allbluecn/kernel'
|
|
23
|
-
import { hashColorIndex } from '@/lib/tag-colors'
|
|
24
|
-
|
|
25
|
-
export const listTagsFn = createServerFn({ method: 'GET' })
|
|
26
|
-
.handler(async () => {
|
|
27
|
-
const prisma = await getPrisma()
|
|
28
|
-
const request = getRequest()
|
|
29
|
-
const session = await getServerSeam().requireAuth(request)
|
|
30
|
-
return prisma.tag.findMany({
|
|
31
|
-
where: { userId: session.user!.id!, isHidden: false },
|
|
32
|
-
orderBy: { sortOrder: 'asc' },
|
|
33
|
-
})
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
const createTagSchema = z.object({ name: z.string().min(1).trim() })
|
|
37
|
-
|
|
38
|
-
export const createTagFn = createServerFn({ method: 'POST' })
|
|
39
|
-
.validator(createTagSchema)
|
|
40
|
-
.handler(async ({ data }) => {
|
|
41
|
-
const prisma = await getPrisma()
|
|
42
|
-
const request = getRequest()
|
|
43
|
-
const session = await getServerSeam().requireAuth(request)
|
|
44
|
-
const userId = session.user!.id!
|
|
45
|
-
|
|
46
|
-
const existing = await prisma.tag.findFirst({ where: { name: data.name, userId } })
|
|
47
|
-
if (existing) return existing
|
|
48
|
-
|
|
49
|
-
return prisma.tag.create({
|
|
50
|
-
data: { name: data.name, color: hashColorIndex(data.name), userId },
|
|
51
|
-
})
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
const updateTagSchema = z.object({
|
|
55
|
-
id: z.string(),
|
|
56
|
-
name: z.string().min(1).trim().optional(),
|
|
57
|
-
color: z.number().int().min(0).max(7).optional(),
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
export const updateTagFn = createServerFn({ method: 'POST' })
|
|
61
|
-
.validator(updateTagSchema)
|
|
62
|
-
.handler(async ({ data }) => {
|
|
63
|
-
const prisma = await getPrisma()
|
|
64
|
-
const request = getRequest()
|
|
65
|
-
const session = await getServerSeam().requireAuth(request)
|
|
66
|
-
const userId = session.user!.id!
|
|
67
|
-
|
|
68
|
-
const tag = await prisma.tag.findFirst({ where: { id: data.id, userId } })
|
|
69
|
-
if (!tag) throw new Error('FORBIDDEN')
|
|
70
|
-
|
|
71
|
-
if (data.name && data.name !== tag.name) {
|
|
72
|
-
const conflict = await prisma.tag.findFirst({
|
|
73
|
-
where: { name: data.name, userId },
|
|
74
|
-
})
|
|
75
|
-
if (conflict) {
|
|
76
|
-
throw new Error('TAG_NAME_CONFLICT')
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return prisma.tag.update({
|
|
81
|
-
where: { id: data.id },
|
|
82
|
-
data: {
|
|
83
|
-
...(data.name !== undefined ? { name: data.name } : {}),
|
|
84
|
-
...(data.color !== undefined ? { color: data.color } : {}),
|
|
85
|
-
},
|
|
86
|
-
})
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
const reorderTagsSchema = z.object({ orderedIds: z.array(z.string()).min(1) })
|
|
90
|
-
|
|
91
|
-
export const reorderTagsFn = createServerFn({ method: 'POST' })
|
|
92
|
-
.validator(reorderTagsSchema)
|
|
93
|
-
.handler(async ({ data }) => {
|
|
94
|
-
const prisma = await getPrisma()
|
|
95
|
-
const request = getRequest()
|
|
96
|
-
const session = await getServerSeam().requireAuth(request)
|
|
97
|
-
const userId = session.user!.id!
|
|
98
|
-
|
|
99
|
-
// DB-01:原逐标签 findFirst 鉴权 + update(2N 次查询)。改一次 findMany in 鉴权 + 事务内
|
|
100
|
-
// 批量 updateMany(N 次写并行、原子提交,鉴权 where 保留 userId 防 TOCTOU)。
|
|
101
|
-
// 查询次数 before: 2N → after: 1 + N(事务内并行)
|
|
102
|
-
const owned = await prisma.tag.findMany({
|
|
103
|
-
where: { id: { in: data.orderedIds }, userId },
|
|
104
|
-
select: { id: true },
|
|
105
|
-
})
|
|
106
|
-
const ownedIds = new Set(owned.map((t) => t.id))
|
|
107
|
-
|
|
108
|
-
await prisma.$transaction(async (tx) => {
|
|
109
|
-
await Promise.all(
|
|
110
|
-
data.orderedIds.map((id, index) => {
|
|
111
|
-
// 未授权/不存在的 id 静默跳过(与原 findFirst 失败 return null 行为一致)
|
|
112
|
-
if (!ownedIds.has(id)) return Promise.resolve()
|
|
113
|
-
return tx.tag.updateMany({ where: { id, userId }, data: { sortOrder: index * 1000 } })
|
|
114
|
-
}),
|
|
115
|
-
)
|
|
116
|
-
})
|
|
117
|
-
return { success: true }
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
const deleteTagSchema = z.object({ id: z.string() })
|
|
121
|
-
|
|
122
|
-
export const deleteTagFn = createServerFn({ method: 'POST' })
|
|
123
|
-
.validator(deleteTagSchema)
|
|
124
|
-
.handler(async ({ data }) => {
|
|
125
|
-
const prisma = await getPrisma()
|
|
126
|
-
const request = getRequest()
|
|
127
|
-
const session = await getServerSeam().requireAuth(request)
|
|
128
|
-
const userId = session.user!.id!
|
|
129
|
-
|
|
130
|
-
const tag = await prisma.tag.findFirst({ where: { id: data.id, userId } })
|
|
131
|
-
if (!tag) throw new Error('FORBIDDEN')
|
|
132
|
-
|
|
133
|
-
await prisma.tag.update({
|
|
134
|
-
where: { id: data.id },
|
|
135
|
-
data: { isHidden: true },
|
|
136
|
-
})
|
|
137
|
-
return { success: true }
|
|
138
|
-
})
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|