feat(FN-3156): add database schema init hook runner for plugin settings lif
The merge adds plugin schema initialization lifecycle support (FN-3156), introduces a ResearchTaskActionModal with model fallback notifications (FN-3012, FN-3008), adds async planning draft sync to prevent UI blocking (FN-3229), and implements viewport-conditional mission split layout (FN-3130). Inf Fusion-Task-Id: FN-3156
This commit is contained in:
@@ -201,6 +201,15 @@ export function MobileNavBar({
|
||||
const primaryPluginViews = pluginDashboardViews
|
||||
.filter((entry) => entry.view.placement === "primary")
|
||||
.sort((a, b) => (a.view.order ?? Number.MAX_SAFE_INTEGER) - (b.view.order ?? Number.MAX_SAFE_INTEGER));
|
||||
// Keep plugin-provided top-level tabs constrained on mobile so fixed tabs retain
|
||||
// reasonable touch-target width. Additional primary plugin destinations overflow into More.
|
||||
const MAX_PRIMARY_PLUGIN_TOP_LEVEL_TABS = 1;
|
||||
const topLevelPrimaryPluginViews = primaryPluginViews.slice(0, MAX_PRIMARY_PLUGIN_TOP_LEVEL_TABS);
|
||||
const overflowPrimaryPluginViews = primaryPluginViews.slice(MAX_PRIMARY_PLUGIN_TOP_LEVEL_TABS);
|
||||
const overflowPluginViews = [
|
||||
...overflowPrimaryPluginViews,
|
||||
...pluginDashboardViews.filter((entry) => entry.view.placement !== "primary"),
|
||||
].sort((a, b) => (a.view.order ?? Number.MAX_SAFE_INTEGER) - (b.view.order ?? Number.MAX_SAFE_INTEGER));
|
||||
|
||||
const isMoreActive =
|
||||
view === "documents"
|
||||
@@ -212,7 +221,7 @@ export function MobileNavBar({
|
||||
|| (todosOpen && todoViewEnabled)
|
||||
|| (view === "roadmaps" && !showRoadmapsTopLevel)
|
||||
|| (view === "skills" && !showSkillsTopLevel)
|
||||
|| (view.startsWith("plugin:") && !primaryPluginViews.some((entry) => buildPluginTaskViewId(entry.pluginId, entry.view.viewId) === view));
|
||||
|| (view.startsWith("plugin:") && !topLevelPrimaryPluginViews.some((entry) => buildPluginTaskViewId(entry.pluginId, entry.view.viewId) === view));
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -320,7 +329,7 @@ export function MobileNavBar({
|
||||
</button>
|
||||
)}
|
||||
|
||||
{primaryPluginViews.map((entry) => {
|
||||
{topLevelPrimaryPluginViews.map((entry) => {
|
||||
const pluginTaskView = buildPluginTaskViewId(entry.pluginId, entry.view.viewId);
|
||||
const PluginIcon = getPluginNavIcon(entry.view.icon);
|
||||
return (
|
||||
@@ -660,10 +669,7 @@ export function MobileNavBar({
|
||||
</button>
|
||||
)}
|
||||
|
||||
{pluginDashboardViews
|
||||
.filter((entry) => entry.view.placement !== "primary")
|
||||
.sort((a, b) => (a.view.order ?? Number.MAX_SAFE_INTEGER) - (b.view.order ?? Number.MAX_SAFE_INTEGER))
|
||||
.map((entry) => {
|
||||
{overflowPluginViews.map((entry) => {
|
||||
const pluginTaskView = buildPluginTaskViewId(entry.pluginId, entry.view.viewId);
|
||||
const PluginIcon = getPluginNavIcon(entry.view.icon);
|
||||
return (
|
||||
|
||||
@@ -134,6 +134,30 @@ describe("MobileNavBar", () => {
|
||||
expect(props.onChangeView).toHaveBeenCalledWith("plugin:fusion-plugin-dependency-graph:queue");
|
||||
});
|
||||
|
||||
it("limits primary plugin tabs on mobile and overflows extra primary views into More", () => {
|
||||
render(
|
||||
<MobileNavBar
|
||||
{...createDefaultProps()}
|
||||
pluginDashboardViews={[
|
||||
{
|
||||
pluginId: "fusion-plugin-dependency-graph",
|
||||
view: { viewId: "graph", label: "Graph", componentPath: "./GraphView", icon: "Map", placement: "primary", order: 1 },
|
||||
},
|
||||
{
|
||||
pluginId: "fusion-plugin-dependency-graph",
|
||||
view: { viewId: "queue", label: "Queue", componentPath: "./QueueView", icon: "Workflow", placement: "primary", order: 2 },
|
||||
},
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByTestId("mobile-nav-tab-plugin-fusion-plugin-dependency-graph-graph")).toBeDefined();
|
||||
expect(screen.queryByTestId("mobile-nav-tab-plugin-fusion-plugin-dependency-graph-queue")).toBeNull();
|
||||
|
||||
fireEvent.click(screen.getByTestId("mobile-nav-tab-more"));
|
||||
expect(screen.getByTestId("mobile-more-item-plugin-fusion-plugin-dependency-graph-queue")).toBeDefined();
|
||||
});
|
||||
|
||||
it("active tab is highlighted for mailbox", () => {
|
||||
render(<MobileNavBar {...createDefaultProps()} view="mailbox" />);
|
||||
expect(screen.getByTestId("mobile-nav-tab-mailbox").className).toContain("mobile-nav-tab--active");
|
||||
|
||||
Reference in New Issue
Block a user