@allbluecn/web-app 0.19.5 → 0.21.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 +3 -3
- package/src/components/bug/__tests__/board-subgroups.test.tsx +1 -1
- package/src/components/bug/__tests__/board-view.test.tsx +1 -1
- package/src/components/bug/__tests__/comment-reactions.test.tsx +1 -1
- package/src/components/bug/__tests__/create-bug-dialog.test.tsx +2 -2
- package/src/components/bug/__tests__/filters-compat.test.tsx +1 -1
- package/src/components/bug/__tests__/fix-request-race.test.tsx +1 -1
- package/src/components/bug/__tests__/peek-modes.test.tsx +1 -1
- package/src/components/bug/__tests__/use-paged-bug-groups.test.tsx +1 -1
- package/src/components/bug/__tests__/view-type.test.tsx +1 -1
- package/src/components/bug/bug-list-view.tsx +2 -2
- package/src/components/bug/bug-toolbar.tsx +1 -1
- package/src/components/bug/create-bug-dialog.tsx +3 -3
- package/src/components/bug/detail/__tests__/activity-timeline.test.tsx +1 -1
- package/src/components/bug/detail/__tests__/bug-detail-collab.test.tsx +1 -1
- package/src/components/bug/detail/__tests__/repro-report-card.test.tsx +1 -1
- package/src/components/bug/detail/activity-tabs.tsx +34 -3
- package/src/components/bug/detail/activity-timeline.tsx +1 -1
- package/src/components/bug/detail/bug-detail-body.tsx +3 -3
- package/src/components/bug/detail/comment-input.tsx +1 -1
- package/src/components/bug/detail/comment-item.tsx +1 -1
- package/src/components/bug/detail/comment-reactions.tsx +1 -1
- package/src/components/bug/detail/comment-thread.tsx +1 -1
- package/src/components/bug/detail/props-section.tsx +2 -2
- package/src/components/bug/detail/repro-report-card.tsx +1 -1
- package/src/components/bug/detail/reproduce-steps-view.tsx +1 -1
- package/src/components/bug/display/use-paged-bug-groups.ts +2 -2
- package/src/components/bug/filters/field-configs.tsx +1 -1
- package/src/components/bug/inline-editors/assignee-editor.tsx +1 -1
- package/src/components/bug/peek-panel.tsx +2 -2
- package/src/components/bug/reproduce-steps-editor.tsx +1 -1
- package/src/components/bug/story-bugs-panel.tsx +10 -6
- package/src/components/bug/views/board-view.tsx +2 -2
- package/src/components/bug/views/bug-list/batch-toolbar.tsx +1 -1
- package/src/components/bug/views/bug-list/group.tsx +1 -1
- package/src/components/bug/views/bug-list/index.tsx +1 -1
- package/src/components/bug/views/bug-list/inline-bug-creator.tsx +1 -1
- package/src/components/bug/views/bug-list/row.tsx +2 -2
- package/src/components/bug/views/create-view-dialog.tsx +1 -1
- package/src/components/design/editor/versions/hooks/use-design-versions.ts +11 -4
- package/src/components/design/editor/versions/page-version-panel.tsx +30 -11
- package/src/components/harness/code/workspace-context.tsx +5 -1
- package/src/components/harness/code/workspace-picker.tsx +19 -6
- package/src/components/harness/composer/harness-composer.tsx +25 -3
- package/src/components/harness/composer/mention/mention-resolvers.ts +2 -0
- package/src/components/harness/composer/mention/mention-suggestion-menu.tsx +6 -3
- package/src/components/harness/composer/mention/use-mention-sources.ts +1 -1
- package/src/components/iteration/iteration-progress-bar.tsx +2 -2
- package/src/components/knowledge/public/legal-compliance-editor.tsx +1 -1
- package/src/components/layout/sidebar-03/nav-knowledge.tsx +1 -1
- package/src/components/layout/sidebar-03/nav-workspace.tsx +1 -1
- package/src/components/project/invite-member-dialog.tsx +2 -2
- package/src/components/project/project-member-manager.tsx +0 -3
- package/src/components/shared-kit/list-kit/kanban/__tests__/instance-key.test.ts +1 -1
- package/src/components/story/__tests__/constants.test.ts +1 -1
- package/src/components/story/__tests__/dependency-type-badge.test.ts +1 -1
- package/src/components/story/__tests__/peek-panel-patch-sync.test.tsx +1 -1
- package/src/components/story/__tests__/story-list-view-peek-sync.test.tsx +1 -1
- package/src/components/story/ai/story-ai-panel.tsx +1 -1
- package/src/components/story/ai/story-ai-preview-list.tsx +2 -2
- package/src/components/story/ai/use-story-ai-model.ts +17 -4
- package/src/components/story/columns.tsx +2 -2
- package/src/components/story/create-story-dialog.tsx +4 -4
- package/src/components/story/detail/__tests__/activity-timeline.test.tsx +1 -1
- package/src/components/story/detail/__tests__/associated-attachments-panel.test.tsx +1 -1
- package/src/components/story/detail/__tests__/story-collab.test.tsx +1 -1
- package/src/components/story/detail/activity-tabs.tsx +1 -1
- package/src/components/story/detail/activity-timeline.tsx +36 -17
- package/src/components/story/detail/comment-input.tsx +1 -1
- package/src/components/story/detail/comment-item.tsx +1 -1
- package/src/components/story/detail/comment-thread.tsx +1 -1
- package/src/components/story/detail/reaction-bar.tsx +1 -1
- package/src/components/story/detail/story-detail-body.tsx +4 -4
- package/src/components/story/detail/story-detail-toolbar/__tests__/attachment-cache.test.ts +83 -0
- package/src/components/story/detail/story-detail-toolbar/associated-attachments-panel.tsx +50 -9
- package/src/components/story/detail/story-detail-toolbar/children.tsx +3 -3
- package/src/components/story/detail/story-detail-toolbar/dependency-panel.tsx +9 -8
- package/src/components/story/detail/story-detail-toolbar/index.tsx +8 -8
- package/src/components/story/detail/story-detail-toolbar/related-test-cases.tsx +2 -2
- package/src/components/story/detail/story-properties.tsx +2 -2
- package/src/components/story/display/__tests__/flatten-story-groups.test.ts +1 -1
- package/src/components/story/display/__tests__/group-fields.test.ts +1 -1
- package/src/components/story/display/__tests__/group-resolver.test.ts +2 -2
- package/src/components/story/display/__tests__/order-resolver.test.ts +1 -1
- package/src/components/story/display/__tests__/use-grouped-stories.test.ts +1 -1
- package/src/components/story/display/__tests__/use-paged-story-groups.test.ts +1 -1
- package/src/components/story/display/flatten-story-groups.ts +1 -1
- package/src/components/story/display/group-fields.ts +2 -2
- package/src/components/story/display/group-resolver.tsx +4 -4
- package/src/components/story/display/order-resolver.ts +3 -3
- package/src/components/story/display/types.ts +5 -4
- package/src/components/story/display/use-grouped-stories.ts +5 -5
- package/src/components/story/display/use-paged-story-groups.ts +11 -4
- package/src/components/story/entity-overlay.ts +24 -0
- package/src/components/story/filters/field-configs.tsx +2 -2
- package/src/components/story/inline-editors/assignee-editor.tsx +1 -1
- package/src/components/story/inline-editors/dependency-type-select.tsx +1 -1
- package/src/components/story/inline-editors/parent-story-editor.tsx +2 -2
- package/src/components/story/inline-editors/priority-editor.tsx +2 -2
- package/src/components/story/inline-editors/state-editor.tsx +2 -2
- package/src/components/story/inline-editors/story-select-dialog.tsx +2 -2
- package/src/components/story/peek-panel.tsx +6 -5
- package/src/components/story/priority-icon.tsx +2 -2
- package/src/components/story/relations/__tests__/attachment-manage-dialog.test.tsx +1 -1
- package/src/components/story/relations/__tests__/design-select-dialog.test.tsx +1 -1
- package/src/components/story/relations/__tests__/knowledge-select-dialog.test.tsx +1 -1
- package/src/components/story/relations/__tests__/link-manage-dialog.test.tsx +1 -1
- package/src/components/story/relations/attachment-manage-dialog.tsx +4 -4
- package/src/components/story/relations/design-select-dialog.tsx +2 -2
- package/src/components/story/relations/knowledge-select-dialog.tsx +2 -2
- package/src/components/story/relations/link-manage-dialog.tsx +2 -2
- package/src/components/story/relations/story-ref-row.tsx +3 -3
- package/src/components/story/story-list-table.tsx +1 -1
- package/src/components/story/story-list-view.tsx +1 -1
- package/src/components/story/story-toolbar.tsx +1 -1
- package/src/components/story/transfer-story-popover.tsx +3 -2
- package/src/components/story/views/__tests__/calendar-view.test.tsx +1 -1
- package/src/components/story/views/__tests__/kanban-drop-subgroup.test.ts +1 -1
- package/src/components/story/views/__tests__/kanban-peek-sync.test.tsx +2 -2
- package/src/components/story/views/__tests__/kanban-view-membership-sync.test.tsx +1 -1
- package/src/components/story/views/__tests__/timeline-view.test.tsx +1 -1
- package/src/components/story/views/calendar/__tests__/mappers.test.ts +1 -1
- package/src/components/story/views/calendar/mappers.ts +1 -1
- package/src/components/story/views/calendar-view.tsx +1 -1
- package/src/components/story/views/create-view-dialog.tsx +1 -1
- package/src/components/story/views/kanban-view.tsx +2 -2
- package/src/components/story/views/story-list/batch-preview-dialog.tsx +2 -2
- package/src/components/story/views/story-list/batch-toolbar.tsx +3 -3
- package/src/components/story/views/story-list/group.tsx +18 -5
- package/src/components/story/views/story-list/index.tsx +4 -2
- package/src/components/story/views/story-list/inline-story-creator.tsx +2 -2
- package/src/components/story/views/story-list/row.tsx +2 -2
- package/src/components/story/views/story-list/use-flat-rows.ts +1 -1
- package/src/components/story/views/timeline/__tests__/mappers.test.ts +2 -2
- package/src/components/story/views/timeline/mappers.ts +2 -2
- package/src/components/story/views/timeline/use-date-commit.ts +1 -1
- package/src/components/story/views/timeline-view.tsx +2 -2
- package/src/components/testcase/__tests__/case-row.test.tsx +1 -1
- package/src/components/testcase/__tests__/create-dialog-scope.test.tsx +1 -1
- package/src/components/testcase/__tests__/display-options.test.tsx +1 -1
- package/src/components/testcase/__tests__/export-entry.test.tsx +1 -1
- package/src/components/testcase/__tests__/list-view.test.tsx +1 -1
- package/src/components/testcase/__tests__/step-editor.test.tsx +4 -2
- package/src/components/testcase/__tests__/toolbar.test.tsx +1 -1
- package/src/components/testcase/create-testcase-dialog.tsx +6 -5
- package/src/components/testcase/detail/case-detail-body.tsx +1 -1
- package/src/components/testcase/detail/properties.tsx +1 -1
- package/src/components/testcase/display/display-dropdown.tsx +2 -2
- package/src/components/testcase/display/use-testcase-display-options.ts +1 -1
- package/src/components/testcase/filters/field-configs.tsx +1 -1
- package/src/components/testcase/generation/draft-card.tsx +2 -2
- package/src/components/testcase/inline-editors/assignee-editor.tsx +1 -1
- package/src/components/testcase/list/case-row.tsx +1 -1
- package/src/components/testcase/list/grouped-list.tsx +1 -1
- package/src/components/testcase/list-view.tsx +2 -2
- package/src/components/testcase/runs/convert-bug-button.tsx +2 -2
- package/src/components/testcase/step-editor.tsx +13 -2
- package/src/components/testcase/testcase-toolbar.tsx +2 -2
- package/src/components/testcase/views/batch-toolbar.tsx +1 -1
- package/src/components/testcase/views/board-view.tsx +2 -2
- package/src/lib/changelog/sdk-versions.ts +2 -2
- package/src/lib/collections/knowledge/knowledge-bases-collection.ts +2 -1
- package/src/lib/collections/query-keys.ts +18 -0
- package/src/lib/collections/reference/users-brief-collection.ts +2 -1
- package/src/lib/collections/reference/workspaces-collection.ts +2 -1
- package/src/lib/story/__tests__/activity-grouper.test.ts +1 -1
- package/src/lib/story/activity-grouper.ts +1 -1
- package/src/paraglide/messages/_index.d.ts +2 -0
- package/src/paraglide/messages/_index.js +88269 -5642
- package/src/paraglide/messages/en.js +28255 -0
- package/src/paraglide/messages/story_group_loadfailed1.d.ts +17 -0
- package/src/paraglide/messages/story_group_loadfailed1.js +30 -0
- package/src/paraglide/messages/story_group_retry.d.ts +16 -0
- package/src/paraglide/messages/story_group_retry.js +29 -0
- package/src/paraglide/messages/zh.js +28253 -0
- package/src/routes/_nav/bugs/$bugId/route.lazy.tsx +2 -2
- package/src/routes/_nav/projects/$projectId/iterations/$iterationId/route.lazy.tsx +1 -1
- package/src/routes/_nav/route.tsx +1 -2
- package/src/routes/_nav/stories/$storyId/route.lazy.tsx +2 -2
- package/src/routes/_nav/stories/$storyId/route.tsx +1 -1
- package/src/routes/api/design/prototype/__tests__/route.test.ts +4 -1
- package/src/server/__tests__/task-executor.test.ts +7 -0
- package/src/server/ai-gateway/__tests__/ai-output-guard.test.ts +4 -4
- package/src/server/ai-gateway/__tests__/tools-authorization.test.ts +25 -0
- package/src/server/ai-gateway/tools/server.ts +24 -15
- package/src/server/knowledge/reindex-guard.ts +35 -0
- package/src/server/lib/__tests__/cron-auth.test.ts +1 -1
- package/src/server/serverFns/__tests__/legal-code-canonical.test.ts +169 -0
- package/src/server/serverFns/__tests__/story-tree.test.ts +0 -1
- package/src/server/serverFns/__tests__/story-types.test.ts +2 -1
- package/src/server/serverFns/__tests__/update-bug-guard.test.ts +1 -1
- package/src/server/serverFns/bug/__tests__/bug-comments.test.ts +95 -44
- package/src/server/serverFns/bug/__tests__/bug-crud.test.ts +46 -18
- package/src/server/serverFns/bug/__tests__/bug-groups.test.ts +1 -1
- package/src/server/serverFns/bug/bug-activities.ts +2 -2
- package/src/server/serverFns/bug/bug-comments.ts +44 -19
- package/src/server/serverFns/bug/bug-crud/detail-select.ts +1 -1
- package/src/server/serverFns/bug/bug-crud/detail.ts +2 -2
- package/src/server/serverFns/bug/bug-crud.ts +142 -110
- package/src/server/serverFns/bug/bug-group-query.ts +1 -1
- package/src/server/serverFns/bug/bug-groups.ts +2 -2
- package/src/server/serverFns/bug/bug-story-utils.ts +1 -1
- package/src/server/serverFns/chat/conversations.ts +27 -13
- package/src/server/serverFns/harness/github-workspace.ts +32 -25
- package/src/server/serverFns/harness/search-mention-candidates.ts +3 -1
- package/src/server/serverFns/iteration/iteration-crud.ts +1 -1
- package/src/server/serverFns/knowledge/public/legal/create.ts +3 -0
- package/src/server/serverFns/knowledge/public/legal/update.ts +8 -8
- package/src/server/serverFns/knowledge-index.ts +12 -5
- package/src/server/serverFns/project.ts +5 -11
- package/src/server/serverFns/story/__tests__/story-dependencies.test.ts +15 -4
- package/src/server/serverFns/story/__tests__/story-transfer.test.ts +20 -0
- package/src/server/serverFns/story/link-preview.ts +3 -2
- package/src/server/serverFns/story/story-children.ts +1 -1
- package/src/server/serverFns/story/story-comments.ts +1 -1
- package/src/server/serverFns/story/story-crud/bulk.ts +1 -1
- package/src/server/serverFns/story/story-crud.ts +1 -1
- package/src/server/serverFns/story/story-dependencies.ts +61 -69
- package/src/server/serverFns/story/story-groups.ts +1 -1
- package/src/server/serverFns/story/story-transfer.ts +8 -20
- package/src/server/serverFns/testcase/__tests__/automation.test.ts +21 -0
- package/src/server/serverFns/testcase/__tests__/testcase-groups.test.ts +1 -1
- package/src/server/serverFns/testcase/automation.ts +24 -1
- package/src/server/serverFns/testcase/testcase-board.ts +1 -1
- package/src/server/serverFns/testcase/testcase-crud.ts +1 -1
- package/src/server/serverFns/testcase/testcase-display-options.ts +1 -1
- package/src/server/serverFns/testcase/testcase-filter-views.ts +1 -1
- package/src/server/serverFns/testcase/types.ts +1 -1
- package/src/server/story/types.ts +7 -3
- package/src/shared/bug/__tests__/constants.test.ts +1 -1
- package/src/{components → shared}/bug/types.ts +4 -3
- package/src/{components → shared}/story/constants.ts +1 -1
- package/src/{components → shared}/story/types.ts +1 -7
- package/src/types/project.ts +1 -2
- /package/src/{components/testcase/display → shared/testcase}/field-configs.ts +0 -0
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
// You should have received a copy of the GNU Affero General Public License
|
|
16
16
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
|
|
18
|
-
import type { StoryListItem } from "
|
|
18
|
+
import type { StoryListItem } from "@/shared/story/types";
|
|
19
19
|
import type { OrderKey, OrderDirection } from "./types";
|
|
20
|
-
import { PRIORITY_RANK } from "
|
|
20
|
+
import { PRIORITY_RANK } from "@/shared/story/constants";
|
|
21
21
|
|
|
22
|
-
export function applyOrder(items:
|
|
22
|
+
export function applyOrder<T extends StoryListItem = StoryListItem>(items: T[], order: OrderKey, dir: OrderDirection = "asc"): T[] {
|
|
23
23
|
const sorted = [...items];
|
|
24
24
|
const mult = dir === "desc" ? -1 : 1;
|
|
25
25
|
switch (order) {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
// 与运行时常量为 story 规范口径落共享层 values.ts,此处仅透传保持消费方
|
|
21
21
|
// import 不变)。story 专属的 GroupNode/GroupContext 留本文件。
|
|
22
22
|
|
|
23
|
-
import type { StoryListItem, UserBrief } from "
|
|
23
|
+
import type { StoryListItem, UserBrief } from "@/shared/story/types";
|
|
24
24
|
|
|
25
25
|
export {
|
|
26
26
|
GROUP_KEYS,
|
|
@@ -42,13 +42,14 @@ export type {
|
|
|
42
42
|
PageSize,
|
|
43
43
|
} from "@/shared/list-kit/display-types";
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
// T=行类型(S14):DependencyRow 等公共行扩展可复用同一分组栈,消费方免 as 强转。
|
|
46
|
+
export interface GroupNode<T = StoryListItem> {
|
|
46
47
|
key: string;
|
|
47
48
|
label: string;
|
|
48
49
|
icon?: React.ComponentType<{ className?: string }>;
|
|
49
50
|
color?: string;
|
|
50
|
-
items:
|
|
51
|
-
subGroups?: GroupNode[];
|
|
51
|
+
items: T[];
|
|
52
|
+
subGroups?: GroupNode<T>[];
|
|
52
53
|
/** 服务端分页:该组总数 */
|
|
53
54
|
total?: number;
|
|
54
55
|
/** 服务端分页:是否还有下一页 */
|
|
@@ -17,23 +17,23 @@
|
|
|
17
17
|
|
|
18
18
|
import { useMemo } from "react";
|
|
19
19
|
import type { DisplayOptions, GroupContext, GroupNode } from "./types";
|
|
20
|
-
import type { StoryListItem } from "
|
|
20
|
+
import type { StoryListItem } from "@/shared/story/types";
|
|
21
21
|
import { applyOrder } from "./order-resolver";
|
|
22
22
|
import { groupBy } from "./group-resolver";
|
|
23
23
|
|
|
24
|
-
interface UseGroupedArgs extends GroupContext {
|
|
25
|
-
stories:
|
|
24
|
+
interface UseGroupedArgs<T extends StoryListItem> extends GroupContext {
|
|
25
|
+
stories: T[];
|
|
26
26
|
filters: DisplayOptions;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export function useGroupedStories({ stories, filters, users, labels, projects }: UseGroupedArgs): GroupNode[] {
|
|
29
|
+
export function useGroupedStories<T extends StoryListItem = StoryListItem>({ stories, filters, users, labels, projects }: UseGroupedArgs<T>): GroupNode<T>[] {
|
|
30
30
|
return useMemo(() => {
|
|
31
31
|
const ctx: GroupContext = { users, labels, projects };
|
|
32
32
|
const ordered = applyOrder(stories, filters.orderBy, filters.orderDir);
|
|
33
33
|
const groups = groupBy(ordered, filters.groupBy, ctx, filters.showEmptyGroups);
|
|
34
34
|
if (filters.subGroupBy !== "none") {
|
|
35
35
|
groups.forEach(g => {
|
|
36
|
-
g.subGroups = groupBy(g.items, filters.subGroupBy, ctx, false);
|
|
36
|
+
g.subGroups = groupBy<T>(g.items, filters.subGroupBy, ctx, false);
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
return groups;
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
import { useCallback, useMemo } from "react";
|
|
19
19
|
import { usePagedGroupsCore } from "@/hooks/use-paged-groups";
|
|
20
|
-
import type { StoryListItem, UserBrief } from "
|
|
20
|
+
import type { StoryListItem, UserBrief } from "@/shared/story/types";
|
|
21
21
|
import type { StoryFilters } from "../story-toolbar";
|
|
22
22
|
import type { FilterCondition } from "../filters";
|
|
23
23
|
import { serializeFilters } from "../filters";
|
|
@@ -25,7 +25,7 @@ import { listStoriesInGroupFn, listStoryGroupsFn, listAllGroupsItemsFn } from "@
|
|
|
25
25
|
import { resolveGroupLabel, resolveGroupIcon, resolveGroupColor } from "./group-resolver";
|
|
26
26
|
import type { DisplayOptions, GroupContext, GroupKey, GroupNode } from "./types";
|
|
27
27
|
import { applyStoryPatchToItem, type StoryPatch } from "./group-fields";
|
|
28
|
-
import { PRIORITY_RANK, STORY_PRIORITIES, STORY_STATES } from "
|
|
28
|
+
import { PRIORITY_RANK, STORY_PRIORITIES, STORY_STATES } from "@/shared/story/constants";
|
|
29
29
|
import { m } from "@/paraglide/messages.js";
|
|
30
30
|
|
|
31
31
|
/** 服务端按组分页的组节点:在 GroupNode 上标记 total/hasMore/loading */
|
|
@@ -35,6 +35,8 @@ export interface PagedGroupNode extends GroupNode {
|
|
|
35
35
|
total?: number;
|
|
36
36
|
hasMore?: boolean;
|
|
37
37
|
loading?: boolean;
|
|
38
|
+
/** S11:组首屏拉取失败显式标记(此前静默降级为空组,用户无从重试) */
|
|
39
|
+
error?: boolean;
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
export interface PagedStoriesArgs {
|
|
@@ -494,6 +496,8 @@ export function usePagedStoryGroups(args: PagedStoriesArgs): {
|
|
|
494
496
|
refresh: () => void;
|
|
495
497
|
/** 行内编辑乐观更新:未触发分组/排序规则时保持位置原地替换,仅触发排序时组内重插,触发分组时回退全量 refresh */
|
|
496
498
|
patchStory: (storyId: string, patch: StoryPatch) => void;
|
|
499
|
+
/** S11:组首屏失败后的重试入口(当前实现为全量刷新;组级精确重试需 core 支持) */
|
|
500
|
+
retry: () => void;
|
|
497
501
|
} {
|
|
498
502
|
const { filters, conditions, display, users, labels, projects, enabled = true } = args;
|
|
499
503
|
// iteration 为甘特专属维度:分页分组仅 list/board 消费(groupBy 运行时已被
|
|
@@ -616,13 +620,14 @@ export function usePagedStoryGroups(args: PagedStoriesArgs): {
|
|
|
616
620
|
skip: 0,
|
|
617
621
|
take: pageSize,
|
|
618
622
|
},
|
|
619
|
-
}).catch(() => ({ items: [] as StoryListItem[], total: sg.total ?? 0, hasMore: false })),
|
|
623
|
+
}).catch(() => ({ items: [] as StoryListItem[], total: sg.total ?? 0, hasMore: false, failed: true as const })),
|
|
620
624
|
),
|
|
621
625
|
);
|
|
622
626
|
subLoaded.forEach((res, i: number) => {
|
|
623
627
|
subScaffolds[i].items = res.items;
|
|
624
628
|
subScaffolds[i].total = res.total;
|
|
625
629
|
subScaffolds[i].hasMore = res.hasMore;
|
|
630
|
+
subScaffolds[i].error = (res as { failed?: boolean }).failed === true;
|
|
626
631
|
});
|
|
627
632
|
g.subGroups = subScaffolds;
|
|
628
633
|
g.totalCount = subScaffolds.reduce((sum, sg) => sum + (sg.total ?? sg.items.length), 0);
|
|
@@ -634,13 +639,14 @@ export function usePagedStoryGroups(args: PagedStoriesArgs): {
|
|
|
634
639
|
scaffolds.map((g) =>
|
|
635
640
|
listStoriesInGroupFn({
|
|
636
641
|
data: { ...base, groupBy, groupKey: g.key, orderBy: display.orderBy, orderDir: display.orderDir, skip: 0, take: pageSize },
|
|
637
|
-
}).catch(() => ({ items: [] as StoryListItem[], total: g.total ?? 0, hasMore: false })),
|
|
642
|
+
}).catch(() => ({ items: [] as StoryListItem[], total: g.total ?? 0, hasMore: false, failed: true as const })),
|
|
638
643
|
),
|
|
639
644
|
);
|
|
640
645
|
loaded.forEach((res, i: number) => {
|
|
641
646
|
scaffolds[i].items = res.items;
|
|
642
647
|
scaffolds[i].total = res.total;
|
|
643
648
|
scaffolds[i].hasMore = res.hasMore;
|
|
649
|
+
scaffolds[i].error = (res as { failed?: boolean }).failed === true;
|
|
644
650
|
});
|
|
645
651
|
}
|
|
646
652
|
|
|
@@ -734,5 +740,6 @@ export function usePagedStoryGroups(args: PagedStoriesArgs): {
|
|
|
734
740
|
loadMore,
|
|
735
741
|
refresh: core.refresh,
|
|
736
742
|
patchStory,
|
|
743
|
+
retry: core.refresh,
|
|
737
744
|
};
|
|
738
745
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
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
|
+
// Peek 面板内实体叠加层(用例/BUG 行的面板内打开)。纯 UI 状态形状,留在
|
|
19
|
+
// components 层:case 分支引用 server serverFns 类型与 folder-tree 组件类型
|
|
20
|
+
// (均 type-only,编译期擦除),不放 src/shared 以免 shared 反向依赖 server。
|
|
21
|
+
// bug 由实体 peek 面板按 id 自取详情。
|
|
22
|
+
export type StoryEntityOverlay =
|
|
23
|
+
| { kind: "case"; item: import("@/server/serverFns/testcase/types").TestCaseSummary; folders: import("@/components/testcase/folder-tree").FolderNodeDto[] }
|
|
24
|
+
| { kind: "bug"; id: string };
|
|
@@ -41,13 +41,13 @@ import type {
|
|
|
41
41
|
} from "@/components/shared-kit/list-kit/filters/types";
|
|
42
42
|
import { cn } from "@/lib/utils";
|
|
43
43
|
import { PriorityIcon } from "../priority-icon";
|
|
44
|
-
import { STORY_STATES, STATE_ICON, PRIORITY_LABEL, type StoryPriority, type StoryState } from "
|
|
44
|
+
import { STORY_STATES, STATE_ICON, PRIORITY_LABEL, type StoryPriority, type StoryState } from "@/shared/story/constants";
|
|
45
45
|
import { StateEditor } from "../inline-editors/state-editor";
|
|
46
46
|
import { PriorityEditor } from "../inline-editors/priority-editor";
|
|
47
47
|
import { AssigneeEditor } from "../inline-editors/assignee-editor";
|
|
48
48
|
import { LabelsEditor } from "../inline-editors/labels-editor";
|
|
49
49
|
import { TitleEditor } from "../inline-editors/title-editor";
|
|
50
|
-
import type { UserBrief } from "
|
|
50
|
+
import type { UserBrief } from "@/shared/story/types";
|
|
51
51
|
|
|
52
52
|
export { serializeFilters, deserializeFilters, OPERATOR_LABELS, generateConditionId } from "@/components/shared-kit/list-kit/filters";
|
|
53
53
|
export type { FilterOperator, FilterFieldType };
|
|
@@ -20,7 +20,7 @@ import { CircleUser, Search, Check, ArrowDownUp } from "lucide-react";
|
|
|
20
20
|
import { Input } from "@/components/ui/input";
|
|
21
21
|
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
|
22
22
|
import { UserAvatar } from "@/components/shared-kit";
|
|
23
|
-
import type { UserBrief } from "
|
|
23
|
+
import type { UserBrief } from "@/shared/story/types";
|
|
24
24
|
import { cn } from "@/lib/utils";
|
|
25
25
|
import { InlineTrigger } from "./inline-trigger";
|
|
26
26
|
import { m } from "@/paraglide/messages.js";
|
|
@@ -20,7 +20,7 @@ import { Check, Waypoints } from "lucide-react";
|
|
|
20
20
|
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
|
21
21
|
import { Button, buttonVariants } from "@/components/ui/button";
|
|
22
22
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
|
23
|
-
import { DEPENDENCY_TYPE_OPTIONS, type DependencyTypeOption } from "
|
|
23
|
+
import { DEPENDENCY_TYPE_OPTIONS, type DependencyTypeOption } from "@/shared/story/constants";
|
|
24
24
|
import { cn } from "@/lib/utils";
|
|
25
25
|
import { m } from "@/paraglide/messages.js";
|
|
26
26
|
|
|
@@ -20,8 +20,8 @@ import { GitPullRequestCreateArrow, ExternalLink, X, GitPullRequestArrow } from
|
|
|
20
20
|
import { Button } from "@/components/ui/button";
|
|
21
21
|
import { cn } from "@/lib/utils";
|
|
22
22
|
import { StorySelectDialog } from "./story-select-dialog";
|
|
23
|
-
import type { StoryState } from "
|
|
24
|
-
import type { ActivityItem } from "
|
|
23
|
+
import type { StoryState } from "@/shared/story/constants";
|
|
24
|
+
import type { ActivityItem } from "@/shared/story/types";
|
|
25
25
|
import { m } from "@/paraglide/messages.js";
|
|
26
26
|
|
|
27
27
|
interface ParentStoryEditorProps {
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
import { useState } from "react";
|
|
19
19
|
import { Check } from "lucide-react";
|
|
20
20
|
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
|
21
|
-
import { PRIORITY_LABEL } from "
|
|
22
|
-
import type { StoryPriority } from "
|
|
21
|
+
import { PRIORITY_LABEL } from "@/shared/story/constants";
|
|
22
|
+
import type { StoryPriority } from "@/shared/story/constants";
|
|
23
23
|
import { PriorityIcon } from "../priority-icon";
|
|
24
24
|
import { cn } from "@/lib/utils";
|
|
25
25
|
import { InlineTrigger } from "./inline-trigger";
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
import { useState } from "react";
|
|
19
19
|
import { Check } from "lucide-react";
|
|
20
20
|
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
|
21
|
-
import { STORY_STATES, STATE_LABEL, STATE_COLOR, STATE_ICON } from "
|
|
22
|
-
import type { StoryState } from "
|
|
21
|
+
import { STORY_STATES, STATE_LABEL, STATE_COLOR, STATE_ICON } from "@/shared/story/constants";
|
|
22
|
+
import type { StoryState } from "@/shared/story/constants";
|
|
23
23
|
import { cn } from "@/lib/utils";
|
|
24
24
|
import { InlineTrigger } from "./inline-trigger";
|
|
25
25
|
import { m } from "@/paraglide/messages.js";
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
DialogTitle,
|
|
38
38
|
} from "@/components/ui/dialog";
|
|
39
39
|
import { toast } from "@/components/ui/toast";
|
|
40
|
-
import type { ActivityItem } from "
|
|
40
|
+
import type { ActivityItem } from "@/shared/story/types";
|
|
41
41
|
import {
|
|
42
42
|
listProjectStoriesFn,
|
|
43
43
|
transferStoryAsChildFn,
|
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
STORY_PRIORITIES,
|
|
52
52
|
type StoryState,
|
|
53
53
|
type DependencyTypeOption,
|
|
54
|
-
} from "
|
|
54
|
+
} from "@/shared/story/constants";
|
|
55
55
|
import { FilterCheckPopover } from "../filters/filter-check-popover";
|
|
56
56
|
import { PriorityIcon } from "../priority-icon";
|
|
57
57
|
import { DependencyTypeSelect } from "./dependency-type-select";
|
|
@@ -35,13 +35,13 @@ import {
|
|
|
35
35
|
getLinkedDocsFn,
|
|
36
36
|
} from "@/server/serverFns/story";
|
|
37
37
|
import { listIterationsFn } from "@/server/serverFns/iteration";
|
|
38
|
-
import type { StoryDetail, UserBrief, CommentWithReplies, ActivityItem, RelationsData } from "
|
|
38
|
+
import type { StoryDetail, UserBrief, CommentWithReplies, ActivityItem, RelationsData } from "@/shared/story/types";
|
|
39
39
|
import { applyStoryPatchToItem, type StoryPatch } from "./display/group-fields";
|
|
40
|
-
import type { StoryState } from "
|
|
40
|
+
import type { StoryState } from "@/shared/story/constants";
|
|
41
41
|
import { StoryDetailBody } from "./detail/story-detail-body";
|
|
42
42
|
import { TestCasePeekPanel } from "@/components/testcase/peek-panel";
|
|
43
43
|
import { BugPeekPanel } from "@/components/bug/peek-panel";
|
|
44
|
-
import type { StoryEntityOverlay } from "./
|
|
44
|
+
import type { StoryEntityOverlay } from "./entity-overlay";
|
|
45
45
|
import { StoryPanelHeader } from "./story-panel-header";
|
|
46
46
|
import type { PeekRelationKind, PeekBreadcrumbItem } from "./story-panel-header";
|
|
47
47
|
import type { PeekMode } from "@/components/shared-kit/peek/peek-mode";
|
|
@@ -252,13 +252,14 @@ export function StoryPeekPanel({
|
|
|
252
252
|
await Promise.all([detailP, restP]);
|
|
253
253
|
if (historyRef.current.length === 0) {
|
|
254
254
|
setRootIdentifier(story.identifier);
|
|
255
|
-
|
|
255
|
+
// StoryDetail.projectId 为 string|null,PeekLocation 以 undefined 表无项目
|
|
256
|
+
setRootProjectId(story.projectId ?? undefined);
|
|
256
257
|
} else {
|
|
257
258
|
// 回填当前层 projectId:跨项目父子/依赖跳转时,面包屑各级需显示各自项目图标
|
|
258
259
|
setHistory((prev) => {
|
|
259
260
|
const last = prev[prev.length - 1];
|
|
260
261
|
if (!last || last.projectId === story.projectId) return prev;
|
|
261
|
-
return prev.map((h, i) => (i === prev.length - 1 ? { ...h, projectId: story.projectId } : h));
|
|
262
|
+
return prev.map((h, i) => (i === prev.length - 1 ? { ...h, projectId: story.projectId ?? undefined } : h));
|
|
262
263
|
});
|
|
263
264
|
}
|
|
264
265
|
const relationsData: RelationsData = {
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
|
|
18
18
|
import { cn } from "@/lib/utils";
|
|
19
|
-
import { PRIORITY_ICON } from "
|
|
20
|
-
import type { StoryPriority } from "
|
|
19
|
+
import { PRIORITY_ICON } from "@/shared/story/constants";
|
|
20
|
+
import type { StoryPriority } from "@/shared/story/constants";
|
|
21
21
|
|
|
22
22
|
export const PRIORITY_COLOR: Record<StoryPriority, string> = {
|
|
23
23
|
urgent: "text-red-600 dark:text-red-400",
|
|
@@ -46,7 +46,7 @@ function uploadResponse(body: Record<string, unknown>) {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
import { AttachmentManageDialog } from "../attachment-manage-dialog";
|
|
49
|
-
import type { StoryAttachmentItem } from "
|
|
49
|
+
import type { StoryAttachmentItem } from "@/shared/story/types";
|
|
50
50
|
|
|
51
51
|
const ATTS: StoryAttachmentItem[] = [
|
|
52
52
|
{ id: "a1", fileName: "设计稿.png", fileSize: 2048, mimeType: "image/png", storageUrl: "/mock-storage/1" },
|
|
@@ -41,7 +41,7 @@ vi.mock("@/components/ui/toast", () => ({
|
|
|
41
41
|
;
|
|
42
42
|
|
|
43
43
|
import { DesignSelectDialog } from "../design-select-dialog";
|
|
44
|
-
import type { DesignBrief } from "
|
|
44
|
+
import type { DesignBrief } from "@/shared/story/types";
|
|
45
45
|
|
|
46
46
|
const design = (id: string, title: string, icon = "file"): DesignBrief => ({ id, title, icon });
|
|
47
47
|
|
|
@@ -43,7 +43,7 @@ vi.mock("@/components/ui/toast", () => ({
|
|
|
43
43
|
;
|
|
44
44
|
|
|
45
45
|
import { KnowledgeSelectDialog } from "../knowledge-select-dialog";
|
|
46
|
-
import type { DocBrief } from "
|
|
46
|
+
import type { DocBrief } from "@/shared/story/types";
|
|
47
47
|
|
|
48
48
|
const doc = (id: string, title: string, parentId: string | null = null): DocBrief => ({
|
|
49
49
|
id,
|
|
@@ -41,7 +41,7 @@ vi.mock("@/components/ui/toast", () => ({
|
|
|
41
41
|
;
|
|
42
42
|
|
|
43
43
|
import { LinkManageDialog } from "../link-manage-dialog";
|
|
44
|
-
import type { StoryLinkItem } from "
|
|
44
|
+
import type { StoryLinkItem } from "@/shared/story/types";
|
|
45
45
|
|
|
46
46
|
const LINKS: StoryLinkItem[] = [
|
|
47
47
|
{ id: "l1", url: "https://a.com", title: "站点A", description: null },
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
import { Textarea } from "@/components/ui/textarea";
|
|
29
29
|
import { getFileTypeIcon } from "./format";
|
|
30
30
|
import { FilePreview } from "./file-preview";
|
|
31
|
-
import type { StoryAttachmentItem } from "
|
|
31
|
+
import type { StoryAttachmentItem } from "@/shared/story/types";
|
|
32
32
|
import { m } from "@/paraglide/messages.js";
|
|
33
33
|
import { toastError } from "@/lib/toast-error";
|
|
34
34
|
|
|
@@ -49,7 +49,7 @@ export interface AttachmentManageDialogProps {
|
|
|
49
49
|
data: StoryAttachmentItem[];
|
|
50
50
|
onUpdate: (attachments: StoryAttachmentItem[]) => void;
|
|
51
51
|
/** 上传附件产生的活动,供时间线即时追加 */
|
|
52
|
-
onActivity?: (activity: import("
|
|
52
|
+
onActivity?: (activity: import("@/shared/story/types").ActivityItem) => void;
|
|
53
53
|
/** 编辑模式:预填充现有附件,隐藏继续上传按钮和上传区 */
|
|
54
54
|
editItem?: StoryAttachmentItem | null;
|
|
55
55
|
}
|
|
@@ -242,7 +242,7 @@ export function AttachmentManageDialog({
|
|
|
242
242
|
if (staged.length === 0 || uploading) return;
|
|
243
243
|
setUploading(true);
|
|
244
244
|
const desc = description.trim();
|
|
245
|
-
const added: Array<StoryAttachmentItem & { activity?: import("
|
|
245
|
+
const added: Array<StoryAttachmentItem & { activity?: import("@/shared/story/types").ActivityItem }> = [];
|
|
246
246
|
for (const item of staged) {
|
|
247
247
|
// 跳过重复文件
|
|
248
248
|
if (duplicateIndexes.has(staged.indexOf(item))) continue;
|
|
@@ -263,7 +263,7 @@ export function AttachmentManageDialog({
|
|
|
263
263
|
}
|
|
264
264
|
const json = await res.json() as Record<string, unknown>;
|
|
265
265
|
if ((json.duplicated as boolean | undefined) === true) continue;
|
|
266
|
-
added.push(json as unknown as StoryAttachmentItem & { activity?: import("
|
|
266
|
+
added.push(json as unknown as StoryAttachmentItem & { activity?: import("@/shared/story/types").ActivityItem });
|
|
267
267
|
} catch (err) {
|
|
268
268
|
toastError(err, m.story_attachmentDialog_removeFailed());
|
|
269
269
|
}
|
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
} from "@/server/serverFns/story";
|
|
42
42
|
import { LucideIconByName } from "@/components/shared-kit/icons/lucide-icon-picker/lucide-icon-by-name";
|
|
43
43
|
import { useLinkedSelection } from "./use-linked-selection";
|
|
44
|
-
import type { DesignBrief } from "
|
|
44
|
+
import type { DesignBrief } from "@/shared/story/types";
|
|
45
45
|
import { m } from "@/paraglide/messages.js";
|
|
46
46
|
import { toastError } from "@/lib/toast-error";
|
|
47
47
|
|
|
@@ -56,7 +56,7 @@ export interface DesignSelectDialogProps {
|
|
|
56
56
|
linkedDesigns: DesignBrief[];
|
|
57
57
|
onUpdate: (designs: DesignBrief[]) => void;
|
|
58
58
|
/** 关联/解联产生的活动,供时间线即时追加 */
|
|
59
|
-
onActivity?: (activity: import("
|
|
59
|
+
onActivity?: (activity: import("@/shared/story/types").ActivityItem) => void;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
function dialogTitle(mode: DesignSelectMode): string {
|
|
@@ -41,7 +41,7 @@ import { GENERAL_GROUPS, type GeneralGroup } from "@/server/serverFns/story/kb-g
|
|
|
41
41
|
import { generalGroupLabel } from "./general-groups";
|
|
42
42
|
import { useLinkedSelection } from "./use-linked-selection";
|
|
43
43
|
import { KbFilterPopover, type KbFilter } from "@/components/knowledge/kb-filter-popover";
|
|
44
|
-
import type { DocBrief } from "
|
|
44
|
+
import type { DocBrief } from "@/shared/story/types";
|
|
45
45
|
import { m } from "@/paraglide/messages.js";
|
|
46
46
|
import { toastError } from "@/lib/toast-error";
|
|
47
47
|
|
|
@@ -65,7 +65,7 @@ export interface KnowledgeSelectDialogProps {
|
|
|
65
65
|
linkedDocs: DocBrief[];
|
|
66
66
|
onUpdate: (docs: DocBrief[]) => void;
|
|
67
67
|
/** 关联知识库文档产生的活动,供时间线即时追加 */
|
|
68
|
-
onActivity?: (activity: import("
|
|
68
|
+
onActivity?: (activity: import("@/shared/story/types").ActivityItem) => void;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
export function KnowledgeSelectDialog({
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
DialogTitle,
|
|
29
29
|
} from "@/components/ui/dialog";
|
|
30
30
|
import { addLinkFn, updateLinkFn } from "@/server/serverFns/story";
|
|
31
|
-
import type { StoryLinkItem } from "
|
|
31
|
+
import type { StoryLinkItem } from "@/shared/story/types";
|
|
32
32
|
import { m } from "@/paraglide/messages.js";
|
|
33
33
|
import { toastError } from "@/lib/toast-error";
|
|
34
34
|
|
|
@@ -39,7 +39,7 @@ export interface LinkManageDialogProps {
|
|
|
39
39
|
data: StoryLinkItem[];
|
|
40
40
|
onUpdate: (links: StoryLinkItem[]) => void;
|
|
41
41
|
/** 添加链接产生的活动,供时间线即时追加 */
|
|
42
|
-
onActivity?: (activity: import("
|
|
42
|
+
onActivity?: (activity: import("@/shared/story/types").ActivityItem) => void;
|
|
43
43
|
/** 非空时进入编辑态(由合并面板「编辑」触发) */
|
|
44
44
|
initialEdit?: StoryLinkItem | null;
|
|
45
45
|
}
|
|
@@ -39,7 +39,7 @@ import { PriorityEditor, StateEditor, AssigneeEditor, DateEditor, LabelsEditor,
|
|
|
39
39
|
import { NameConfirmDialog } from "@/components/shared-kit/dialogs/name-confirm-dialog";
|
|
40
40
|
import { cn } from "@/lib/utils";
|
|
41
41
|
import { LucideIconByName } from "@/components/shared-kit/icons/lucide-icon-picker/lucide-icon-by-name";
|
|
42
|
-
import { dependencyTypeOption } from "
|
|
42
|
+
import { dependencyTypeOption } from "@/shared/story/constants";
|
|
43
43
|
import type { DisplayProperty } from "../display/types";
|
|
44
44
|
import type { StoryPatch } from "../display/group-fields";
|
|
45
45
|
import type {
|
|
@@ -47,8 +47,8 @@ import type {
|
|
|
47
47
|
UserBrief,
|
|
48
48
|
DependencyEdgeType,
|
|
49
49
|
DependencyGroup,
|
|
50
|
-
} from "
|
|
51
|
-
import type { DependencyTypeOption } from "
|
|
50
|
+
} from "@/shared/story/types";
|
|
51
|
+
import type { DependencyTypeOption } from "@/shared/story/constants";
|
|
52
52
|
import { m } from "@/paraglide/messages.js";
|
|
53
53
|
import { toastError } from "@/lib/toast-error";
|
|
54
54
|
|
|
@@ -20,7 +20,7 @@ import { flexRender, useTable, type SortingState } from "@tanstack/react-table";
|
|
|
20
20
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
21
21
|
import { ArrowDown, ArrowUp, ChevronDown } from "lucide-react";
|
|
22
22
|
import { createStoryColumns, storyTableFeatures } from "./columns";
|
|
23
|
-
import type { StoryListItem } from "
|
|
23
|
+
import type { StoryListItem } from "@/shared/story/types";
|
|
24
24
|
import { ALL_DISPLAY_PROPERTIES } from "./display/types";
|
|
25
25
|
import type { DisplayProperty, OrderKey } from "./display/types";
|
|
26
26
|
import { InfiniteScrollSentinel } from "@/components/infinite-scroll-sentinel";
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
buildDefaultView, DEFAULT_VIEW_ID, type SavedView,
|
|
37
37
|
} from "./views/view-types";
|
|
38
38
|
import { isStoryView, type StoryView } from "./views/view-switcher";
|
|
39
|
-
import type { UserBrief, StoryListItem } from "
|
|
39
|
+
import type { UserBrief, StoryListItem } from "@/shared/story/types";
|
|
40
40
|
import type { DisplayOptions } from "./display/types";
|
|
41
41
|
import { applyStoryPatchToItem, type StoryPatch } from "./display/group-fields";
|
|
42
42
|
import { useDisplayOptions } from "./display/use-display-options";
|
|
@@ -39,7 +39,7 @@ import type { DisplayOptions } from "./display/types";
|
|
|
39
39
|
import { StoryFilterToggle, StoryFilterRow, AppliedFilters, type FilterCondition } from "./filters";
|
|
40
40
|
import { LucideIconByName } from "@/components/shared-kit/icons/lucide-icon-picker/lucide-icon-by-name";
|
|
41
41
|
import { CreateProjectDialog } from "@/components/project/create-project-dialog";
|
|
42
|
-
import type { UserBrief } from "
|
|
42
|
+
import type { UserBrief } from "@/shared/story/types";
|
|
43
43
|
import { m } from "@/paraglide/messages.js";
|
|
44
44
|
import { useToolbarSearch } from "@/hooks/use-toolbar-search";
|
|
45
45
|
import { cn } from "@/lib/utils";
|
|
@@ -41,11 +41,12 @@ interface TransferStoryPopoverProps {
|
|
|
41
41
|
storyIds?: string[];
|
|
42
42
|
currentProjectId?: string | null;
|
|
43
43
|
projects: { id: string; name: string; displayId?: string | null; icon: string }[];
|
|
44
|
-
onTransferred: (updatedStories?: Array<{ id: string; identifier: string; projectId: string; parentId: string | null }>) => void;
|
|
44
|
+
onTransferred: (updatedStories?: Array<{ id: string; identifier: string; projectId: string | null; parentId: string | null }>) => void;
|
|
45
45
|
trigger?: React.ReactNode;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
// projectId 诚实可空(公共行口径);当前消费方仅清选择+刷新,不读载荷
|
|
49
|
+
type TransferredStory = { id: string; identifier: string; projectId: string | null; parentId: string | null };
|
|
49
50
|
|
|
50
51
|
export function TransferStoryPopover({
|
|
51
52
|
storyId,
|
|
@@ -22,7 +22,7 @@ import { CalendarView } from "../calendar-view";
|
|
|
22
22
|
import { resolveDragBlockedToast } from "../calendar/drag-blocked";
|
|
23
23
|
import { formatDateLocal } from "@/lib/datetime";
|
|
24
24
|
import { m } from "@/paraglide/messages.js";
|
|
25
|
-
import type { StoryListItem } from "
|
|
25
|
+
import type { StoryListItem } from "@/shared/story/types";
|
|
26
26
|
|
|
27
27
|
function story(
|
|
28
28
|
id: string,
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
// 原分区」而不发 patch,表现为拖到「已取消-高」却落进「已取消-低」。
|
|
21
21
|
import { describe, expect, it } from "vitest";
|
|
22
22
|
import { resolveDropSubKey, resolveSubKeyForDrop } from "../kanban-view";
|
|
23
|
-
import type { StoryListItem } from "
|
|
23
|
+
import type { StoryListItem } from "@/shared/story/types";
|
|
24
24
|
|
|
25
25
|
const card = (id: string) => ({ id }) as StoryListItem;
|
|
26
26
|
|
|
@@ -35,9 +35,9 @@ import { render, screen, waitFor } from "@testing-library/react";
|
|
|
35
35
|
import userEvent from "@testing-library/user-event";
|
|
36
36
|
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
37
37
|
import { KanbanView } from "../kanban-view";
|
|
38
|
-
import { PRIORITY_LABEL } from "
|
|
38
|
+
import { PRIORITY_LABEL } from "@/shared/story/constants";
|
|
39
39
|
import type { DisplayOptions, GroupNode } from "../../display/types";
|
|
40
|
-
import type { StoryListItem } from "
|
|
40
|
+
import type { StoryListItem } from "@/shared/story/types";
|
|
41
41
|
|
|
42
42
|
vi.mock("@tanstack/react-start", () => ({
|
|
43
43
|
useServerFn: (fn: unknown) => fn,
|
|
@@ -33,7 +33,7 @@ import { act, render } from "@testing-library/react";
|
|
|
33
33
|
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
34
34
|
import { KanbanView } from "../kanban-view";
|
|
35
35
|
import type { DisplayOptions, GroupNode } from "../../display/types";
|
|
36
|
-
import type { StoryListItem } from "
|
|
36
|
+
import type { StoryListItem } from "@/shared/story/types";
|
|
37
37
|
|
|
38
38
|
vi.mock("@tanstack/react-start", () => ({
|
|
39
39
|
useServerFn: (fn: unknown) => fn,
|
|
@@ -60,7 +60,7 @@ vi.mock("@/server/serverFns/iteration", () => ({
|
|
|
60
60
|
import { TimelineView } from "../timeline-view";
|
|
61
61
|
import { formatDateLocal } from "@/lib/datetime";
|
|
62
62
|
import type { GroupKey } from "../../display/types";
|
|
63
|
-
import type { StoryListItem } from "
|
|
63
|
+
import type { StoryListItem } from "@/shared/story/types";
|
|
64
64
|
|
|
65
65
|
function story(
|
|
66
66
|
id: string,
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
fromGanttRangeToStoryDates,
|
|
23
23
|
} from "../mappers";
|
|
24
24
|
import { parseDate } from "@/lib/datetime";
|
|
25
|
-
import type { StoryListItem } from "
|
|
25
|
+
import type { StoryListItem } from "@/shared/story/types";
|
|
26
26
|
|
|
27
27
|
/** 需求样本工厂:固定 id/identifier/name/state,其余按需覆盖 */
|
|
28
28
|
const mkStory = (over: Partial<StoryListItem> = {}): StoryListItem => ({
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
import { addDays, startOfDay } from "date-fns";
|
|
38
38
|
import { parseDate } from "@/lib/datetime";
|
|
39
39
|
import type { CalendarEvent } from "@/components/reui/event-calendar/event-calendar-types";
|
|
40
|
-
import type { StoryListItem } from "
|
|
40
|
+
import type { StoryListItem } from "@/shared/story/types";
|
|
41
41
|
// 甘特导出单一事实源(禁止复制定义——复制即两份漂移)
|
|
42
42
|
import { STORY_STATE_GANTT_COLOR } from "../timeline/mappers";
|
|
43
43
|
|
|
@@ -78,7 +78,7 @@ import type {
|
|
|
78
78
|
EventCalendarViewSettings,
|
|
79
79
|
} from "@/components/reui/event-calendar/event-calendar-types";
|
|
80
80
|
import type { WeekStartsOn } from "@/components/reui/event-calendar/event-calendar-lib";
|
|
81
|
-
import type { StoryListItem } from "
|
|
81
|
+
import type { StoryListItem } from "@/shared/story/types";
|
|
82
82
|
import { applyOrder } from "../display/order-resolver";
|
|
83
83
|
import type { OrderKey } from "../display/types";
|
|
84
84
|
import {
|
|
@@ -38,7 +38,7 @@ import { StoryFilterRow } from "../filters";
|
|
|
38
38
|
import { createDefaultCondition, type FilterCondition } from "../filters/field-configs";
|
|
39
39
|
import { VIEW_ICONS, type SavedView, type ViewProjectInfo } from "./view-types";
|
|
40
40
|
import { ViewIcon } from "@/components/shared-kit/views/view-icon";
|
|
41
|
-
import type { UserBrief } from "
|
|
41
|
+
import type { UserBrief } from "@/shared/story/types";
|
|
42
42
|
import { m } from "@/paraglide/messages.js";
|
|
43
43
|
|
|
44
44
|
export interface CreateViewDialogPayload {
|