fix: Delete old logo and old dashboard (#6884)
deleted old logo and dashboard, and moved code
This commit is contained in:
parent
037ffb620a
commit
1cc49962d5
23 changed files with 37 additions and 1032 deletions
|
|
@ -7,10 +7,7 @@ import { Button } from "@/components/ui/button";
|
||||||
import { Separator } from "@/components/ui/separator";
|
import { Separator } from "@/components/ui/separator";
|
||||||
import { CustomOrgSelector } from "@/customization/components/custom-org-selector";
|
import { CustomOrgSelector } from "@/customization/components/custom-org-selector";
|
||||||
import { CustomProductSelector } from "@/customization/components/custom-product-selector";
|
import { CustomProductSelector } from "@/customization/components/custom-product-selector";
|
||||||
import {
|
import { ENABLE_DATASTAX_LANGFLOW } from "@/customization/feature-flags";
|
||||||
ENABLE_DATASTAX_LANGFLOW,
|
|
||||||
ENABLE_NEW_LOGO,
|
|
||||||
} from "@/customization/feature-flags";
|
|
||||||
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
import useTheme from "@/customization/hooks/use-custom-theme";
|
import useTheme from "@/customization/hooks/use-custom-theme";
|
||||||
import { useResetDismissUpdateAll } from "@/hooks/use-reset-dismiss-update-all";
|
import { useResetDismissUpdateAll } from "@/hooks/use-reset-dismiss-update-all";
|
||||||
|
|
@ -67,10 +64,8 @@ export default function AppHeader(): JSX.Element {
|
||||||
>
|
>
|
||||||
{ENABLE_DATASTAX_LANGFLOW ? (
|
{ENABLE_DATASTAX_LANGFLOW ? (
|
||||||
<DataStaxLogo className="fill-black dark:fill-[white]" />
|
<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>
|
</Button>
|
||||||
{ENABLE_DATASTAX_LANGFLOW && (
|
{ENABLE_DATASTAX_LANGFLOW && (
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,4 @@ export const ENABLE_BRANDING = true;
|
||||||
export const ENABLE_MVPS = false;
|
export const ENABLE_MVPS = false;
|
||||||
export const ENABLE_CUSTOM_PARAM = false;
|
export const ENABLE_CUSTOM_PARAM = false;
|
||||||
export const ENABLE_INTEGRATIONS = false;
|
export const ENABLE_INTEGRATIONS = false;
|
||||||
export const ENABLE_NEW_LOGO = true;
|
|
||||||
export const ENABLE_DATASTAX_LANGFLOW = false;
|
export const ENABLE_DATASTAX_LANGFLOW = false;
|
||||||
export const ENABLE_HOMEPAGE = true;
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
import LangflowLogo from "@/assets/LangflowLogo.svg?react";
|
import LangflowLogo from "@/assets/LangflowLogo.svg?react";
|
||||||
import ChainLogo from "@/assets/logo.svg?react";
|
|
||||||
import { TextEffectPerChar } from "@/components/ui/textAnimation";
|
import { TextEffectPerChar } from "@/components/ui/textAnimation";
|
||||||
import { ENABLE_NEW_LOGO } from "@/customization/feature-flags";
|
|
||||||
import { track } from "@/customization/utils/analytics";
|
import { track } from "@/customization/utils/analytics";
|
||||||
import { useMessagesStore } from "@/stores/messagesStore";
|
import { useMessagesStore } from "@/stores/messagesStore";
|
||||||
import { useUtilityStore } from "@/stores/utilityStore";
|
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 h-full w-full flex-col items-center justify-center">
|
||||||
<div className="flex flex-col items-center justify-center gap-4 p-8">
|
<div className="flex flex-col items-center justify-center gap-4 p-8">
|
||||||
{ENABLE_NEW_LOGO ? (
|
<LangflowLogo
|
||||||
<LangflowLogo
|
title="Langflow logo"
|
||||||
title="Langflow logo"
|
className="h-10 w-10 scale-[1.5]"
|
||||||
className="h-10 w-10 scale-[1.5]"
|
/>
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<ChainLogo
|
|
||||||
title="Langflow logo"
|
|
||||||
className="h-10 w-10 scale-[1.5]"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<div className="flex flex-col items-center justify-center">
|
<div className="flex flex-col items-center justify-center">
|
||||||
<h3 className="mt-2 pb-2 text-2xl font-semibold text-primary">
|
<h3 className="mt-2 pb-2 text-2xl font-semibold text-primary">
|
||||||
New chat
|
New chat
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,13 @@
|
||||||
import LangflowLogo from "@/assets/LangflowLogo.svg?react";
|
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() {
|
export default function LogoIcon() {
|
||||||
return (
|
return (
|
||||||
<div className="relative flex h-8 w-8 items-center justify-center rounded-md bg-muted">
|
<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">
|
<div className="flex h-8 w-8 items-center justify-center">
|
||||||
{ENABLE_NEW_LOGO ? (
|
<LangflowLogo
|
||||||
<LangflowLogo
|
title="Langflow Logo"
|
||||||
title="Langflow Logo"
|
className="absolute h-[18px] w-[18px]"
|
||||||
className="absolute h-[18px] w-[18px]"
|
/>
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<ChainLogo
|
|
||||||
title="Langflow Logo"
|
|
||||||
className="absolute h-[18px] w-[18px]"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import LangflowLogo from "@/assets/LangflowLogo.svg?react";
|
import LangflowLogo from "@/assets/LangflowLogo.svg?react";
|
||||||
import { useLoginUser } from "@/controllers/API/queries/auth";
|
import { useLoginUser } from "@/controllers/API/queries/auth";
|
||||||
import { ENABLE_NEW_LOGO } from "@/customization/feature-flags";
|
|
||||||
import { useContext, useState } from "react";
|
import { useContext, useState } from "react";
|
||||||
import { Button } from "../../../components/ui/button";
|
import { Button } from "../../../components/ui/button";
|
||||||
import { Input } from "../../../components/ui/input";
|
import { Input } from "../../../components/ui/input";
|
||||||
|
|
@ -51,14 +50,7 @@ export default function LoginAdminPage() {
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full flex-col items-center justify-center bg-muted">
|
<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">
|
<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]" />
|
||||||
<LangflowLogo
|
|
||||||
title="Langflow logo"
|
|
||||||
className="h-10 w-10 scale-[1.5]"
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<span className="mb-4 text-5xl">⛓️</span>
|
|
||||||
)}
|
|
||||||
<span className="mb-6 text-2xl font-semibold text-primary">Admin</span>
|
<span className="mb-6 text-2xl font-semibold text-primary">Admin</span>
|
||||||
<Input
|
<Input
|
||||||
onChange={({ target: { value } }) => {
|
onChange={({ target: { value } }) => {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import LangflowLogo from "@/assets/LangflowLogo.svg?react";
|
import LangflowLogo from "@/assets/LangflowLogo.svg?react";
|
||||||
import { ENABLE_NEW_LOGO } from "@/customization/feature-flags";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import { Input } from "../../components/ui/input";
|
import { Input } from "../../components/ui/input";
|
||||||
|
|
@ -19,14 +18,10 @@ export default function DeleteAccountPage() {
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full flex-col items-center justify-center bg-muted">
|
<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">
|
<div className="flex w-72 flex-col items-center justify-center gap-2">
|
||||||
{ENABLE_NEW_LOGO ? (
|
<LangflowLogo
|
||||||
<LangflowLogo
|
title="Langflow logo"
|
||||||
title="Langflow logo"
|
className="mb-4 h-10 w-10 scale-[1.5]"
|
||||||
className="mb-4 h-10 w-10 scale-[1.5]"
|
/>
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<span className="mb-4 text-5xl">⛓️</span>
|
|
||||||
)}
|
|
||||||
<span className="mb-4 text-center text-2xl font-semibold text-primary">
|
<span className="mb-4 text-center text-2xl font-semibold text-primary">
|
||||||
Delete your account
|
Delete your account
|
||||||
</span>
|
</span>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import LangflowLogo from "@/assets/LangflowLogo.svg?react";
|
import LangflowLogo from "@/assets/LangflowLogo.svg?react";
|
||||||
import { useLoginUser } from "@/controllers/API/queries/auth";
|
import { useLoginUser } from "@/controllers/API/queries/auth";
|
||||||
import { CustomLink } from "@/customization/components/custom-link";
|
import { CustomLink } from "@/customization/components/custom-link";
|
||||||
import { ENABLE_NEW_LOGO } from "@/customization/feature-flags";
|
|
||||||
import * as Form from "@radix-ui/react-form";
|
import * as Form from "@radix-ui/react-form";
|
||||||
import { useContext, useState } from "react";
|
import { useContext, useState } from "react";
|
||||||
import InputComponent from "../../components/core/parameterRenderComponent/components/inputComponent";
|
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 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">
|
<div className="flex w-72 flex-col items-center justify-center gap-2">
|
||||||
{ENABLE_NEW_LOGO ? (
|
<LangflowLogo
|
||||||
<LangflowLogo
|
title="Langflow logo"
|
||||||
title="Langflow logo"
|
className="mb-4 h-10 w-10 scale-[1.5]"
|
||||||
className="mb-4 h-10 w-10 scale-[1.5]"
|
/>
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<span className="mb-4 text-5xl">⛓️</span>
|
|
||||||
)}
|
|
||||||
<span className="mb-6 text-2xl font-semibold text-primary">
|
<span className="mb-6 text-2xl font-semibold text-primary">
|
||||||
Sign in to Langflow
|
Sign in to Langflow
|
||||||
</span>
|
</span>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
import ForwardedIconComponent from "@/components/common/genericIconComponent";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
import { ChangeEvent, KeyboardEvent } from "react";
|
import { ChangeEvent, KeyboardEvent } from "react";
|
||||||
import ForwardedIconComponent from "../../../../../../components/common/genericIconComponent";
|
|
||||||
import { Input } from "../../../../../../components/ui/input";
|
|
||||||
|
|
||||||
type InputSearchComponentProps = {
|
type InputSearchComponentProps = {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import LangflowLogo from "@/assets/LangflowLogo.svg?react";
|
import LangflowLogo from "@/assets/LangflowLogo.svg?react";
|
||||||
import ForwardedIconComponent from "@/components/common/genericIconComponent";
|
import ForwardedIconComponent from "@/components/common/genericIconComponent";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { ENABLE_NEW_LOGO } from "@/customization/feature-flags";
|
|
||||||
import { useFolderStore } from "@/stores/foldersStore";
|
import { useFolderStore } from "@/stores/foldersStore";
|
||||||
|
|
||||||
type EmptyPageProps = {
|
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="m-0 h-full w-full bg-secondary p-0">
|
||||||
<div className="text-container">
|
<div className="text-container">
|
||||||
<div className="relative z-20 flex w-full flex-col items-center justify-center gap-2">
|
<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" />
|
||||||
<LangflowLogo className="h-7 w-8" />
|
|
||||||
) : (
|
|
||||||
<span className="fill-foreground text-4xl">⛓️</span>
|
|
||||||
)}
|
|
||||||
<h3
|
<h3
|
||||||
className="pt-5 font-chivo text-2xl font-semibold text-foreground"
|
className="pt-5 font-chivo text-2xl font-semibold text-foreground"
|
||||||
data-testid="mainpage_title"
|
data-testid="mainpage_title"
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ import GridSkeleton from "../../components/gridSkeleton";
|
||||||
import HeaderComponent from "../../components/header";
|
import HeaderComponent from "../../components/header";
|
||||||
import ListComponent from "../../components/list";
|
import ListComponent from "../../components/list";
|
||||||
import ListSkeleton from "../../components/listSkeleton";
|
import ListSkeleton from "../../components/listSkeleton";
|
||||||
|
import ModalsComponent from "../../components/modalsComponent";
|
||||||
import useFileDrop from "../../hooks/use-on-file-drop";
|
import useFileDrop from "../../hooks/use-on-file-drop";
|
||||||
import ModalsComponent from "../../oldComponents/modalsComponent";
|
|
||||||
import EmptyFolder from "../emptyFolder";
|
import EmptyFolder from "../emptyFolder";
|
||||||
|
|
||||||
const HomePage = ({ type }) => {
|
const HomePage = ({ type }) => {
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ import { useFolderStore } from "@/stores/foldersStore";
|
||||||
import { useQueryClient } from "@tanstack/react-query";
|
import { useQueryClient } from "@tanstack/react-query";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Outlet } from "react-router-dom";
|
import { Outlet } from "react-router-dom";
|
||||||
|
import ModalsComponent from "../components/modalsComponent";
|
||||||
import useFileDrop from "../hooks/use-on-file-drop";
|
import useFileDrop from "../hooks/use-on-file-drop";
|
||||||
import ModalsComponent from "../oldComponents/modalsComponent";
|
|
||||||
import EmptyPage from "./emptyPage";
|
import EmptyPage from "./emptyPage";
|
||||||
|
|
||||||
export default function CollectionPage(): JSX.Element {
|
export default function CollectionPage(): JSX.Element {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import LangflowLogo from "@/assets/LangflowLogo.svg?react";
|
||||||
import InputComponent from "@/components/core/parameterRenderComponent/components/inputComponent";
|
import InputComponent from "@/components/core/parameterRenderComponent/components/inputComponent";
|
||||||
import { useAddUser } from "@/controllers/API/queries/auth";
|
import { useAddUser } from "@/controllers/API/queries/auth";
|
||||||
import { CustomLink } from "@/customization/components/custom-link";
|
import { CustomLink } from "@/customization/components/custom-link";
|
||||||
import { ENABLE_NEW_LOGO } from "@/customization/feature-flags";
|
|
||||||
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
import { track } from "@/customization/utils/analytics";
|
import { track } from "@/customization/utils/analytics";
|
||||||
import * as Form from "@radix-ui/react-form";
|
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 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">
|
<div className="flex w-72 flex-col items-center justify-center gap-2">
|
||||||
{ENABLE_NEW_LOGO ? (
|
<LangflowLogo
|
||||||
<LangflowLogo
|
title="Langflow logo"
|
||||||
title="Langflow logo"
|
className="mb-4 h-10 w-10 scale-[1.5]"
|
||||||
className="mb-4 h-10 w-10 scale-[1.5]"
|
/>
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<span className="mb-4 text-5xl">⛓️</span>
|
|
||||||
)}
|
|
||||||
<span className="mb-6 text-2xl font-semibold text-primary">
|
<span className="mb-6 text-2xl font-semibold text-primary">
|
||||||
Sign up for Langflow
|
Sign up for Langflow
|
||||||
</span>
|
</span>
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||||
import { useStoreStore } from "../../stores/storeStore";
|
import { useStoreStore } from "../../stores/storeStore";
|
||||||
import { storeComponent } from "../../types/store";
|
import { storeComponent } from "../../types/store";
|
||||||
import { cn } from "../../utils/utils";
|
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 {
|
export default function StorePage(): JSX.Element {
|
||||||
const hasApiKey = useStoreStore((state) => state.hasApiKey);
|
const hasApiKey = useStoreStore((state) => state.hasApiKey);
|
||||||
|
|
|
||||||
|
|
@ -13,18 +13,13 @@ import { StoreGuard } from "./components/authorization/storeGuard";
|
||||||
import ContextWrapper from "./contexts";
|
import ContextWrapper from "./contexts";
|
||||||
import { CustomNavigate } from "./customization/components/custom-navigate";
|
import { CustomNavigate } from "./customization/components/custom-navigate";
|
||||||
import { BASENAME } from "./customization/config-constants";
|
import { BASENAME } from "./customization/config-constants";
|
||||||
import {
|
import { ENABLE_CUSTOM_PARAM } from "./customization/feature-flags";
|
||||||
ENABLE_CUSTOM_PARAM,
|
|
||||||
ENABLE_HOMEPAGE,
|
|
||||||
} from "./customization/feature-flags";
|
|
||||||
import { AppAuthenticatedPage } from "./pages/AppAuthenticatedPage";
|
import { AppAuthenticatedPage } from "./pages/AppAuthenticatedPage";
|
||||||
import { AppInitPage } from "./pages/AppInitPage";
|
import { AppInitPage } from "./pages/AppInitPage";
|
||||||
import { AppWrapperPage } from "./pages/AppWrapperPage";
|
import { AppWrapperPage } from "./pages/AppWrapperPage";
|
||||||
import { DashboardWrapperPage } from "./pages/DashboardWrapperPage";
|
import { DashboardWrapperPage } from "./pages/DashboardWrapperPage";
|
||||||
import FlowPage from "./pages/FlowPage";
|
import FlowPage from "./pages/FlowPage";
|
||||||
import LoginPage from "./pages/LoginPage";
|
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 CollectionPage from "./pages/MainPage/pages";
|
||||||
import HomePage from "./pages/MainPage/pages/homePage";
|
import HomePage from "./pages/MainPage/pages/homePage";
|
||||||
import SettingsPage from "./pages/SettingsPage";
|
import SettingsPage from "./pages/SettingsPage";
|
||||||
|
|
@ -66,83 +61,36 @@ const router = createBrowserRouter(
|
||||||
>
|
>
|
||||||
<Route path="" element={<AppAuthenticatedPage />}>
|
<Route path="" element={<AppAuthenticatedPage />}>
|
||||||
<Route path="" element={<DashboardWrapperPage />}>
|
<Route path="" element={<DashboardWrapperPage />}>
|
||||||
<Route
|
<Route path="" element={<CollectionPage />}>
|
||||||
path=""
|
|
||||||
element={
|
|
||||||
ENABLE_HOMEPAGE ? <CollectionPage /> : <OldHomePage />
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Route
|
<Route
|
||||||
index
|
index
|
||||||
element={<CustomNavigate replace to={"flows"} />}
|
element={<CustomNavigate replace to={"flows"} />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="flows/"
|
path="flows/"
|
||||||
element={
|
element={<HomePage key="flows" type="flows" />}
|
||||||
ENABLE_HOMEPAGE ? (
|
|
||||||
<HomePage key="flows" type="flows" />
|
|
||||||
) : (
|
|
||||||
<MyCollectionComponent key="flows" type="flows" />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<Route
|
<Route
|
||||||
path="folder/:folderId"
|
path="folder/:folderId"
|
||||||
element={
|
element={<HomePage key="flows" type="flows" />}
|
||||||
ENABLE_HOMEPAGE ? (
|
|
||||||
<HomePage key="flows" type="flows" />
|
|
||||||
) : (
|
|
||||||
<MyCollectionComponent key="flows" type="flows" />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
<Route
|
<Route
|
||||||
path="components/"
|
path="components/"
|
||||||
element={
|
element={<HomePage key="components" type="components" />}
|
||||||
ENABLE_HOMEPAGE ? (
|
|
||||||
<HomePage key="components" type="components" />
|
|
||||||
) : (
|
|
||||||
<MyCollectionComponent
|
|
||||||
key="components"
|
|
||||||
type="component"
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<Route
|
<Route
|
||||||
path="folder/:folderId"
|
path="folder/:folderId"
|
||||||
element={
|
element={<HomePage key="components" type="components" />}
|
||||||
ENABLE_HOMEPAGE ? (
|
|
||||||
<HomePage key="components" type="components" />
|
|
||||||
) : (
|
|
||||||
<MyCollectionComponent
|
|
||||||
key="components"
|
|
||||||
type="component"
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
<Route
|
<Route
|
||||||
path="all/"
|
path="all/"
|
||||||
element={
|
element={<HomePage key="flows" type="flows" />}
|
||||||
ENABLE_HOMEPAGE ? (
|
|
||||||
<HomePage key="flows" type="flows" />
|
|
||||||
) : (
|
|
||||||
<MyCollectionComponent key="all" type="all" />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<Route
|
<Route
|
||||||
path="folder/:folderId"
|
path="folder/:folderId"
|
||||||
element={
|
element={<HomePage key="flows" type="flows" />}
|
||||||
ENABLE_HOMEPAGE ? (
|
|
||||||
<HomePage key="flows" type="flows" />
|
|
||||||
) : (
|
|
||||||
<MyCollectionComponent key="all" type="all" />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
</Route>
|
</Route>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue