FN-7874: add Discord get-help link and central-DB wording to storage banner
Adds a hardened Discord support link and clarifies that project databases move to the central Fusion database in the storage update notice banner. - Add a "Get help" button/link to the Fusion Discord (https://discord.gg/ksrfuy7WYR) in StorageMigrationNoticeBanner, with new .storage-migration-notice-banner__actions/__help CSS (desktop + mobile layout) - Revise the banner body copy to state that project databases will be served from the central Fusion database instead of each project's local .fusion/fusion.db SQLite file - Add storageMigrationNotice.getHelp/getHelpLabel i18n keys and update en/app.json body copy; sync placeholder keys across es/fr/ko/zh-CN/zh-TW locales and regenerate resources.d.ts - Extend StorageMigrationNoticeBanner tests to cover the new help link (href/target/rel) and updated body copy, including dismissed/error-path cases - Add a minor changeset for @runfusion/fusion documenting the banner change Files changed: .changeset/fn-7874-storage-banner-get-help.md | 7 ++++++ .../components/StorageMigrationNoticeBanner.css | 26 ++++++++++++++++++++++ .../components/StorageMigrationNoticeBanner.tsx | 16 ++++++++++++- .../StorageMigrationNoticeBanner.test.tsx | 16 +++++++++++-- packages/i18n/locales/en/app.json | 4 +++- packages/i18n/locales/es/app.json | 7 ++++++ packages/i18n/locales/fr/app.json | 7 ++++++ packages/i18n/locales/ko/app.json | 7 ++++++ packages/i18n/locales/zh-CN/app.json | 7 ++++++ packages/i18n/locales/zh-TW/app.json | 7 ++++++ packages/i18n/src/resources.d.ts | 7 ++++++ 11 files changed, 107 insertions(+), 4 deletions(-) Fusion-Task-Id: FN-7874 Fusion-Task-Lineage: baa88812-18ca-4910-a641-8d6e23f602a6 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
7
.changeset/fn-7874-storage-banner-get-help.md
Normal file
7
.changeset/fn-7874-storage-banner-get-help.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@runfusion/fusion": minor
|
||||
---
|
||||
|
||||
summary: Storage update banner now has a Get help (Discord) button and notes project DBs move to the central Fusion database.
|
||||
category: feature
|
||||
dev: Adds `storageMigrationNotice.getHelp`/`getHelpLabel` i18n keys and a hardened Discord link in `StorageMigrationNoticeBanner`; revised body copy in `en/app.json` and component default.
|
||||
@@ -37,6 +37,23 @@
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.storage-migration-notice-banner__actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: var(--space-xs);
|
||||
}
|
||||
|
||||
.storage-migration-notice-banner__help {
|
||||
align-self: flex-start;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.storage-migration-notice-banner__help:focus-visible {
|
||||
outline: none;
|
||||
box-shadow: var(--focus-ring-strong);
|
||||
}
|
||||
|
||||
.storage-migration-notice-banner__dismiss {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
@@ -67,6 +84,15 @@
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.storage-migration-notice-banner__actions {
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.storage-migration-notice-banner__help {
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.storage-migration-notice-banner__dismiss {
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ export const STORAGE_MIGRATION_NOTICE_DISMISS_KEY = "fusion:storage-migration-no
|
||||
/*
|
||||
FNXC:StorageMigrationNotice 2026-07-12-00:00:
|
||||
The dashboard must announce the next-version SQLite → embedded Postgres storage change before operators upgrade. Dismissal is global rather than project-scoped because the notice describes an app-wide on-disk storage engine change, not a per-project condition; localStorage persistence makes the one-time acknowledgement permanent on this browser profile.
|
||||
|
||||
FNXC:StorageMigrationNotice 2026-07-12-00:10:
|
||||
Operators need immediate support and clear storage-impact wording from the notice itself, so the banner links to the hardened Fusion Discord destination and states that project databases will be served from the central Fusion database instead of each project's local SQLite file.
|
||||
*/
|
||||
function isDismissed(): boolean {
|
||||
if (typeof window === "undefined") return false;
|
||||
@@ -48,9 +51,20 @@ export function StorageMigrationNoticeBanner() {
|
||||
<p className="storage-migration-notice-banner__text">
|
||||
{t(
|
||||
"storageMigrationNotice.body",
|
||||
"The next Fusion version will replace the current SQLite data store with an embedded Postgres backend for data storage. No migration runs from this notice; it is an advance heads-up for operators who rely on the current .fusion/fusion.db SQLite file.",
|
||||
"The next Fusion version will replace the current SQLite data store with an embedded Postgres backend for data storage, and project databases will be served from the central Fusion database instead of each project's local .fusion/fusion.db SQLite file. No migration runs from this notice; it is an advance heads-up for operators who rely on the current storage layout.",
|
||||
)}
|
||||
</p>
|
||||
<div className="storage-migration-notice-banner__actions">
|
||||
<a
|
||||
className="storage-migration-notice-banner__help btn btn-sm"
|
||||
href="https://discord.gg/ksrfuy7WYR"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label={t("storageMigrationNotice.getHelpLabel", "Get help on Discord")}
|
||||
>
|
||||
{t("storageMigrationNotice.getHelp", "Get help")}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -6,8 +6,10 @@ import {
|
||||
} from "../StorageMigrationNoticeBanner";
|
||||
|
||||
const title = "Storage update coming in the next Fusion version";
|
||||
const body = /next Fusion version will replace the current SQLite data store with an embedded Postgres backend/i;
|
||||
const body = /project databases will be served from the central Fusion database/i;
|
||||
const dismissLabel = "Dismiss storage update notice";
|
||||
const getHelpLabel = "Get help on Discord";
|
||||
const discordUrl = "https://discord.gg/ksrfuy7WYR";
|
||||
const originalLocalStorage = window.localStorage;
|
||||
|
||||
describe("StorageMigrationNoticeBanner", () => {
|
||||
@@ -29,12 +31,18 @@ describe("StorageMigrationNoticeBanner", () => {
|
||||
window.localStorage.clear();
|
||||
});
|
||||
|
||||
it("renders the storage notice when the dismissal key is absent", () => {
|
||||
it("renders the storage notice and hardened Discord help link when the dismissal key is absent", () => {
|
||||
render(<StorageMigrationNoticeBanner />);
|
||||
|
||||
expect(screen.getByRole("status")).toBeInTheDocument();
|
||||
expect(screen.getByText(title)).toBeInTheDocument();
|
||||
expect(screen.getByText(body)).toBeInTheDocument();
|
||||
const getHelpLink = screen.getByRole("link", { name: getHelpLabel });
|
||||
expect(getHelpLink).toHaveAttribute("href", discordUrl);
|
||||
expect(getHelpLink).toHaveAttribute("target", "_blank");
|
||||
expect(getHelpLink.getAttribute("rel")?.split(" ")).toEqual(
|
||||
expect.arrayContaining(["noopener", "noreferrer"]),
|
||||
);
|
||||
expect(screen.getByRole("button", { name: dismissLabel })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -46,6 +54,7 @@ describe("StorageMigrationNoticeBanner", () => {
|
||||
expect(window.localStorage.getItem(STORAGE_MIGRATION_NOTICE_DISMISS_KEY)).toBe("1");
|
||||
expect(screen.queryByRole("status")).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: dismissLabel })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("link", { name: getHelpLabel })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("returns null on a fresh mount when the dismissal key is already persisted", () => {
|
||||
@@ -56,6 +65,7 @@ describe("StorageMigrationNoticeBanner", () => {
|
||||
expect(screen.queryByRole("status")).not.toBeInTheDocument();
|
||||
expect(screen.queryByText(title)).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: dismissLabel })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("link", { name: getHelpLabel })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("does not crash when localStorage getItem or setItem throws", () => {
|
||||
@@ -73,6 +83,8 @@ describe("StorageMigrationNoticeBanner", () => {
|
||||
|
||||
expect(() => render(<StorageMigrationNoticeBanner />)).not.toThrow();
|
||||
expect(screen.getByRole("status")).toBeInTheDocument();
|
||||
expect(screen.getByText(body)).toBeInTheDocument();
|
||||
expect(screen.getByRole("link", { name: getHelpLabel })).toHaveAttribute("href", discordUrl);
|
||||
|
||||
expect(() => {
|
||||
fireEvent.click(screen.getByRole("button", { name: dismissLabel }));
|
||||
|
||||
@@ -1421,8 +1421,10 @@
|
||||
"versionMismatchSuffix": "Update to stay in sync."
|
||||
},
|
||||
"storageMigrationNotice": {
|
||||
"body": "The next Fusion version will replace the current SQLite data store with an embedded Postgres backend for data storage. No migration runs from this notice; it is an advance heads-up for operators who rely on the current .fusion/fusion.db SQLite file.",
|
||||
"body": "The next Fusion version will replace the current SQLite data store with an embedded Postgres backend for data storage, and project databases will be served from the central Fusion database instead of each project's local .fusion/fusion.db SQLite file. No migration runs from this notice; it is an advance heads-up for operators who rely on the current storage layout.",
|
||||
"dismissLabel": "Dismiss storage update notice",
|
||||
"getHelp": "Get help",
|
||||
"getHelpLabel": "Get help on Discord",
|
||||
"title": "Storage update coming in the next Fusion version"
|
||||
},
|
||||
"cliBinary": {
|
||||
|
||||
@@ -1413,6 +1413,8 @@
|
||||
"storageMigrationNotice": {
|
||||
"body": "",
|
||||
"dismissLabel": "",
|
||||
"getHelp": "",
|
||||
"getHelpLabel": "",
|
||||
"title": ""
|
||||
},
|
||||
"cliBinary": {
|
||||
@@ -2446,6 +2448,7 @@
|
||||
"previewTitle": "Vista previa de {{file}}"
|
||||
},
|
||||
"fileEditor": {
|
||||
"autoSave": "",
|
||||
"edit": "Editar",
|
||||
"editMode": "Modo editar",
|
||||
"editorFor": "Editor para {{filePath}}",
|
||||
@@ -2453,6 +2456,7 @@
|
||||
"lineNumber": "Línea #",
|
||||
"preview": "Vista previa",
|
||||
"previewMode": "Modo vista previa",
|
||||
"toggleAutoSave": "",
|
||||
"toggleLineNumbers": "Alternar números de línea",
|
||||
"toggleOptions": "Alternar opciones del editor",
|
||||
"toggleWordWrap": "Alternar ajuste de palabra",
|
||||
@@ -8357,6 +8361,7 @@
|
||||
},
|
||||
"todo": {
|
||||
"addItemPlaceholder": "Agregar elemento de tarea",
|
||||
"allDoneHidden": "",
|
||||
"addList": "Agregar lista",
|
||||
"assignAgent": "Asignar {{text}} al agente",
|
||||
"cancelItemEdit": "Cancelar edición de elemento",
|
||||
@@ -8386,6 +8391,7 @@
|
||||
"failedToCreateTask": "Error al crear la tarea: {{error}}",
|
||||
"failedToLoadAgents": "Error al cargar agentes: {{error}}",
|
||||
"failedUpdateItem": "Error al actualizar el elemento",
|
||||
"hideDone": "",
|
||||
"failedUpdateItemToast": "Error al actualizar el elemento de tareas pendientes",
|
||||
"itemsLabel": "Elementos de tareas",
|
||||
"lists": "Listas",
|
||||
@@ -8405,6 +8411,7 @@
|
||||
"saveListRename": "Guardar cambio de nombre de lista",
|
||||
"selectList": "Seleccionar lista {{title}}",
|
||||
"selectListEmpty": "Seleccione una lista de la barra lateral",
|
||||
"showDone": "",
|
||||
"startPlanning": "Comenzar a planificar desde {{text}}",
|
||||
"taskCreatedAndAssigned": "Creado {{id}} y asignado a {{agent}}",
|
||||
"taskCreatedFromTodo": "Creado {{id}} desde la lista de tareas",
|
||||
|
||||
@@ -1413,6 +1413,8 @@
|
||||
"storageMigrationNotice": {
|
||||
"body": "",
|
||||
"dismissLabel": "",
|
||||
"getHelp": "",
|
||||
"getHelpLabel": "",
|
||||
"title": ""
|
||||
},
|
||||
"cliBinary": {
|
||||
@@ -2446,6 +2448,7 @@
|
||||
"previewTitle": "Aperçu de {{file}}"
|
||||
},
|
||||
"fileEditor": {
|
||||
"autoSave": "",
|
||||
"edit": "Modifier",
|
||||
"editMode": "Mode édition",
|
||||
"editorFor": "Éditeur pour {{filePath}}",
|
||||
@@ -2453,6 +2456,7 @@
|
||||
"lineNumber": "Ligne #",
|
||||
"preview": "Aperçu",
|
||||
"previewMode": "Mode aperçu",
|
||||
"toggleAutoSave": "",
|
||||
"toggleLineNumbers": "Basculer les numéros de ligne",
|
||||
"toggleOptions": "Basculer les options de l'éditeur",
|
||||
"toggleWordWrap": "Basculer le retour à la ligne automatique",
|
||||
@@ -8357,6 +8361,7 @@
|
||||
},
|
||||
"todo": {
|
||||
"addItemPlaceholder": "Ajouter un élément de tâche",
|
||||
"allDoneHidden": "",
|
||||
"addList": "Ajouter une liste",
|
||||
"assignAgent": "Assigner {{text}} à l'agent",
|
||||
"cancelItemEdit": "Annuler la modification de l'élément",
|
||||
@@ -8386,6 +8391,7 @@
|
||||
"failedToCreateTask": "Échec de la création de la tâche : {{error}}",
|
||||
"failedToLoadAgents": "Échec du chargement des agents : {{error}}",
|
||||
"failedUpdateItem": "Échec de la mise à jour de l'élément",
|
||||
"hideDone": "",
|
||||
"failedUpdateItemToast": "Échec de la mise à jour de la tâche à faire",
|
||||
"itemsLabel": "Éléments de la liste de tâches",
|
||||
"lists": "Listes",
|
||||
@@ -8405,6 +8411,7 @@
|
||||
"saveListRename": "Enregistrer le renommage de la liste",
|
||||
"selectList": "Sélectionner la liste {{title}}",
|
||||
"selectListEmpty": "Sélectionnez une liste dans la barre latérale",
|
||||
"showDone": "",
|
||||
"startPlanning": "Commencer à planifier à partir de {{text}}",
|
||||
"taskCreatedAndAssigned": "Créé {{id}} et assigné à {{agent}}",
|
||||
"taskCreatedFromTodo": "Créé {{id}} à partir de la liste de tâches",
|
||||
|
||||
@@ -1413,6 +1413,8 @@
|
||||
"storageMigrationNotice": {
|
||||
"body": "",
|
||||
"dismissLabel": "",
|
||||
"getHelp": "",
|
||||
"getHelpLabel": "",
|
||||
"title": ""
|
||||
},
|
||||
"cliBinary": {
|
||||
@@ -2446,6 +2448,7 @@
|
||||
"previewTitle": "{{file}} 미리보기"
|
||||
},
|
||||
"fileEditor": {
|
||||
"autoSave": "",
|
||||
"edit": "편집",
|
||||
"editMode": "편집 모드",
|
||||
"editorFor": "{{filePath}} 편집기",
|
||||
@@ -2453,6 +2456,7 @@
|
||||
"lineNumber": "줄 번호",
|
||||
"preview": "미리보기",
|
||||
"previewMode": "미리보기 모드",
|
||||
"toggleAutoSave": "",
|
||||
"toggleLineNumbers": "줄 번호 표시 토글",
|
||||
"toggleOptions": "편집기 옵션 토글",
|
||||
"toggleWordWrap": "자동 줄 바꿈 토글",
|
||||
@@ -8357,6 +8361,7 @@
|
||||
},
|
||||
"todo": {
|
||||
"addItemPlaceholder": "할 일 항목 추가",
|
||||
"allDoneHidden": "",
|
||||
"addList": "목록 추가",
|
||||
"assignAgent": "{{text}}을(를) 에이전트에 할당",
|
||||
"cancelItemEdit": "항목 편집 취소",
|
||||
@@ -8386,6 +8391,7 @@
|
||||
"failedToCreateTask": "작업 생성 실패: {{error}}",
|
||||
"failedToLoadAgents": "에이전트 불러오기 실패: {{error}}",
|
||||
"failedUpdateItem": "항목 업데이트 실패",
|
||||
"hideDone": "",
|
||||
"failedUpdateItemToast": "할 일 항목 업데이트에 실패했습니다",
|
||||
"itemsLabel": "할 일 항목",
|
||||
"lists": "목록",
|
||||
@@ -8405,6 +8411,7 @@
|
||||
"saveListRename": "목록 이름 바꾸기 저장",
|
||||
"selectList": "{{title}} 목록 선택",
|
||||
"selectListEmpty": "사이드바에서 목록을 선택하세요",
|
||||
"showDone": "",
|
||||
"startPlanning": "{{text}}에서 계획 시작",
|
||||
"taskCreatedAndAssigned": "{{id}} 생성 후 {{agent}}에 할당됨",
|
||||
"taskCreatedFromTodo": "할 일에서 {{id}} 생성됨",
|
||||
|
||||
@@ -1413,6 +1413,8 @@
|
||||
"storageMigrationNotice": {
|
||||
"body": "",
|
||||
"dismissLabel": "",
|
||||
"getHelp": "",
|
||||
"getHelpLabel": "",
|
||||
"title": ""
|
||||
},
|
||||
"cliBinary": {
|
||||
@@ -2446,6 +2448,7 @@
|
||||
"previewTitle": "{{file}} 的预览"
|
||||
},
|
||||
"fileEditor": {
|
||||
"autoSave": "",
|
||||
"edit": "编辑",
|
||||
"editMode": "编辑模式",
|
||||
"editorFor": "{{filePath}}编辑器",
|
||||
@@ -2453,6 +2456,7 @@
|
||||
"lineNumber": "行号",
|
||||
"preview": "预览",
|
||||
"previewMode": "预览模式",
|
||||
"toggleAutoSave": "",
|
||||
"toggleLineNumbers": "切换行号",
|
||||
"toggleOptions": "切换编辑器选项",
|
||||
"toggleWordWrap": "切换自动换行",
|
||||
@@ -8357,6 +8361,7 @@
|
||||
},
|
||||
"todo": {
|
||||
"addItemPlaceholder": "添加待办事项",
|
||||
"allDoneHidden": "",
|
||||
"addList": "添加列表",
|
||||
"assignAgent": "将 {{text}} 分配给代理",
|
||||
"cancelItemEdit": "取消项目编辑",
|
||||
@@ -8386,6 +8391,7 @@
|
||||
"failedToCreateTask": "创建任务失败:{{error}}",
|
||||
"failedToLoadAgents": "加载代理失败:{{error}}",
|
||||
"failedUpdateItem": "更新项失败",
|
||||
"hideDone": "",
|
||||
"failedUpdateItemToast": "更新待办事项失败",
|
||||
"itemsLabel": "待办事项",
|
||||
"lists": "列表",
|
||||
@@ -8405,6 +8411,7 @@
|
||||
"saveListRename": "保存列表重命名",
|
||||
"selectList": "选择列表 {{title}}",
|
||||
"selectListEmpty": "从边栏选择一个列表",
|
||||
"showDone": "",
|
||||
"startPlanning": "从 {{text}} 开始规划",
|
||||
"taskCreatedAndAssigned": "创建了 {{id}} 并分配给 {{agent}}",
|
||||
"taskCreatedFromTodo": "从待办事项创建了 {{id}}",
|
||||
|
||||
@@ -1413,6 +1413,8 @@
|
||||
"storageMigrationNotice": {
|
||||
"body": "",
|
||||
"dismissLabel": "",
|
||||
"getHelp": "",
|
||||
"getHelpLabel": "",
|
||||
"title": ""
|
||||
},
|
||||
"cliBinary": {
|
||||
@@ -2446,6 +2448,7 @@
|
||||
"previewTitle": "{{file}} 的預覽"
|
||||
},
|
||||
"fileEditor": {
|
||||
"autoSave": "",
|
||||
"edit": "編輯",
|
||||
"editMode": "編輯模式",
|
||||
"editorFor": "{{filePath}}編輯器",
|
||||
@@ -2453,6 +2456,7 @@
|
||||
"lineNumber": "行號",
|
||||
"preview": "預覽",
|
||||
"previewMode": "預覽模式",
|
||||
"toggleAutoSave": "",
|
||||
"toggleLineNumbers": "切換行號",
|
||||
"toggleOptions": "切換編輯器選項",
|
||||
"toggleWordWrap": "切換自動換行",
|
||||
@@ -8357,6 +8361,7 @@
|
||||
},
|
||||
"todo": {
|
||||
"addItemPlaceholder": "新增待辦事項",
|
||||
"allDoneHidden": "",
|
||||
"addList": "新增清單",
|
||||
"assignAgent": "將 {{text}} 指派給代理",
|
||||
"cancelItemEdit": "取消項目編輯",
|
||||
@@ -8386,6 +8391,7 @@
|
||||
"failedToCreateTask": "建立任務失敗:{{error}}",
|
||||
"failedToLoadAgents": "加載代理失敗:{{error}}",
|
||||
"failedUpdateItem": "更新項目失敗",
|
||||
"hideDone": "",
|
||||
"failedUpdateItemToast": "更新待辦項目失敗",
|
||||
"itemsLabel": "待辦事項",
|
||||
"lists": "清單",
|
||||
@@ -8405,6 +8411,7 @@
|
||||
"saveListRename": "保存清單重新命名",
|
||||
"selectList": "選擇清單 {{title}}",
|
||||
"selectListEmpty": "從側邊欄選擇清單",
|
||||
"showDone": "",
|
||||
"startPlanning": "從 {{text}} 開始規劃",
|
||||
"taskCreatedAndAssigned": "建立了 {{id}} 並指派給 {{agent}}",
|
||||
"taskCreatedFromTodo": "從待辦事項建立了 {{id}}",
|
||||
|
||||
7
packages/i18n/src/resources.d.ts
vendored
7
packages/i18n/src/resources.d.ts
vendored
@@ -1412,6 +1412,13 @@ export default interface Resources {
|
||||
"versionMismatchPrefix": "Your installed",
|
||||
"versionMismatchSuffix": "Update to stay in sync."
|
||||
},
|
||||
"storageMigrationNotice": {
|
||||
"body": "The next Fusion version will replace the current SQLite data store with an embedded Postgres backend for data storage, and project databases will be served from the central Fusion database instead of each project's local .fusion/fusion.db SQLite file. No migration runs from this notice; it is an advance heads-up for operators who rely on the current storage layout.",
|
||||
"dismissLabel": "Dismiss storage update notice",
|
||||
"getHelp": "Get help",
|
||||
"getHelpLabel": "Get help on Discord",
|
||||
"title": "Storage update coming in the next Fusion version"
|
||||
},
|
||||
"cliBinary": {
|
||||
"binaryLabel": "Binary:",
|
||||
"checking": "Checking…",
|
||||
|
||||
Reference in New Issue
Block a user