fix: Delete old logo and old dashboard (#6884)

deleted old logo and dashboard, and moved code
This commit is contained in:
Deon Sanchez 2025-03-04 09:51:12 -07:00 committed by GitHub
commit 1cc49962d5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 37 additions and 1032 deletions

View file

@ -7,10 +7,7 @@ import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
import { CustomOrgSelector } from "@/customization/components/custom-org-selector";
import { CustomProductSelector } from "@/customization/components/custom-product-selector";
import {
ENABLE_DATASTAX_LANGFLOW,
ENABLE_NEW_LOGO,
} from "@/customization/feature-flags";
import { ENABLE_DATASTAX_LANGFLOW } from "@/customization/feature-flags";
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
import useTheme from "@/customization/hooks/use-custom-theme";
import { useResetDismissUpdateAll } from "@/hooks/use-reset-dismiss-update-all";
@ -67,10 +64,8 @@ export default function AppHeader(): JSX.Element {
>
{ENABLE_DATASTAX_LANGFLOW ? (
<DataStaxLogo className="fill-black dark:fill-[white]" />
) : ENABLE_NEW_LOGO ? (
<LangflowLogo className="h-5 w-6" />
) : (
<span className="fill-black text-2xl dark:fill-white"></span>
<LangflowLogo className="h-5 w-6" />
)}
</Button>
{ENABLE_DATASTAX_LANGFLOW && (

View file

@ -7,6 +7,4 @@ export const ENABLE_BRANDING = true;
export const ENABLE_MVPS = false;
export const ENABLE_CUSTOM_PARAM = false;
export const ENABLE_INTEGRATIONS = false;
export const ENABLE_NEW_LOGO = true;
export const ENABLE_DATASTAX_LANGFLOW = false;
export const ENABLE_HOMEPAGE = true;

View file

@ -1,7 +1,5 @@
import LangflowLogo from "@/assets/LangflowLogo.svg?react";
import ChainLogo from "@/assets/logo.svg?react";
import { TextEffectPerChar } from "@/components/ui/textAnimation";
import { ENABLE_NEW_LOGO } from "@/customization/feature-flags";
import { track } from "@/customization/utils/analytics";
import { useMessagesStore } from "@/stores/messagesStore";
import { useUtilityStore } from "@/stores/utilityStore";
@ -179,17 +177,10 @@ export default function ChatView({
) : (
<div className="flex h-full w-full flex-col items-center justify-center">
<div className="flex flex-col items-center justify-center gap-4 p-8">
{ENABLE_NEW_LOGO ? (
<LangflowLogo
title="Langflow logo"
className="h-10 w-10 scale-[1.5]"
/>
) : (
<ChainLogo
title="Langflow logo"
className="h-10 w-10 scale-[1.5]"
/>
)}
<LangflowLogo
title="Langflow logo"
className="h-10 w-10 scale-[1.5]"
/>
<div className="flex flex-col items-center justify-center">
<h3 className="mt-2 pb-2 text-2xl font-semibold text-primary">
New chat

View file

@ -1,22 +1,13 @@
import LangflowLogo from "@/assets/LangflowLogo.svg?react";
import ChainLogo from "@/assets/logo.svg?react";
import { ENABLE_NEW_LOGO } from "@/customization/feature-flags";
export default function LogoIcon() {
return (
<div className="relative flex h-8 w-8 items-center justify-center rounded-md bg-muted">
<div className="flex h-8 w-8 items-center justify-center">
{ENABLE_NEW_LOGO ? (
<LangflowLogo
title="Langflow Logo"
className="absolute h-[18px] w-[18px]"
/>
) : (
<ChainLogo
title="Langflow Logo"
className="absolute h-[18px] w-[18px]"
/>
)}
<LangflowLogo
title="Langflow Logo"
className="absolute h-[18px] w-[18px]"
/>
</div>
</div>
);

View file

@ -1,6 +1,5 @@
import LangflowLogo from "@/assets/LangflowLogo.svg?react";
import { useLoginUser } from "@/controllers/API/queries/auth";
import { ENABLE_NEW_LOGO } from "@/customization/feature-flags";
import { useContext, useState } from "react";
import { Button } from "../../../components/ui/button";
import { Input } from "../../../components/ui/input";
@ -51,14 +50,7 @@ export default function LoginAdminPage() {
return (
<div className="flex h-full w-full flex-col items-center justify-center bg-muted">
<div className="flex w-72 flex-col items-center justify-center gap-2">
{ENABLE_NEW_LOGO ? (
<LangflowLogo
title="Langflow logo"
className="h-10 w-10 scale-[1.5]"
/>
) : (
<span className="mb-4 text-5xl"></span>
)}
<LangflowLogo title="Langflow logo" className="h-10 w-10 scale-[1.5]" />
<span className="mb-6 text-2xl font-semibold text-primary">Admin</span>
<Input
onChange={({ target: { value } }) => {

View file

@ -1,5 +1,4 @@
import LangflowLogo from "@/assets/LangflowLogo.svg?react";
import { ENABLE_NEW_LOGO } from "@/customization/feature-flags";
import { useState } from "react";
import { Button } from "../../components/ui/button";
import { Input } from "../../components/ui/input";
@ -19,14 +18,10 @@ export default function DeleteAccountPage() {
return (
<div className="flex h-full w-full flex-col items-center justify-center bg-muted">
<div className="flex w-72 flex-col items-center justify-center gap-2">
{ENABLE_NEW_LOGO ? (
<LangflowLogo
title="Langflow logo"
className="mb-4 h-10 w-10 scale-[1.5]"
/>
) : (
<span className="mb-4 text-5xl"></span>
)}
<LangflowLogo
title="Langflow logo"
className="mb-4 h-10 w-10 scale-[1.5]"
/>
<span className="mb-4 text-center text-2xl font-semibold text-primary">
Delete your account
</span>

View file

@ -1,7 +1,6 @@
import LangflowLogo from "@/assets/LangflowLogo.svg?react";
import { useLoginUser } from "@/controllers/API/queries/auth";
import { CustomLink } from "@/customization/components/custom-link";
import { ENABLE_NEW_LOGO } from "@/customization/feature-flags";
import * as Form from "@radix-ui/react-form";
import { useContext, useState } from "react";
import InputComponent from "../../components/core/parameterRenderComponent/components/inputComponent";
@ -67,14 +66,10 @@ export default function LoginPage(): JSX.Element {
>
<div className="flex h-full w-full flex-col items-center justify-center bg-muted">
<div className="flex w-72 flex-col items-center justify-center gap-2">
{ENABLE_NEW_LOGO ? (
<LangflowLogo
title="Langflow logo"
className="mb-4 h-10 w-10 scale-[1.5]"
/>
) : (
<span className="mb-4 text-5xl"></span>
)}
<LangflowLogo
title="Langflow logo"
className="mb-4 h-10 w-10 scale-[1.5]"
/>
<span className="mb-6 text-2xl font-semibold text-primary">
Sign in to Langflow
</span>

View file

@ -1,6 +1,6 @@
import ForwardedIconComponent from "@/components/common/genericIconComponent";
import { Input } from "@/components/ui/input";
import { ChangeEvent, KeyboardEvent } from "react";
import ForwardedIconComponent from "../../../../../../components/common/genericIconComponent";
import { Input } from "../../../../../../components/ui/input";
type InputSearchComponentProps = {
loading: boolean;

View file

@ -1,39 +0,0 @@
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
import useFlowsManagerStore from "@/stores/flowsManagerStore";
import { useParams } from "react-router-dom";
import CollectionCardComponent from "../../../../../../components/core/cardComponent";
const CollectionCard = ({ item, type, isLoading, control }) => {
const navigate = useCustomNavigate();
const isComponent = item.is_component ?? false;
const editFlowButtonTestId = `edit-flow-button-${item.id}`;
const { folderId } = useParams();
const editFlowLink = `/flow/${item.id}${folderId ? `/folder/${folderId}` : ""}`;
const setFlowToCanvas = useFlowsManagerStore(
(state) => state.setFlowToCanvas,
);
const handleClick = async () => {
if (!isComponent) {
await setFlowToCanvas(item);
navigate(editFlowLink);
}
};
return (
<CollectionCardComponent
data={{
is_component: isComponent,
...item,
}}
disabled={isLoading}
data-testid={editFlowButtonTestId}
onClick={!isComponent ? handleClick : undefined}
control={control}
/>
);
};
export default CollectionCard;

View file

@ -1,281 +0,0 @@
import PaginatorComponent from "@/components/common/paginatorComponent";
import { PAGINATION_PAGE, PAGINATION_SIZE } from "@/constants/constants";
import { usePostDownloadMultipleFlows } from "@/controllers/API/queries/flows";
import TemplatesModal from "@/modals/templatesModal";
import { Pagination } from "@/types/utils/types";
import { useEffect, useMemo, useState } from "react";
import { FormProvider, useForm, useWatch } from "react-hook-form";
import { useLocation, useParams } from "react-router-dom";
import { SkeletonCardComponent } from "../../../../components/common/skeletonCardComponent";
import CardsWrapComponent from "../../../../components/core/cardsWrapComponent";
import DeleteConfirmationModal from "../../../../modals/deleteConfirmationModal";
import useAlertStore from "../../../../stores/alertStore";
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
import { useFolderStore } from "../../../../stores/foldersStore";
import { FlowType } from "../../../../types/flow";
import useFileDrop from "../../hooks/use-on-file-drop";
import { getNameByType } from "../../utils/get-name-by-type";
import useDescriptionModal from "../../hooks/use-description-modal";
import useFilteredFlows from "../../hooks/use-filtered-flows";
import useSelectAll from "../../hooks/use-handle-select-all";
import useSelectOptionsChange from "../../hooks/use-select-options-change";
import useSelectedFlows from "../../hooks/use-selected-flows";
import EmptyComponent from "../emptyComponent";
import HeaderComponent from "../headerComponent";
import CollectionCard from "./components/collectionCard";
export default function ComponentsComponent({
type = "all",
currentFolder,
pagination,
isLoading,
deleteFlow,
onPaginate,
}: {
type?: string;
currentFolder?: FlowType[];
isLoading: boolean;
pagination: Pagination;
deleteFlow: ({ id }: { id: string[] }) => Promise<void>;
onPaginate: (pageIndex: number, pageSize: number) => void;
}) {
const { folderId } = useParams();
const [openModal, setOpenModal] = useState(false);
const setSuccessData = useAlertStore((state) => state.setSuccessData);
const setErrorData = useAlertStore((state) => state.setErrorData);
const [openDelete, setOpenDelete] = useState(false);
const searchFlowsComponents = useFlowsManagerStore(
(state) => state.searchFlowsComponents,
);
const setSelectedFlowsComponentsCards = useFlowsManagerStore(
(state) => state.setSelectedFlowsComponentsCards,
);
const selectedFlowsComponentsCards = useFlowsManagerStore(
(state) => state.selectedFlowsComponentsCards,
);
const myCollectionId = useFolderStore((state) => state.myCollectionId);
const flowsFromFolder = currentFolder ?? [];
const [filteredFlows, setFilteredFlows] =
useState<FlowType[]>(flowsFromFolder);
const handleFileDrop = useFileDrop(type);
const location = useLocation();
const name = getNameByType(type);
const [shouldSelectAll, setShouldSelectAll] = useState(true);
const cardTypes = useMemo(() => {
if (location.pathname.includes("components")) {
return "Components";
}
if (location.pathname.includes("flows")) {
return "Flows";
}
return "Items";
}, [location]);
useEffect(() => {
setSelectedFlowsComponentsCards([]);
handleSelectAll(false);
setShouldSelectAll(true);
}, [folderId, location, myCollectionId]);
useFilteredFlows(flowsFromFolder, searchFlowsComponents, setFilteredFlows);
const resetFilter = () => {
onPaginate(PAGINATION_PAGE, PAGINATION_SIZE);
};
const { getValues, control, setValue } = useForm();
const entireFormValues = useWatch({ control });
const methods = useForm();
const { handleSelectAll } = useSelectAll(
flowsFromFolder!,
getValues,
setValue,
);
const handleDuplicate = () => {};
const { mutate: mutateDownloadMultipleFlows } =
usePostDownloadMultipleFlows();
const handleExport = () => {
mutateDownloadMultipleFlows(
{
flow_ids: selectedFlowsComponentsCards,
},
{
onSuccess: (data) => {
const selectedFlow = flowsFromFolder.find(
(flow) => flow.id === selectedFlowsComponentsCards[0],
);
const blobType =
selectedFlowsComponentsCards.length > 1
? "application/zip"
: "application/json";
const fileNameSuffix =
selectedFlowsComponentsCards.length > 1
? "_langflow_flows.zip"
: `${selectedFlow!.name}.json`;
const blob = new Blob([data], { type: blobType });
const link = document.createElement("a");
link.href = window.URL.createObjectURL(blob);
let current_time = new Date().toISOString().replace(/[:.]/g, "");
current_time = current_time
.replace(/-/g, "")
.replace(/T/g, "")
.replace(/Z/g, "");
link.download =
selectedFlowsComponentsCards.length > 1
? `${current_time}${fileNameSuffix}`
: `${fileNameSuffix}`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
setSuccessData({ title: `${cardTypes} exported successfully` });
setSelectedFlowsComponentsCards([]);
handleSelectAll(false);
setShouldSelectAll(true);
},
},
);
};
const { handleSelectOptionsChange } = useSelectOptionsChange(
selectedFlowsComponentsCards,
setErrorData,
setOpenDelete,
handleDuplicate,
handleExport,
);
const handleDeleteMultiple = () => {
deleteFlow({ id: selectedFlowsComponentsCards })
.then(() => {
resetFilter();
setSelectedFlowsComponentsCards([]);
handleSelectAll(false);
setShouldSelectAll(true);
setSuccessData({
title: "Selected items deleted successfully",
});
})
.catch(() => {
setErrorData({
title: "Error deleting items",
list: ["Please try again"],
});
});
};
useSelectedFlows(entireFormValues, setSelectedFlowsComponentsCards);
const descriptionModal = useDescriptionModal(
selectedFlowsComponentsCards,
type,
);
const handleOpenModal = () => {
setOpenModal(true);
};
return (
<>
<div className="flex w-full gap-4 pb-5">
<HeaderComponent
disabled={isLoading || flowsFromFolder?.length === 0}
shouldSelectAll={shouldSelectAll}
setShouldSelectAll={setShouldSelectAll}
handleDelete={() => handleSelectOptionsChange("delete")}
handleSelectAll={handleSelectAll}
handleDuplicate={() => handleSelectOptionsChange("duplicate")}
handleExport={() => handleSelectOptionsChange("export")}
disableFunctions={!(selectedFlowsComponentsCards?.length > 0)}
/>
</div>
<CardsWrapComponent
onFileDrop={handleFileDrop}
dragMessage={`Drag your ${name} here`}
>
<div
className="flex h-full w-full flex-col justify-between"
data-testid="cards-wrapper"
>
<div className="flex w-full flex-col gap-4">
{!isLoading && flowsFromFolder?.length === 0 ? (
<EmptyComponent handleOpenModal={handleOpenModal} />
) : (
<div className="grid w-full gap-4 md:grid-cols-2 lg:grid-cols-2">
{flowsFromFolder?.length > 0 ? (
<>
{flowsFromFolder?.map((item) => (
<FormProvider {...methods} key={item.id}>
<form>
<CollectionCard
item={item}
type={type}
isLoading={isLoading}
control={control}
/>
</form>
</FormProvider>
))}
</>
) : (
<>
<SkeletonCardComponent />
<SkeletonCardComponent />
</>
)}
</div>
)}
</div>
{!isLoading && flowsFromFolder?.length > 0 && (
<div className="relative py-6">
<PaginatorComponent
pageIndex={pagination.page}
pageSize={pagination.size}
rowsCount={[10, 20, 50, 100]}
totalRowsCount={pagination.total ?? 0}
paginate={onPaginate}
pages={pagination.pages}
></PaginatorComponent>
</div>
)}
</div>
</CardsWrapComponent>
{openDelete && (
<DeleteConfirmationModal
open={openDelete}
setOpen={setOpenDelete}
onConfirm={handleDeleteMultiple}
description={descriptionModal}
>
<></>
</DeleteConfirmationModal>
)}
<TemplatesModal open={openModal} setOpen={setOpenModal} />
</>
);
}

View file

@ -1,35 +0,0 @@
import { useIsFetching } from "@tanstack/react-query";
type EmptyComponentProps = {
handleOpenModal: () => void;
};
const EmptyComponent = ({ handleOpenModal }: EmptyComponentProps) => {
const isLoadingFolders = !!useIsFetching({
queryKey: ["useGetFolders"],
exact: false,
});
return (
<div className="mt-2 flex w-full items-center justify-center text-center">
<div className="flex-max-width h-full flex-col">
<div className="align-center flex w-full justify-center gap-1">
<span className="text-muted-foreground">
This folder is empty. New?
</span>
<span className="transition-colors hover:text-muted-foreground">
<button
onClick={handleOpenModal}
disabled={isLoadingFolders}
className="underline"
>
Start Here
</button>
</span>
<span className="animate-pulse">🚀</span>
</div>
</div>
</div>
);
};
export default EmptyComponent;

View file

@ -1,126 +0,0 @@
import IconComponent from "../../../../components/common/genericIconComponent";
import ShadTooltip from "../../../../components/common/shadTooltipComponent";
import { Button } from "../../../../components/ui/button";
import { Checkbox } from "../../../../components/ui/checkbox";
import { cn } from "../../../../utils/utils";
type HeaderComponentProps = {
handleSelectAll: (select) => void;
handleDelete: () => void;
handleDuplicate: () => void;
handleExport: () => void;
disableFunctions: boolean;
setShouldSelectAll: (select) => void;
shouldSelectAll: boolean;
disabled: boolean;
};
const HeaderComponent = ({
handleSelectAll,
handleDelete,
handleDuplicate,
handleExport,
disableFunctions,
setShouldSelectAll,
shouldSelectAll,
disabled,
}: HeaderComponentProps) => {
const handleClick = () => {
handleSelectAll(shouldSelectAll);
setShouldSelectAll((prevState) => !prevState);
};
return (
<>
<div
className={cn(
"flex w-full items-center justify-between gap-4",
disabled ? "pointer-events-none opacity-50" : "",
)}
>
<div className="flex items-center justify-self-start">
<a onClick={handleClick} className="cursor-pointer text-sm">
<div className="flex items-center space-x-2">
<Checkbox checked={!shouldSelectAll} id="terms" />
<span className="label text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
{shouldSelectAll ? "Select All" : "Unselect All"}
</span>
</div>
</a>
</div>
<div className="flex items-center gap-2">
<div>
<ShadTooltip
content={
disableFunctions ? (
<span>Select items to export</span>
) : (
<span>Export selected items</span>
)
}
>
<Button
unstyled
onClick={handleExport}
disabled={disableFunctions}
>
<IconComponent
name="FileDown"
className={cn("h-5 w-5 text-primary transition-all")}
/>
</Button>
</ShadTooltip>
</div>
<div>
<ShadTooltip
content={
disableFunctions ? (
<span>Select items to duplicate</span>
) : (
<span>Duplicate selected items</span>
)
}
>
<Button
unstyled
onClick={handleDuplicate}
disabled={disableFunctions}
>
<IconComponent
name="Copy"
className={cn("h-5 w-5 text-primary transition-all")}
/>
</Button>
</ShadTooltip>
</div>
<div>
<ShadTooltip
content={
disableFunctions ? (
<span>Select items to delete</span>
) : (
<span>Delete selected items</span>
)
}
>
<Button
unstyled
onClick={handleDelete}
disabled={disableFunctions}
>
<IconComponent
name="Trash2"
className={cn(
"h-5 w-5 text-primary transition-all",
disableFunctions ? "" : "hover:text-status-red",
)}
/>
</Button>
</ShadTooltip>
</div>
</div>
</div>
</>
);
};
export default HeaderComponent;

View file

@ -1,41 +0,0 @@
// Modals.tsx
import TemplatesModal from "@/modals/templatesModal";
import DeleteConfirmationModal from "../../../../modals/deleteConfirmationModal";
interface ModalsProps {
openModal: boolean;
setOpenModal: (value: boolean) => void;
openDeleteFolderModal: boolean;
setOpenDeleteFolderModal: (value: boolean) => void;
handleDeleteFolder: () => void;
}
const ModalsComponent = ({
openModal = false,
setOpenModal = () => {},
openDeleteFolderModal = false,
setOpenDeleteFolderModal = () => {},
handleDeleteFolder = () => {},
}: ModalsProps) => (
<>
{openModal && <TemplatesModal open={openModal} setOpen={setOpenModal} />}
{openDeleteFolderModal && (
<DeleteConfirmationModal
open={openDeleteFolderModal}
setOpen={setOpenDeleteFolderModal}
onConfirm={() => {
handleDeleteFolder();
setOpenDeleteFolderModal(false);
}}
description="folder"
note={
"Deleting the selected folder will remove all associated flows and components."
}
>
<></>
</DeleteConfirmationModal>
)}
</>
);
export default ModalsComponent;

View file

@ -1,68 +0,0 @@
import { SEARCH_TABS } from "@/constants/constants";
import { useCallback, useState } from "react";
import InputSearchComponent from "../inputSearchComponent";
import TabsSearchComponent from "../tabsComponent";
type HeaderTabsSearchComponentProps = {
loading: boolean;
onChangeTab: (tab: string) => void;
onSearch: (search: string) => void;
activeTab: string;
};
const HeaderTabsSearchComponent = ({
loading,
onChangeTab,
onSearch,
activeTab,
}: HeaderTabsSearchComponentProps) => {
const [inputValue, setInputValue] = useState("");
const handleChangeTab = useCallback(
(tab: string) => {
onChangeTab(tab);
},
[onChangeTab],
);
const handleSearch = useCallback(() => {
onSearch(inputValue);
}, [onSearch, inputValue]);
const handleInputChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(e.target.value);
},
[],
);
const handleKeyDown = useCallback(
(e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter") {
handleSearch();
}
},
[handleSearch],
);
return (
<>
<div className="relative flex items-end gap-4">
<InputSearchComponent
loading={loading}
value={inputValue}
onChange={handleInputChange}
onKeyDown={handleKeyDown}
/>
<TabsSearchComponent
tabsOptions={SEARCH_TABS}
setActiveTab={handleChangeTab}
loading={loading}
tabActive={activeTab}
/>
</div>
</>
);
};
export default HeaderTabsSearchComponent;

View file

@ -1,64 +0,0 @@
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
import { useCallback } from "react";
type TabsSearchComponentProps = {
tabsOptions: string[];
setActiveTab: (tab: string) => void;
loading: boolean;
tabActive: string;
};
const TabsSearchComponent = ({
tabsOptions,
setActiveTab,
loading,
tabActive,
}: TabsSearchComponentProps) => {
const navigate = useCustomNavigate();
const changeLocation = useCallback(
(tabOption: string) => {
const location = window.location.pathname;
let newLocation = "";
switch (tabOption) {
case "Flows":
newLocation = location.replace(/.*\/(?:all|components)/, "/flows");
break;
case "Components":
newLocation = location.replace(/.*\/(?:flows|all)/, "/components");
break;
default:
newLocation = location.replace(/.*\/(?:flows|components)/, "/all");
break;
}
navigate(newLocation);
setActiveTab(tabOption);
},
[navigate, setActiveTab],
);
return (
<>
<div className="ml-4 flex w-full gap-2 border-b border-border">
{tabsOptions.map((tabOption, index) => (
<button
key={index}
data-testid={`${tabOption}-button-store`}
disabled={loading}
onClick={() => changeLocation(tabOption)}
className={
(tabActive === tabOption
? "border-b-2 border-primary p-3"
: "border-b-2 border-transparent p-3 text-muted-foreground hover:text-primary") +
(loading ? " cursor-not-allowed" : "")
}
>
{tabOption}
</button>
))}
</div>
</>
);
};
export default TabsSearchComponent;

View file

@ -1,105 +0,0 @@
import { useGetFolderQuery } from "@/controllers/API/queries/folders/use-get-folder";
import useDeleteFlow from "@/hooks/flows/use-delete-flow";
import { useFolderStore } from "@/stores/foldersStore";
import { useIsFetching, useIsMutating } from "@tanstack/react-query";
import { useCallback, useState } from "react";
import { useLocation, useParams } from "react-router-dom";
import ComponentsComponent from "../componentsComponent";
import HeaderTabsSearchComponent from "./components/headerTabsSearchComponent";
type MyCollectionComponentProps = {
type: string;
};
const MyCollectionComponent = ({ type }: MyCollectionComponentProps) => {
const { folderId } = useParams();
const location = useLocation();
const myCollectionId = useFolderStore((state) => state.myCollectionId);
const [pageIndex, setPageIndex] = useState(1);
const [pageSize, setPageSize] = useState(10);
const [filter, setFilter] = useState<string>(() => {
if (location.pathname.includes("components")) return "Components";
if (location.pathname.includes("flows")) return "Flows";
return "All";
});
const [search, setSearch] = useState<string>("");
const { data: folderData, isFetching } = useGetFolderQuery({
id: folderId ?? myCollectionId!,
page: pageIndex,
size: pageSize,
is_component: filter === "Components",
is_flow: filter === "Flows",
search: search,
});
const data = {
flows: folderData?.flows?.items ?? [],
name: folderData?.folder?.name ?? "",
description: folderData?.folder?.description ?? "",
parent_id: folderData?.folder?.parent_id ?? "",
components: folderData?.folder?.components ?? [],
pagination: {
page: folderData?.flows?.page ?? 1,
size: folderData?.flows?.size ?? 10,
total: folderData?.flows?.total ?? 0,
pages: folderData?.flows?.pages ?? 0,
},
};
const isLoadingFolders = !!useIsFetching({
queryKey: ["useGetFolders"],
exact: false,
});
const { deleteFlow, isDeleting } = useDeleteFlow();
const isAddingFlow = !!useIsMutating({
mutationKey: ["usePostAddFlow"],
exact: true,
});
const handlePageChange = useCallback(
(newPageIndex: number, newPageSize: number) => {
setPageIndex(newPageIndex);
setPageSize(newPageSize);
},
[],
);
const onChangeTab = useCallback((newFilter: string) => {
setFilter(newFilter);
setPageIndex(1);
}, []);
const onSearch = useCallback((newSearch: string) => {
setSearch(newSearch);
setPageIndex(1);
}, []);
return (
<>
<HeaderTabsSearchComponent
loading={isFetching || isLoadingFolders || isDeleting || isAddingFlow}
onChangeTab={onChangeTab}
onSearch={onSearch}
activeTab={filter}
/>
<div className="mt-5 flex h-full flex-col">
<ComponentsComponent
type={type}
currentFolder={data.flows}
pagination={data.pagination}
deleteFlow={deleteFlow}
isLoading={
isFetching || isLoadingFolders || isDeleting || isAddingFlow
}
onPaginate={handlePageChange}
/>
</div>
</>
);
};
export default MyCollectionComponent;

View file

@ -1,131 +0,0 @@
import FolderSidebarNav from "@/components/core/folderSidebarComponent";
import { SidebarProvider } from "@/components/ui/sidebar";
import { useDeleteFolders } from "@/controllers/API/queries/folders";
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
import { track } from "@/customization/utils/analytics";
import useAlertStore from "@/stores/alertStore";
import { useIsFetching, useQueryClient } from "@tanstack/react-query";
import { useEffect, useState } from "react";
import { Outlet, useLocation } from "react-router-dom";
import PageLayout from "../../../../components/common/pageLayout";
import DropdownButton from "../../../../components/core/dropdownButtonComponent";
import {
MY_COLLECTION_DESC,
USER_PROJECTS_HEADER,
} from "../../../../constants/constants";
import { useFolderStore } from "../../../../stores/foldersStore";
import useDropdownOptions from "../../hooks/use-dropdown-options";
import ModalsComponent from "../../oldComponents/modalsComponent";
export default function OldHomePage(): JSX.Element {
const location = useLocation();
const pathname = location.pathname;
const [openModal, setOpenModal] = useState(false);
const [openDeleteFolderModal, setOpenDeleteFolderModal] = useState(false);
const is_component = pathname.includes("/components");
const setFolderToEdit = useFolderStore((state) => state.setFolderToEdit);
const navigate = useCustomNavigate();
const setSuccessData = useAlertStore((state) => state.setSuccessData);
const setErrorData = useAlertStore((state) => state.setErrorData);
const folderToEdit = useFolderStore((state) => state.folderToEdit);
const queryClient = useQueryClient();
// cleanup the query cache when the component unmounts
// prevent unnecessary queries on flow update
useEffect(() => {
return () => queryClient.removeQueries({ queryKey: ["useGetFolder"] });
}, []);
const dropdownOptions = useDropdownOptions({
navigate,
is_component,
});
const { mutate } = useDeleteFolders();
const handleDeleteFolder = () => {
mutate(
{
folder_id: folderToEdit?.id!,
},
{
onSuccess: () => {
setSuccessData({
title: "Folder deleted successfully.",
});
navigate("/all");
},
onError: (err) => {
console.error(err);
setErrorData({
title: "Error deleting folder.",
});
},
},
);
};
const isFetchingFolders = !!useIsFetching({
queryKey: ["useGetFolders"],
exact: false,
});
const isFetchingFolder = !!useIsFetching({
queryKey: ["useGetFolder"],
exact: false,
});
const isLoadingFolder = isFetchingFolders || isFetchingFolder;
return (
<>
<div className="flex h-full w-full space-y-8 md:flex-col lg:flex-row lg:space-y-0">
<SidebarProvider>
<aside className="hidden h-full w-fit flex-col space-y-6 px-4 lg:flex">
<FolderSidebarNav
handleChangeFolder={(id: string) => {
navigate(`all/folder/${id}`);
}}
handleDeleteFolder={(item) => {
setFolderToEdit(item);
setOpenDeleteFolderModal(true);
}}
className="w-[20vw] max-w-[288px]"
/>
</aside>
<PageLayout
title={USER_PROJECTS_HEADER}
description={MY_COLLECTION_DESC}
button={
<div className="flex gap-2">
<DropdownButton
firstButtonName="New Project"
onFirstBtnClick={() => {
setOpenModal(true);
track("New Project Button Clicked");
}}
options={dropdownOptions}
plusButton={true}
dropdownOptions={false}
isFetchingFolders={isLoadingFolder}
/>
</div>
}
>
<div className="relative h-full w-full flex-1">
<Outlet />
</div>
</PageLayout>
</SidebarProvider>
</div>
<ModalsComponent
openModal={openModal}
setOpenModal={setOpenModal}
openDeleteFolderModal={openDeleteFolderModal}
setOpenDeleteFolderModal={setOpenDeleteFolderModal}
handleDeleteFolder={handleDeleteFolder}
/>
</>
);
}

View file

@ -1,7 +1,6 @@
import LangflowLogo from "@/assets/LangflowLogo.svg?react";
import ForwardedIconComponent from "@/components/common/genericIconComponent";
import { Button } from "@/components/ui/button";
import { ENABLE_NEW_LOGO } from "@/customization/feature-flags";
import { useFolderStore } from "@/stores/foldersStore";
type EmptyPageProps = {
@ -15,11 +14,7 @@ export const EmptyPage = ({ setOpenModal }: EmptyPageProps) => {
<div className="m-0 h-full w-full bg-secondary p-0">
<div className="text-container">
<div className="relative z-20 flex w-full flex-col items-center justify-center gap-2">
{ENABLE_NEW_LOGO ? (
<LangflowLogo className="h-7 w-8" />
) : (
<span className="fill-foreground text-4xl"></span>
)}
<LangflowLogo className="h-7 w-8" />
<h3
className="pt-5 font-chivo text-2xl font-semibold text-foreground"
data-testid="mainpage_title"

View file

@ -12,8 +12,8 @@ import GridSkeleton from "../../components/gridSkeleton";
import HeaderComponent from "../../components/header";
import ListComponent from "../../components/list";
import ListSkeleton from "../../components/listSkeleton";
import ModalsComponent from "../../components/modalsComponent";
import useFileDrop from "../../hooks/use-on-file-drop";
import ModalsComponent from "../../oldComponents/modalsComponent";
import EmptyFolder from "../emptyFolder";
const HomePage = ({ type }) => {

View file

@ -10,8 +10,8 @@ import { useFolderStore } from "@/stores/foldersStore";
import { useQueryClient } from "@tanstack/react-query";
import { useEffect, useState } from "react";
import { Outlet } from "react-router-dom";
import ModalsComponent from "../components/modalsComponent";
import useFileDrop from "../hooks/use-on-file-drop";
import ModalsComponent from "../oldComponents/modalsComponent";
import EmptyPage from "./emptyPage";
export default function CollectionPage(): JSX.Element {

View file

@ -2,7 +2,6 @@ import LangflowLogo from "@/assets/LangflowLogo.svg?react";
import InputComponent from "@/components/core/parameterRenderComponent/components/inputComponent";
import { useAddUser } from "@/controllers/API/queries/auth";
import { CustomLink } from "@/customization/components/custom-link";
import { ENABLE_NEW_LOGO } from "@/customization/feature-flags";
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
import { track } from "@/customization/utils/analytics";
import * as Form from "@radix-ui/react-form";
@ -91,14 +90,10 @@ export default function SignUp(): JSX.Element {
>
<div className="flex h-full w-full flex-col items-center justify-center bg-muted">
<div className="flex w-72 flex-col items-center justify-center gap-2">
{ENABLE_NEW_LOGO ? (
<LangflowLogo
title="Langflow logo"
className="mb-4 h-10 w-10 scale-[1.5]"
/>
) : (
<span className="mb-4 text-5xl"></span>
)}
<LangflowLogo
title="Langflow logo"
className="mb-4 h-10 w-10 scale-[1.5]"
/>
<span className="mb-6 text-2xl font-semibold text-primary">
Sign up for Langflow
</span>

View file

@ -42,7 +42,7 @@ import useFlowsManagerStore from "../../stores/flowsManagerStore";
import { useStoreStore } from "../../stores/storeStore";
import { storeComponent } from "../../types/store";
import { cn } from "../../utils/utils";
import InputSearchComponent from "../MainPage/oldComponents/myCollectionComponent/components/inputSearchComponent";
import InputSearchComponent from "../MainPage/components/inputSearchComponent";
export default function StorePage(): JSX.Element {
const hasApiKey = useStoreStore((state) => state.hasApiKey);

View file

@ -13,18 +13,13 @@ import { StoreGuard } from "./components/authorization/storeGuard";
import ContextWrapper from "./contexts";
import { CustomNavigate } from "./customization/components/custom-navigate";
import { BASENAME } from "./customization/config-constants";
import {
ENABLE_CUSTOM_PARAM,
ENABLE_HOMEPAGE,
} from "./customization/feature-flags";
import { ENABLE_CUSTOM_PARAM } from "./customization/feature-flags";
import { AppAuthenticatedPage } from "./pages/AppAuthenticatedPage";
import { AppInitPage } from "./pages/AppInitPage";
import { AppWrapperPage } from "./pages/AppWrapperPage";
import { DashboardWrapperPage } from "./pages/DashboardWrapperPage";
import FlowPage from "./pages/FlowPage";
import LoginPage from "./pages/LoginPage";
import MyCollectionComponent from "./pages/MainPage/oldComponents/myCollectionComponent";
import OldHomePage from "./pages/MainPage/oldPages/mainPage";
import CollectionPage from "./pages/MainPage/pages";
import HomePage from "./pages/MainPage/pages/homePage";
import SettingsPage from "./pages/SettingsPage";
@ -66,83 +61,36 @@ const router = createBrowserRouter(
>
<Route path="" element={<AppAuthenticatedPage />}>
<Route path="" element={<DashboardWrapperPage />}>
<Route
path=""
element={
ENABLE_HOMEPAGE ? <CollectionPage /> : <OldHomePage />
}
>
<Route path="" element={<CollectionPage />}>
<Route
index
element={<CustomNavigate replace to={"flows"} />}
/>
<Route
path="flows/"
element={
ENABLE_HOMEPAGE ? (
<HomePage key="flows" type="flows" />
) : (
<MyCollectionComponent key="flows" type="flows" />
)
}
element={<HomePage key="flows" type="flows" />}
>
<Route
path="folder/:folderId"
element={
ENABLE_HOMEPAGE ? (
<HomePage key="flows" type="flows" />
) : (
<MyCollectionComponent key="flows" type="flows" />
)
}
element={<HomePage key="flows" type="flows" />}
/>
</Route>
<Route
path="components/"
element={
ENABLE_HOMEPAGE ? (
<HomePage key="components" type="components" />
) : (
<MyCollectionComponent
key="components"
type="component"
/>
)
}
element={<HomePage key="components" type="components" />}
>
<Route
path="folder/:folderId"
element={
ENABLE_HOMEPAGE ? (
<HomePage key="components" type="components" />
) : (
<MyCollectionComponent
key="components"
type="component"
/>
)
}
element={<HomePage key="components" type="components" />}
/>
</Route>
<Route
path="all/"
element={
ENABLE_HOMEPAGE ? (
<HomePage key="flows" type="flows" />
) : (
<MyCollectionComponent key="all" type="all" />
)
}
element={<HomePage key="flows" type="flows" />}
>
<Route
path="folder/:folderId"
element={
ENABLE_HOMEPAGE ? (
<HomePage key="flows" type="flows" />
) : (
<MyCollectionComponent key="all" type="all" />
)
}
element={<HomePage key="flows" type="flows" />}
/>
</Route>
</Route>