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>
107 lines
3.3 KiB
TypeScript
107 lines
3.3 KiB
TypeScript
import "./SetupWarningBanner.css";
|
|
import { X } from "lucide-react";
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
interface SetupWarningBannerProps {
|
|
/** Whether an AI provider is connected */
|
|
hasAiProvider: boolean;
|
|
/** Whether GitHub is connected */
|
|
hasGithub: boolean;
|
|
/** Whether the GitHub warning item is allowed to render after any grace period */
|
|
showGithubWarning?: boolean;
|
|
/** Optional: compact mode for inline use (QuickEntryBox) */
|
|
compact?: boolean;
|
|
/** Optional callback to open GitHub/authentication setup */
|
|
onConnectGithub?: () => void;
|
|
/** Optional callback to dismiss the banner */
|
|
onDismiss?: () => void;
|
|
}
|
|
|
|
interface WarningItem {
|
|
key: "ai" | "github";
|
|
title: string;
|
|
description: string;
|
|
}
|
|
|
|
export function SetupWarningBanner({
|
|
hasAiProvider,
|
|
hasGithub,
|
|
showGithubWarning = !hasGithub,
|
|
compact = false,
|
|
onDismiss,
|
|
onConnectGithub,
|
|
}: SetupWarningBannerProps) {
|
|
const { t } = useTranslation("app");
|
|
const shouldShowGithubWarning = !hasGithub && showGithubWarning;
|
|
if (hasAiProvider && !shouldShowGithubWarning) {
|
|
return null;
|
|
}
|
|
|
|
const dismissButton = onDismiss ? (
|
|
<button
|
|
type="button"
|
|
className="setup-warning-banner__dismiss touch-target"
|
|
aria-label={t("setup.dismissWarning", "Dismiss setup warning")}
|
|
onClick={onDismiss}
|
|
>
|
|
<X size={16} aria-hidden="true" />
|
|
</button>
|
|
) : null;
|
|
|
|
if (compact) {
|
|
return (
|
|
<div
|
|
className={`setup-warning-banner setup-warning-banner--compact${onDismiss ? " setup-warning-banner--dismissible" : ""}`}
|
|
role="status"
|
|
aria-live="polite"
|
|
>
|
|
<p className="setup-warning-banner__compact-text">
|
|
{t("setup.compactWarning", "⚠ Setup incomplete — AI and/or GitHub features will be limited.")}
|
|
</p>
|
|
{dismissButton}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const warningItems: WarningItem[] = [];
|
|
|
|
if (!hasAiProvider) {
|
|
warningItems.push({
|
|
key: "ai",
|
|
title: t("setup.noAiProvider", "No AI provider connected"),
|
|
description: t("setup.noAiProviderDesc", "AI agents won't be able to work on tasks until you connect a provider. Set one up in Settings → AI Setup."),
|
|
});
|
|
}
|
|
|
|
if (shouldShowGithubWarning) {
|
|
warningItems.push({
|
|
key: "github",
|
|
title: t("setup.noGithub", "GitHub not connected"),
|
|
description: t("setup.noGithubDesc", "You won't be able to import issues from GitHub, but you can still create tasks manually."),
|
|
});
|
|
}
|
|
|
|
return (
|
|
<div
|
|
className={`setup-warning-banner${onDismiss ? " setup-warning-banner--dismissible" : ""}`}
|
|
role="status"
|
|
aria-live="polite"
|
|
>
|
|
{dismissButton}
|
|
{warningItems.map((warning) => (
|
|
<div key={warning.key} className="setup-warning-banner__item">
|
|
<strong className="setup-warning-banner__title">{warning.title}</strong>
|
|
<p className="setup-warning-banner__description">{warning.description}</p>
|
|
{warning.key === "github" && onConnectGithub ? (
|
|
<div className="setup-warning-banner__actions">
|
|
<button type="button" className="btn btn-sm btn-primary" onClick={onConnectGithub}>
|
|
{t("setup.connectGithub", "Connect GitHub")}
|
|
</button>
|
|
</div>
|
|
) : null}
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|