Persist GitLab tracking metadata and surface it across task APIs and dashboard views. - add task-store schema, migration, and update helpers for linked GitLab items and stale state - expose validated GitLab tracking updates through task workflow routes and legacy task payloads - render GitLab badges, detail-panel metadata, open/unlink actions, styling, i18n strings, and docs - cover persistence, route validation, task card badges, and task detail interactions with tests - add a patch changeset for the published Fusion package Files changed: .changeset/fn-7425-gitlab-tracking.md | 7 ++ docs/cli-reference.md | 2 +- docs/dashboard-guide.md | 3 + packages/core/src/__tests__/db-migrate.test.ts | 29 +++++ .../src/__tests__/store-gitlab-tracking.test.ts | 138 +++++++++++++++++++++ packages/core/src/db.ts | 10 +- packages/core/src/gitlab-tracking.ts | 10 ++ packages/core/src/index.ts | 3 +- packages/core/src/store.ts | 135 +++++++++++++++++++- packages/core/src/types.ts | 49 ++++++++ packages/dashboard/app/api/legacy.ts | 3 + packages/dashboard/app/components/GitLabBadge.tsx | 33 +++++ packages/dashboard/app/components/TaskCard.tsx | 7 +- .../dashboard/app/components/TaskCardBadge.tsx | 15 ++- .../dashboard/app/components/TaskDetailModal.css | 47 +++++-- .../dashboard/app/components/TaskDetailModal.tsx | 134 +++++++++++++++++++- .../app/components/__tests__/TaskCard.test.tsx | 49 ++++++++ .../TaskDetailModal.gitlab-tracking.test.tsx | 121 ++++++++++++++++++ .../__tests__/TaskDetailModal.test-helpers.ts | 1 + packages/dashboard/app/styles.css | 9 ++ .../src/__tests__/routes-tasks-ops.test.ts | 136 ++++++++++++++++++++ packages/dashboard/src/gitlab.ts | 24 +++- packages/dashboard/src/routes/register-gitlab.ts | 1 + .../src/routes/register-task-workflow-routes.ts | 106 +++++++++++++++- packages/i18n/locales/en/app.json | 31 +++++ packages/i18n/src/resources.d.ts | 31 +++++ 26 files changed, 1106 insertions(+), 28 deletions(-) Fusion-Task-Id: FN-7425 Fusion-Task-Lineage: 9b5e6005-7284-402e-995c-553be2275eff Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
82 lines
2.2 KiB
TypeScript
82 lines
2.2 KiB
TypeScript
import { memo, useEffect } from "react";
|
|
import type { IssueInfo, PrInfo, TaskGitLabTracking } from "@fusion/core";
|
|
import { useBadgeWebSocket } from "../hooks/useBadgeWebSocket";
|
|
import { GitHubBadge } from "./GitHubBadge";
|
|
import { GitLabBadge } from "./GitLabBadge";
|
|
|
|
export function pickPreferredBadge<T extends { lastCheckedAt?: string }>(
|
|
liveValue: T | null | undefined,
|
|
liveTimestamp: string | undefined,
|
|
taskValue: T | undefined,
|
|
taskTimestamp: string | undefined,
|
|
): T | undefined {
|
|
if (liveValue == null) {
|
|
return taskValue;
|
|
}
|
|
|
|
if (!liveTimestamp) {
|
|
return taskValue ?? liveValue;
|
|
}
|
|
|
|
if (!taskTimestamp || liveTimestamp >= taskTimestamp) {
|
|
return liveValue;
|
|
}
|
|
|
|
return taskValue;
|
|
}
|
|
|
|
interface TaskCardBadgeProps {
|
|
taskId: string;
|
|
prInfo?: PrInfo;
|
|
issueInfo?: IssueInfo;
|
|
gitlabTracking?: TaskGitLabTracking;
|
|
updatedAt: string;
|
|
isInViewport: boolean;
|
|
projectId?: string;
|
|
}
|
|
|
|
function TaskCardBadgeComponent({ taskId, prInfo, issueInfo, gitlabTracking, updatedAt, isInViewport, projectId }: TaskCardBadgeProps) {
|
|
const { badgeUpdates, subscribeToBadge, unsubscribeFromBadge } = useBadgeWebSocket(projectId);
|
|
const hasGitHubBadge = Boolean(prInfo || issueInfo);
|
|
|
|
useEffect(() => {
|
|
if (!hasGitHubBadge || !isInViewport) {
|
|
unsubscribeFromBadge(taskId);
|
|
return;
|
|
}
|
|
|
|
subscribeToBadge(taskId);
|
|
return () => {
|
|
unsubscribeFromBadge(taskId);
|
|
};
|
|
}, [hasGitHubBadge, isInViewport, projectId, subscribeToBadge, taskId, unsubscribeFromBadge]);
|
|
|
|
const liveBadgeData = badgeUpdates.get(`${projectId ?? "default"}:${taskId}`);
|
|
const livePrInfo = pickPreferredBadge<PrInfo>(
|
|
liveBadgeData?.prInfo,
|
|
liveBadgeData?.timestamp,
|
|
prInfo,
|
|
prInfo?.lastCheckedAt ?? updatedAt,
|
|
);
|
|
const liveIssueInfo = pickPreferredBadge<IssueInfo>(
|
|
liveBadgeData?.issueInfo,
|
|
liveBadgeData?.timestamp,
|
|
issueInfo,
|
|
issueInfo?.lastCheckedAt ?? updatedAt,
|
|
);
|
|
|
|
if (!livePrInfo && !liveIssueInfo && !gitlabTracking?.item) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<GitHubBadge prInfo={livePrInfo} issueInfo={liveIssueInfo} />
|
|
<GitLabBadge item={gitlabTracking?.item} />
|
|
</>
|
|
);
|
|
}
|
|
|
|
export const TaskCardBadge = memo(TaskCardBadgeComponent);
|
|
TaskCardBadge.displayName = "TaskCardBadge";
|