fix: update project description, update alerts animation, fix delete and duplicate loading (#3835)
* Deleted "personal" from manage your projects * Removed animations from alerts on the dropdown * Changed useDeleteFlow to return isPending as well * Added delete loading to components and added filter of components not present in "flows" for deletion * added isDuplicating as a isMutating with the postAddFlow
This commit is contained in:
parent
a7d1449e9d
commit
bad009c0fa
7 changed files with 167 additions and 156 deletions
|
|
@ -1,5 +1,4 @@
|
||||||
import { CustomLink } from "@/customization/components/custom-link";
|
import { CustomLink } from "@/customization/components/custom-link";
|
||||||
import { Transition } from "@headlessui/react";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import IconComponent from "../../../../components/genericIconComponent";
|
import IconComponent from "../../../../components/genericIconComponent";
|
||||||
import { SingleAlertComponentType } from "../../../../types/alerts";
|
import { SingleAlertComponentType } from "../../../../types/alerts";
|
||||||
|
|
@ -11,161 +10,147 @@ export default function SingleAlert({
|
||||||
const [show, setShow] = useState(true);
|
const [show, setShow] = useState(true);
|
||||||
const type = dropItem.type;
|
const type = dropItem.type;
|
||||||
|
|
||||||
return (
|
return type === "error" ? (
|
||||||
<Transition
|
<div
|
||||||
className="noflow nowheel nopan nodelete nodrag relative"
|
className="mx-2 mb-2 flex rounded-md bg-error-background p-3"
|
||||||
show={show}
|
key={dropItem.id}
|
||||||
appear={true}
|
|
||||||
enter="transition-transform duration-500 ease-out"
|
|
||||||
enterFrom={"transform translate-x-[-100%]"}
|
|
||||||
enterTo={"transform translate-x-0"}
|
|
||||||
leave="transition-transform duration-500 ease-in"
|
|
||||||
leaveFrom={"transform translate-x-0"}
|
|
||||||
leaveTo={"transform translate-x-[-100%]"}
|
|
||||||
>
|
>
|
||||||
{type === "error" ? (
|
<div className="flex-shrink-0">
|
||||||
<div
|
<IconComponent
|
||||||
className="mx-2 mb-2 flex rounded-md bg-error-background p-3"
|
name="XCircle"
|
||||||
key={dropItem.id}
|
className="h-5 w-5 text-status-red"
|
||||||
>
|
aria-hidden="true"
|
||||||
<div className="flex-shrink-0">
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="ml-3">
|
||||||
|
<h3 className="text-sm font-medium text-error-foreground word-break-break-word">
|
||||||
|
{dropItem.title}
|
||||||
|
</h3>
|
||||||
|
{dropItem.list ? (
|
||||||
|
<div className="mt-2 text-sm text-error-foreground">
|
||||||
|
<ul className="list-disc space-y-1 pl-5">
|
||||||
|
{dropItem.list.map((item, idx) => (
|
||||||
|
<li className="word-break-break-word" key={idx}>
|
||||||
|
{item}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="ml-auto pl-3">
|
||||||
|
<div className="-mx-1.5 -my-1.5">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
setShow(false);
|
||||||
|
setTimeout(() => {
|
||||||
|
removeAlert(dropItem.id);
|
||||||
|
}, 500);
|
||||||
|
}}
|
||||||
|
className="inline-flex rounded-md p-1.5 text-status-red"
|
||||||
|
>
|
||||||
|
<span className="sr-only">Dismiss</span>
|
||||||
<IconComponent
|
<IconComponent
|
||||||
name="XCircle"
|
name="X"
|
||||||
className="h-5 w-5 text-status-red"
|
className="h-4 w-4 text-error-foreground"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</button>
|
||||||
<div className="ml-3">
|
|
||||||
<h3 className="text-sm font-medium text-error-foreground word-break-break-word">
|
|
||||||
{dropItem.title}
|
|
||||||
</h3>
|
|
||||||
{dropItem.list ? (
|
|
||||||
<div className="mt-2 text-sm text-error-foreground">
|
|
||||||
<ul className="list-disc space-y-1 pl-5">
|
|
||||||
{dropItem.list.map((item, idx) => (
|
|
||||||
<li className="word-break-break-word" key={idx}>
|
|
||||||
{item}
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="ml-auto pl-3">
|
|
||||||
<div className="-mx-1.5 -my-1.5">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => {
|
|
||||||
setShow(false);
|
|
||||||
setTimeout(() => {
|
|
||||||
removeAlert(dropItem.id);
|
|
||||||
}, 500);
|
|
||||||
}}
|
|
||||||
className="inline-flex rounded-md p-1.5 text-status-red"
|
|
||||||
>
|
|
||||||
<span className="sr-only">Dismiss</span>
|
|
||||||
<IconComponent
|
|
||||||
name="X"
|
|
||||||
className="h-4 w-4 text-error-foreground"
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
) : type === "notice" ? (
|
</div>
|
||||||
<div
|
</div>
|
||||||
className="mx-2 mb-2 flex rounded-md bg-info-background p-3"
|
) : type === "notice" ? (
|
||||||
key={dropItem.id}
|
<div
|
||||||
>
|
className="mx-2 mb-2 flex rounded-md bg-info-background p-3"
|
||||||
<div className="flex-shrink-0 cursor-help">
|
key={dropItem.id}
|
||||||
|
>
|
||||||
|
<div className="flex-shrink-0 cursor-help">
|
||||||
|
<IconComponent
|
||||||
|
name="Info"
|
||||||
|
className="h-5 w-5 text-status-blue"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="ml-3 flex-1 md:flex md:justify-between">
|
||||||
|
<p className="text-sm font-medium text-info-foreground">
|
||||||
|
{dropItem.title}
|
||||||
|
</p>
|
||||||
|
<p className="mt-3 text-sm md:ml-6 md:mt-0">
|
||||||
|
{dropItem.link ? (
|
||||||
|
<CustomLink
|
||||||
|
to={dropItem.link}
|
||||||
|
className="whitespace-nowrap font-medium text-info-foreground hover:text-accent-foreground"
|
||||||
|
>
|
||||||
|
Details
|
||||||
|
</CustomLink>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="ml-auto pl-3">
|
||||||
|
<div className="-mx-1.5 -my-1.5">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
setShow(false);
|
||||||
|
setTimeout(() => {
|
||||||
|
removeAlert(dropItem.id);
|
||||||
|
}, 500);
|
||||||
|
}}
|
||||||
|
className="inline-flex rounded-md p-1.5 text-info-foreground"
|
||||||
|
>
|
||||||
|
<span className="sr-only">Dismiss</span>
|
||||||
<IconComponent
|
<IconComponent
|
||||||
name="Info"
|
name="X"
|
||||||
className="h-5 w-5 text-status-blue"
|
className="h-4 w-4 text-info-foreground"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</button>
|
||||||
<div className="ml-3 flex-1 md:flex md:justify-between">
|
|
||||||
<p className="text-sm font-medium text-info-foreground">
|
|
||||||
{dropItem.title}
|
|
||||||
</p>
|
|
||||||
<p className="mt-3 text-sm md:ml-6 md:mt-0">
|
|
||||||
{dropItem.link ? (
|
|
||||||
<CustomLink
|
|
||||||
to={dropItem.link}
|
|
||||||
className="whitespace-nowrap font-medium text-info-foreground hover:text-accent-foreground"
|
|
||||||
>
|
|
||||||
Details
|
|
||||||
</CustomLink>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="ml-auto pl-3">
|
|
||||||
<div className="-mx-1.5 -my-1.5">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => {
|
|
||||||
setShow(false);
|
|
||||||
setTimeout(() => {
|
|
||||||
removeAlert(dropItem.id);
|
|
||||||
}, 500);
|
|
||||||
}}
|
|
||||||
className="inline-flex rounded-md p-1.5 text-info-foreground"
|
|
||||||
>
|
|
||||||
<span className="sr-only">Dismiss</span>
|
|
||||||
<IconComponent
|
|
||||||
name="X"
|
|
||||||
className="h-4 w-4 text-info-foreground"
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
</div>
|
||||||
<div
|
</div>
|
||||||
className="mx-2 mb-2 flex rounded-md bg-success-background p-3"
|
) : (
|
||||||
key={dropItem.id}
|
<div
|
||||||
>
|
className="mx-2 mb-2 flex rounded-md bg-success-background p-3"
|
||||||
<div className="flex-shrink-0">
|
key={dropItem.id}
|
||||||
|
>
|
||||||
|
<div className="flex-shrink-0">
|
||||||
|
<IconComponent
|
||||||
|
name="CheckCircle2"
|
||||||
|
className="h-5 w-5 text-status-green"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="ml-3">
|
||||||
|
<p className="text-sm font-medium text-success-foreground">
|
||||||
|
{dropItem.title}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="ml-auto pl-3">
|
||||||
|
<div className="-mx-1.5 -my-1.5">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
setShow(false);
|
||||||
|
setTimeout(() => {
|
||||||
|
removeAlert(dropItem.id);
|
||||||
|
}, 500);
|
||||||
|
}}
|
||||||
|
className="inline-flex rounded-md p-1.5 text-status-green"
|
||||||
|
>
|
||||||
|
<span className="sr-only">Dismiss</span>
|
||||||
<IconComponent
|
<IconComponent
|
||||||
name="CheckCircle2"
|
name="X"
|
||||||
className="h-5 w-5 text-status-green"
|
className="h-4 w-4 text-success-foreground"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</button>
|
||||||
<div className="ml-3">
|
|
||||||
<p className="text-sm font-medium text-success-foreground">
|
|
||||||
{dropItem.title}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="ml-auto pl-3">
|
|
||||||
<div className="-mx-1.5 -my-1.5">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => {
|
|
||||||
setShow(false);
|
|
||||||
setTimeout(() => {
|
|
||||||
removeAlert(dropItem.id);
|
|
||||||
}, 500);
|
|
||||||
}}
|
|
||||||
className="inline-flex rounded-md p-1.5 text-status-green"
|
|
||||||
>
|
|
||||||
<span className="sr-only">Dismiss</span>
|
|
||||||
<IconComponent
|
|
||||||
name="X"
|
|
||||||
className="h-4 w-4 text-success-foreground"
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
</div>
|
||||||
</Transition>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -703,7 +703,7 @@ export const CHAT_INPUT_PLACEHOLDER =
|
||||||
export const CHAT_INPUT_PLACEHOLDER_SEND = "Send a message...";
|
export const CHAT_INPUT_PLACEHOLDER_SEND = "Send a message...";
|
||||||
export const EDIT_CODE_TITLE = "Edit Code";
|
export const EDIT_CODE_TITLE = "Edit Code";
|
||||||
export const MY_COLLECTION_DESC =
|
export const MY_COLLECTION_DESC =
|
||||||
"Manage your personal projects. Download and upload entire collections.";
|
"Manage your projects. Download and upload entire collections.";
|
||||||
export const STORE_DESC = "Explore community-shared flows and components.";
|
export const STORE_DESC = "Explore community-shared flows and components.";
|
||||||
export const STORE_TITLE = "Langflow Store";
|
export const STORE_TITLE = "Langflow Store";
|
||||||
export const NO_API_KEY = "You don't have an API key.";
|
export const NO_API_KEY = "You don't have an API key.";
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ const useAddFlow = () => {
|
||||||
);
|
);
|
||||||
const flows = useFlowsManagerStore((state) => state.flows);
|
const flows = useFlowsManagerStore((state) => state.flows);
|
||||||
const setFlows = useFlowsManagerStore((state) => state.setFlows);
|
const setFlows = useFlowsManagerStore((state) => state.setFlows);
|
||||||
const deleteFlow = useDeleteFlow();
|
const { deleteFlow } = useDeleteFlow();
|
||||||
|
|
||||||
const { folderId } = useParams();
|
const { folderId } = useParams();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ const useDeleteFlow = () => {
|
||||||
const flows = useFlowsManagerStore((state) => state.flows);
|
const flows = useFlowsManagerStore((state) => state.flows);
|
||||||
const setFlows = useFlowsManagerStore((state) => state.setFlows);
|
const setFlows = useFlowsManagerStore((state) => state.setFlows);
|
||||||
|
|
||||||
const { mutate } = useDeleteDeleteFlows();
|
const { mutate, isPending } = useDeleteDeleteFlows();
|
||||||
|
|
||||||
const deleteFlow = async ({
|
const deleteFlow = async ({
|
||||||
id,
|
id,
|
||||||
|
|
@ -45,7 +45,7 @@ const useDeleteFlow = () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return deleteFlow;
|
return { deleteFlow, isDeleting: isPending };
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useDeleteFlow;
|
export default useDeleteFlow;
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ export const SidebarDraggableComponent = forwardRef(
|
||||||
ref,
|
ref,
|
||||||
) => {
|
) => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const deleteFlow = useDeleteFlow();
|
const { deleteFlow } = useDeleteFlow();
|
||||||
const flows = useFlowsManagerStore((state) => state.flows);
|
const flows = useFlowsManagerStore((state) => state.flows);
|
||||||
|
|
||||||
const version = useDarkStore((state) => state.version);
|
const version = useDarkStore((state) => state.version);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { usePostDownloadMultipleFlows } from "@/controllers/API/queries/flows";
|
import { usePostDownloadMultipleFlows } from "@/controllers/API/queries/flows";
|
||||||
import useDeleteFlow from "@/hooks/flows/use-delete-flow";
|
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { FormProvider, useForm, useWatch } from "react-hook-form";
|
import { FormProvider, useForm, useWatch } from "react-hook-form";
|
||||||
import { useLocation, useParams } from "react-router-dom";
|
import { useLocation, useParams } from "react-router-dom";
|
||||||
|
|
@ -29,10 +28,12 @@ export default function ComponentsComponent({
|
||||||
type = "all",
|
type = "all",
|
||||||
currentFolder,
|
currentFolder,
|
||||||
isLoading,
|
isLoading,
|
||||||
|
deleteFlow,
|
||||||
}: {
|
}: {
|
||||||
type?: string;
|
type?: string;
|
||||||
currentFolder?: FolderType;
|
currentFolder?: FolderType;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
|
deleteFlow: ({ id }: { id: string[] }) => Promise<void>;
|
||||||
}) {
|
}) {
|
||||||
const { folderId } = useParams();
|
const { folderId } = useParams();
|
||||||
|
|
||||||
|
|
@ -176,8 +177,6 @@ export default function ComponentsComponent({
|
||||||
handleExport,
|
handleExport,
|
||||||
);
|
);
|
||||||
|
|
||||||
const deleteFlow = useDeleteFlow();
|
|
||||||
|
|
||||||
const handleDeleteMultiple = () => {
|
const handleDeleteMultiple = () => {
|
||||||
deleteFlow({ id: selectedFlowsComponentsCards })
|
deleteFlow({ id: selectedFlowsComponentsCards })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import { useGetFolderQuery } from "@/controllers/API/queries/folders/use-get-folder";
|
import { useGetFolderQuery } from "@/controllers/API/queries/folders/use-get-folder";
|
||||||
|
import useDeleteFlow from "@/hooks/flows/use-delete-flow";
|
||||||
|
import useFlowsManagerStore from "@/stores/flowsManagerStore";
|
||||||
import { useFolderStore } from "@/stores/foldersStore";
|
import { useFolderStore } from "@/stores/foldersStore";
|
||||||
import { useIsFetching } from "@tanstack/react-query";
|
import { useIsFetching, useIsMutating } from "@tanstack/react-query";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import ComponentsComponent from "../componentsComponent";
|
import ComponentsComponent from "../componentsComponent";
|
||||||
import HeaderTabsSearchComponent from "./components/headerTabsSearchComponent";
|
import HeaderTabsSearchComponent from "./components/headerTabsSearchComponent";
|
||||||
|
|
@ -13,27 +15,52 @@ const MyCollectionComponent = ({ type }: MyCollectionComponentProps) => {
|
||||||
const { folderId } = useParams();
|
const { folderId } = useParams();
|
||||||
const myCollectionId = useFolderStore((state) => state.myCollectionId);
|
const myCollectionId = useFolderStore((state) => state.myCollectionId);
|
||||||
|
|
||||||
const { data, isFetching } = useGetFolderQuery(
|
const flows = useFlowsManagerStore((state) => state.flows);
|
||||||
|
|
||||||
|
const { data: folderData, isFetching } = useGetFolderQuery(
|
||||||
{
|
{
|
||||||
id: folderId ?? myCollectionId ?? "",
|
id: folderId ?? myCollectionId ?? "",
|
||||||
},
|
},
|
||||||
{ enabled: !!folderId || !!myCollectionId },
|
{ enabled: !!folderId || !!myCollectionId },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
flows:
|
||||||
|
folderData?.flows.filter((flow) =>
|
||||||
|
flows?.find((f) => f.id === flow.id),
|
||||||
|
) ?? [],
|
||||||
|
name: folderData?.name ?? "",
|
||||||
|
description: folderData?.description ?? "",
|
||||||
|
parent_id: folderData?.parent_id ?? "",
|
||||||
|
components: folderData?.components ?? [],
|
||||||
|
};
|
||||||
|
|
||||||
const isLoadingFolders = !!useIsFetching({
|
const isLoadingFolders = !!useIsFetching({
|
||||||
queryKey: ["useGetFolders"],
|
queryKey: ["useGetFolders"],
|
||||||
exact: false,
|
exact: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { deleteFlow, isDeleting } = useDeleteFlow();
|
||||||
|
|
||||||
|
const isAddingFlow = !!useIsMutating({
|
||||||
|
mutationKey: ["usePostAddFlow"],
|
||||||
|
exact: true,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<HeaderTabsSearchComponent loading={isFetching || isLoadingFolders} />
|
<HeaderTabsSearchComponent
|
||||||
|
loading={isFetching || isLoadingFolders || isDeleting || isAddingFlow}
|
||||||
|
/>
|
||||||
<div className="mt-5 flex h-full flex-col">
|
<div className="mt-5 flex h-full flex-col">
|
||||||
<ComponentsComponent
|
<ComponentsComponent
|
||||||
key={type}
|
key={type}
|
||||||
type={type}
|
type={type}
|
||||||
currentFolder={data}
|
currentFolder={data}
|
||||||
isLoading={isFetching || isLoadingFolders}
|
deleteFlow={deleteFlow}
|
||||||
|
isLoading={
|
||||||
|
isFetching || isLoadingFolders || isDeleting || isAddingFlow
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue