Delay dashboard GitHub setup warnings until the project grace period expires while keeping AI setup warnings immediate. - Add per-project GitHub warning delay state and persistence. - Route dashboard GitHub warnings to Settings → Authentication with a Connect GitHub action. - Hide non-actionable GitHub-only warnings in the New Task modal and update localized copy, docs, and tests. Files changed: .changeset/fn-7475-github-setup-warning.md | 7 ++ docs/dashboard-guide.md | 6 + packages/dashboard/app/App.tsx | 11 +- packages/dashboard/app/components/NewTaskModal.tsx | 8 +- .../app/components/SetupWarningBanner.css | 10 ++ .../app/components/SetupWarningBanner.tsx | 18 ++- .../app/components/__tests__/NewTaskModal.test.tsx | 46 ++++++- .../__tests__/SetupWarningBanner.test.tsx | 40 ++++++ .../app/components/dashboard/DashboardBanners.tsx | 3 + .../dashboard/__tests__/DashboardBanners.test.tsx | 125 ++++++++++++++++++- .../dashboard/app/components/dashboard/types.ts | 1 + .../__tests__/useGithubSetupWarningDelay.test.ts | 134 +++++++++++++++++++++ .../app/hooks/useGithubSetupWarningDelay.ts | 96 +++++++++++++++ packages/dashboard/app/utils/projectStorage.ts | 1 + packages/i18n/locales/en/app.json | 5 +- packages/i18n/locales/es/app.json | 5 +- packages/i18n/locales/fr/app.json | 5 +- packages/i18n/locales/ko/app.json | 5 +- packages/i18n/locales/zh-CN/app.json | 5 +- packages/i18n/locales/zh-TW/app.json | 5 +- packages/i18n/src/resources.d.ts | 127 +++++++++++++------ 21 files changed, 606 insertions(+), 57 deletions(-) Fusion-Task-Id: FN-7475 Fusion-Task-Lineage: 5bf1fffa-b58c-42a1-b170-367a4c20eaaf Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
97 lines
2.7 KiB
TypeScript
97 lines
2.7 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
import { getScopedItem, removeScopedItem, setScopedItem } from "../utils/projectStorage";
|
|
|
|
export const GITHUB_SETUP_WARNING_DELAY_MS = 86_400_000;
|
|
export const GITHUB_SETUP_WARNING_MISSING_SINCE_KEY = "kb-github-setup-warning-missing-since";
|
|
|
|
export interface UseGithubSetupWarningDelayOptions {
|
|
projectId?: string;
|
|
hasGithub: boolean;
|
|
loading: boolean;
|
|
now?: () => number;
|
|
}
|
|
|
|
function readMissingSince(projectId: string): number | null {
|
|
try {
|
|
const stored = getScopedItem(GITHUB_SETUP_WARNING_MISSING_SINCE_KEY, projectId);
|
|
if (!stored) {
|
|
return null;
|
|
}
|
|
|
|
const parsed = Number(stored);
|
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function writeMissingSince(projectId: string, missingSince: number): void {
|
|
try {
|
|
setScopedItem(GITHUB_SETUP_WARNING_MISSING_SINCE_KEY, String(missingSince), projectId);
|
|
} catch {
|
|
// Best effort only: storage failures must not break dashboard rendering.
|
|
}
|
|
}
|
|
|
|
function clearMissingSince(projectId: string): void {
|
|
try {
|
|
removeScopedItem(GITHUB_SETUP_WARNING_MISSING_SINCE_KEY, projectId);
|
|
} catch {
|
|
// Best effort only: storage failures must not break dashboard rendering.
|
|
}
|
|
}
|
|
|
|
export function useGithubSetupWarningDelay({
|
|
projectId,
|
|
hasGithub,
|
|
loading,
|
|
now = Date.now,
|
|
}: UseGithubSetupWarningDelayOptions): boolean {
|
|
const [showWarning, setShowWarning] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if (!projectId) {
|
|
setShowWarning(false);
|
|
return undefined;
|
|
}
|
|
|
|
if (loading) {
|
|
setShowWarning(false);
|
|
return undefined;
|
|
}
|
|
|
|
if (hasGithub) {
|
|
clearMissingSince(projectId);
|
|
setShowWarning(false);
|
|
return undefined;
|
|
}
|
|
|
|
/*
|
|
FNXC:SetupWarning 2026-07-03-00:00:
|
|
GitHub setup prompts are intentionally delayed for one day after a project first observes GitHub missing. AI-provider warnings remain immediate, but GitHub import/auth nudges should not interrupt new projects during their first 24 hours.
|
|
*/
|
|
const observedAt = now();
|
|
const existingMissingSince = readMissingSince(projectId);
|
|
const missingSince = existingMissingSince ?? observedAt;
|
|
if (existingMissingSince == null) {
|
|
writeMissingSince(projectId, missingSince);
|
|
}
|
|
|
|
const elapsedMs = observedAt - missingSince;
|
|
if (elapsedMs >= GITHUB_SETUP_WARNING_DELAY_MS) {
|
|
setShowWarning(true);
|
|
return undefined;
|
|
}
|
|
|
|
setShowWarning(false);
|
|
const timeoutMs = GITHUB_SETUP_WARNING_DELAY_MS - elapsedMs;
|
|
const timer = window.setTimeout(() => {
|
|
setShowWarning(true);
|
|
}, timeoutMs);
|
|
|
|
return () => window.clearTimeout(timer);
|
|
}, [hasGithub, loading, now, projectId]);
|
|
|
|
return showWarning;
|
|
}
|