From 3fba536f03fe995ed1f8173a2e43446dfd9821fc Mon Sep 17 00:00:00 2001 From: Cristhian Zanforlin Lousa Date: Sat, 11 Apr 2026 10:56:16 -0400 Subject: [PATCH] fix(ui): Show welcome page for new users when AUTO_LOGIN is false (#12626) * fix page displayed on AUTO LOGIN false * fix: translate Portuguese test comments to English --------- Co-authored-by: ogabrielluiz --- .../pages/__tests__/main-page-utils.test.ts | 97 +++++++++++++++++++ .../pages/MainPage/pages/main-page-utils.ts | 13 +++ .../src/pages/MainPage/pages/main-page.tsx | 39 ++++---- 3 files changed, 128 insertions(+), 21 deletions(-) create mode 100644 src/frontend/src/pages/MainPage/pages/__tests__/main-page-utils.test.ts create mode 100644 src/frontend/src/pages/MainPage/pages/main-page-utils.ts diff --git a/src/frontend/src/pages/MainPage/pages/__tests__/main-page-utils.test.ts b/src/frontend/src/pages/MainPage/pages/__tests__/main-page-utils.test.ts new file mode 100644 index 0000000000..c1ef765e1b --- /dev/null +++ b/src/frontend/src/pages/MainPage/pages/__tests__/main-page-utils.test.ts @@ -0,0 +1,97 @@ +import type { FlowType } from "@/types/flow"; +import type { FolderType } from "../../entities"; +import { shouldShowMainContent } from "../main-page-utils"; + +const makeFlow = (id: string): FlowType => + ({ id, name: `flow-${id}`, is_component: false }) as FlowType; + +const makeFolder = (id: string, name = "default"): FolderType => ({ + id, + name, + description: "", + parent_id: "", + flows: [], + components: [], +}); + +describe("shouldShowMainContent", () => { + it("should_show_welcome_page_when_new_user_has_no_flows_and_examples_are_global_with_auto_login_off", () => { + // Arrange — reproduces the exact bug scenario: + // AUTO_LOGIN=false, new user on first login. + // /flows/ returns [] (user_id == current_user.id doesn't match starters). + // /basic_examples/ returns global STARTER_FOLDER flows (user_id=None). + // User only has the default folder from get_or_create_default_folder. + const flows: FlowType[] = []; + const examples: FlowType[] = [ + makeFlow("starter-1"), + makeFlow("starter-2"), + makeFlow("starter-3"), + ]; + const folders: FolderType[] = [makeFolder("default-folder-id")]; + + // Act + const result = shouldShowMainContent(flows, examples, folders); + + // Assert — must be false so the Welcome page is shown + expect(result).toBe(false); + }); + + it("should_show_welcome_page_when_user_flows_are_all_starter_examples_with_auto_login_on", () => { + // AUTO_LOGIN=true: /flows/ returns starters via OR (user_id is None). + // So flows and examples share the same ids. + const sharedFlows = [ + makeFlow("starter-1"), + makeFlow("starter-2"), + makeFlow("starter-3"), + ]; + const folders: FolderType[] = [makeFolder("default-folder-id")]; + + const result = shouldShowMainContent(sharedFlows, sharedFlows, folders); + + expect(result).toBe(false); + }); + + it("should_show_main_content_when_user_has_at_least_one_custom_flow_besides_examples", () => { + const examples = [makeFlow("starter-1"), makeFlow("starter-2")]; + const flows = [...examples, makeFlow("user-custom-1")]; + const folders = [makeFolder("default-folder-id")]; + + const result = shouldShowMainContent(flows, examples, folders); + + expect(result).toBe(true); + }); + + it("should_show_main_content_when_user_has_more_than_one_folder", () => { + const flows: FlowType[] = []; + const examples = [makeFlow("starter-1")]; + const folders = [ + makeFolder("default-folder-id"), + makeFolder("extra-folder-id", "Extra"), + ]; + + const result = shouldShowMainContent(flows, examples, folders); + + expect(result).toBe(true); + }); + + it("should_show_welcome_page_when_user_has_no_flows_and_no_examples_and_single_folder", () => { + const result = shouldShowMainContent([], [], [makeFolder("default")]); + + expect(result).toBe(false); + }); + + it("should_show_main_content_when_auto_login_off_user_creates_only_a_single_custom_flow", () => { + // AUTO_LOGIN=false user creating their first custom flow. + const flows = [makeFlow("my-first-flow")]; + const examples = [ + makeFlow("starter-1"), + makeFlow("starter-2"), + makeFlow("starter-3"), + ]; + const folders = [makeFolder("default-folder-id")]; + + const result = shouldShowMainContent(flows, examples, folders); + + expect(result).toBe(true); + }); +}); diff --git a/src/frontend/src/pages/MainPage/pages/main-page-utils.ts b/src/frontend/src/pages/MainPage/pages/main-page-utils.ts new file mode 100644 index 0000000000..2fe17584ae --- /dev/null +++ b/src/frontend/src/pages/MainPage/pages/main-page-utils.ts @@ -0,0 +1,13 @@ +import type { FlowType } from "@/types/flow"; +import type { FolderType } from "../entities"; + +export function shouldShowMainContent( + flows: FlowType[] | undefined, + examples: FlowType[] | undefined, + folders: FolderType[] | undefined, +): boolean { + if (!flows || !examples || !folders) return false; + const exampleIds = new Set(examples.map((example) => example.id)); + const userOwnedFlows = flows.filter((flow) => !exampleIds.has(flow.id)); + return userOwnedFlows.length > 0 || folders.length > 1; +} diff --git a/src/frontend/src/pages/MainPage/pages/main-page.tsx b/src/frontend/src/pages/MainPage/pages/main-page.tsx index c0001e2821..b714cfc1f6 100644 --- a/src/frontend/src/pages/MainPage/pages/main-page.tsx +++ b/src/frontend/src/pages/MainPage/pages/main-page.tsx @@ -11,7 +11,7 @@ import useAlertStore from "@/stores/alertStore"; import useFlowsManagerStore from "@/stores/flowsManagerStore"; import { useFolderStore } from "@/stores/foldersStore"; import ModalsComponent from "../components/modalsComponent"; -import EmptyPageCommunity from "./empty-page"; +import { shouldShowMainContent } from "./main-page-utils"; export default function CollectionPage(): JSX.Element { const [openModal, setOpenModal] = useState(false); @@ -54,33 +54,30 @@ export default function CollectionPage(): JSX.Element { ); }; + const showMainContent = shouldShowMainContent(flows, examples, folders); + return ( - {flows && - examples && - folders && - ((flows?.length !== examples?.length && folders?.length > 0) || - folders?.length > 1) && ( - { - navigate(`all/folder/${id}`); - }} - handleDeleteFolder={(item) => { - setFolderToEdit(item); - setOpenDeleteFolderModal(true); - }} - handleFilesClick={() => { - navigate("assets"); - }} - /> - )} + {flows && examples && folders && showMainContent && ( + { + navigate(`all/folder/${id}`); + }} + handleDeleteFolder={(item) => { + setFolderToEdit(item); + setOpenDeleteFolderModal(true); + }} + handleFilesClick={() => { + navigate("assets"); + }} + /> + )}
{flows && examples && folders ? (
- {(flows?.length !== examples?.length && folders?.length > 0) || - folders?.length > 1 ? ( + {showMainContent ? ( ) : (