feat(FN-2285): rebrand dashboard TUI header to Fusion
- Update dashboard TUI header copy from "fn board" to "fusion" branding - Add CLI tests that validate the new header text and related rendering behavior - Include a changeset documenting the published @runfusion/fusion patch for the branding update
This commit is contained in:
5
.changeset/update-tui-header-branding.md
Normal file
5
.changeset/update-tui-header-branding.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@runfusion/fusion": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Update dashboard TUI header branding from "fn board" to "fusion" for consistent product naming.
|
||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
LogRingBuffer,
|
LogRingBuffer,
|
||||||
DashboardLogSink,
|
DashboardLogSink,
|
||||||
isTTYAvailable,
|
isTTYAvailable,
|
||||||
|
renderHeaderToString,
|
||||||
type SystemInfo,
|
type SystemInfo,
|
||||||
type TaskStats,
|
type TaskStats,
|
||||||
type SettingsValues,
|
type SettingsValues,
|
||||||
@@ -148,6 +149,40 @@ describe("isTTYAvailable", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ── Header Branding Tests ───────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe("renderHeaderToString", () => {
|
||||||
|
it("includes 'fusion' in header title", () => {
|
||||||
|
const header = renderHeaderToString(80);
|
||||||
|
expect(header).toContain("fusion");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not include old 'fn board' branding", () => {
|
||||||
|
const header = renderHeaderToString(80);
|
||||||
|
expect(header).not.toContain("fn board");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders correctly at wide terminal width (>= 70 cols)", () => {
|
||||||
|
const header = renderHeaderToString(80);
|
||||||
|
expect(header).toContain("fusion");
|
||||||
|
expect(header).toContain("Logs");
|
||||||
|
expect(header).toContain("System");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders correctly at medium terminal width (>= 40 cols)", () => {
|
||||||
|
const header = renderHeaderToString(50);
|
||||||
|
expect(header).toContain("fusion");
|
||||||
|
expect(header).toContain("[1]L"); // Short label for Logs
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders correctly at narrow terminal width (< 40 cols)", () => {
|
||||||
|
const header = renderHeaderToString(30);
|
||||||
|
expect(header).toContain("fusion");
|
||||||
|
expect(header).toContain("Logs");
|
||||||
|
expect(header).toContain("[n/p]nav");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// ── Type exports verification ─────────────────────────────────────────────
|
// ── Type exports verification ─────────────────────────────────────────────
|
||||||
|
|
||||||
describe("Type exports", () => {
|
describe("Type exports", () => {
|
||||||
|
|||||||
@@ -556,7 +556,7 @@ export class DashboardTUI {
|
|||||||
|
|
||||||
private renderHeader(): void {
|
private renderHeader(): void {
|
||||||
const cols = process.stdout.columns || 80;
|
const cols = process.stdout.columns || 80;
|
||||||
const title = colorize(" fn board ", "cyan");
|
const title = colorize(" fusion ", "cyan");
|
||||||
const titleLen = visibleLength(title);
|
const titleLen = visibleLength(title);
|
||||||
|
|
||||||
process.stdout.write(title);
|
process.stdout.write(title);
|
||||||
@@ -1012,3 +1012,81 @@ function padRight(text: string, width: number): string {
|
|||||||
export function isTTYAvailable(): boolean {
|
export function isTTYAvailable(): boolean {
|
||||||
return Boolean(process.stdout.isTTY && process.stdin.isTTY);
|
return Boolean(process.stdout.isTTY && process.stdin.isTTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Header String Helper (for testing) ─────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the header to a string using the given column width.
|
||||||
|
* Used for testing without requiring TTY mode.
|
||||||
|
*/
|
||||||
|
export function renderHeaderToString(cols: number): string {
|
||||||
|
const title = colorize(" fusion ", "cyan");
|
||||||
|
const titleLen = visibleLength(title);
|
||||||
|
|
||||||
|
let output = title;
|
||||||
|
|
||||||
|
// Build tabs based on column width (same logic as renderHeader)
|
||||||
|
if (cols >= 70) {
|
||||||
|
for (let i = 0; i < SECTION_ORDER.length; i++) {
|
||||||
|
const section = SECTION_ORDER[i];
|
||||||
|
const isActive = section === "logs"; // Default active section for test
|
||||||
|
const num = (i + 1).toString();
|
||||||
|
const label = section.charAt(0).toUpperCase() + section.slice(1);
|
||||||
|
const tabText = `[${num}] ${label}`;
|
||||||
|
const style = isActive ? "brightBlue" : "dim";
|
||||||
|
output += colorize(` ${tabText} `, style);
|
||||||
|
}
|
||||||
|
} else if (cols >= 40) {
|
||||||
|
const shortLabels: Record<SectionId, string> = {
|
||||||
|
logs: "L",
|
||||||
|
system: "S",
|
||||||
|
utilities: "U",
|
||||||
|
stats: "St",
|
||||||
|
settings: "Se",
|
||||||
|
};
|
||||||
|
for (let i = 0; i < SECTION_ORDER.length; i++) {
|
||||||
|
const section = SECTION_ORDER[i];
|
||||||
|
const isActive = section === "logs";
|
||||||
|
const num = (i + 1).toString();
|
||||||
|
const shortLabel = shortLabels[section];
|
||||||
|
const tabText = `[${num}]${shortLabel}`;
|
||||||
|
const style = isActive ? "brightBlue" : "dim";
|
||||||
|
output += colorize(` ${tabText} `, style);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output += colorize(" [1]Logs ", "brightBlue");
|
||||||
|
output += colorize(" [n/p]nav ", "dim");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate tabs length for padding
|
||||||
|
const tabsLength = SECTION_ORDER.reduce((acc, s, i) => {
|
||||||
|
let label: string;
|
||||||
|
if (cols >= 70) {
|
||||||
|
label = s.charAt(0).toUpperCase() + s.slice(1);
|
||||||
|
} else if (cols >= 40) {
|
||||||
|
const shortLabels: Record<SectionId, string> = {
|
||||||
|
logs: "L",
|
||||||
|
system: "S",
|
||||||
|
utilities: "U",
|
||||||
|
stats: "St",
|
||||||
|
settings: "Se",
|
||||||
|
};
|
||||||
|
label = shortLabels[s];
|
||||||
|
} else {
|
||||||
|
label = s.charAt(0).toUpperCase() + s.slice(1);
|
||||||
|
}
|
||||||
|
const tabText = `[${i + 1}]${label} `;
|
||||||
|
return acc + tabText.length;
|
||||||
|
}, 0);
|
||||||
|
const headerLen = titleLen + tabsLength;
|
||||||
|
|
||||||
|
const remaining = cols - headerLen;
|
||||||
|
if (remaining > 0) {
|
||||||
|
output += " ".repeat(remaining);
|
||||||
|
}
|
||||||
|
|
||||||
|
output += "\n";
|
||||||
|
output += colorize("─".repeat(Math.max(20, cols)), "dim") + "\n";
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user