Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Folders Design Uplift #4122

Merged
merged 21 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
985c0d8
move folders to a full page aside
mfortman11 Oct 10, 2024
6045130
new dropdown + styles
mfortman11 Oct 11, 2024
41699b2
Merge branch 'main' of github.com:langflow-ai/langflow into folders-u…
mfortman11 Oct 11, 2024
bdabedf
[autofix.ci] apply automated fixes
autofix-ci[bot] Oct 11, 2024
6c0e78f
Merge branch 'main' of github.com:langflow-ai/langflow into folders-u…
mfortman11 Oct 14, 2024
320893c
Merge branch 'main' of github.com:langflow-ai/langflow into folders-u…
mfortman11 Oct 14, 2024
7201cd3
Merge branch 'folders-uplift' of github.com:mfortman11/langflow into …
mfortman11 Oct 14, 2024
b041da7
design updates
mfortman11 Oct 15, 2024
5b610f0
Merge branch 'main' of github.com:langflow-ai/langflow into folders-u…
mfortman11 Oct 15, 2024
b25c985
[autofix.ci] apply automated fixes
autofix-ci[bot] Oct 15, 2024
2584ec7
Merge branch 'main' into folders-uplift
ogabrielluiz Oct 15, 2024
1670075
Merge branch 'main' of github.com:langflow-ai/langflow into folders-u…
mfortman11 Oct 17, 2024
6fee8a8
Merge branch 'folders-uplift' of github.com:mfortman11/langflow into …
mfortman11 Oct 17, 2024
1c59871
increase empty state width
mfortman11 Oct 17, 2024
3313eb7
[autofix.ci] apply automated fixes
autofix-ci[bot] Oct 17, 2024
97659e5
Merge branch 'main' into folders-uplift
mfortman11 Oct 18, 2024
66bacad
Merge branch 'main' into folders-uplift
mfortman11 Oct 18, 2024
7f49bc5
test fix
mfortman11 Oct 18, 2024
e95238c
Merge branch 'folders-uplift' of github.com:mfortman11/langflow into …
mfortman11 Oct 18, 2024
80200d7
Merge branch 'main' of github.com:langflow-ai/langflow into folders-u…
mfortman11 Oct 18, 2024
864d598
[autofix.ci] apply automated fixes
autofix-ci[bot] Oct 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import ShadTooltip from "@/components/shadTooltipComponent";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
} from "@/components/ui/select-custom";
import {
usePatchFolders,
usePostFolders,
Expand Down Expand Up @@ -129,6 +135,7 @@ const SideBarFoldersButtonsComponent = ({
link.download = `${data.folder_name}.json`;

link.click();
track("Folder Exported", { folderId: id! });
},
onError: () => {
setErrorData({
Expand Down Expand Up @@ -245,13 +252,13 @@ const SideBarFoldersButtonsComponent = ({
isDeletingFolder;

const HeaderButtons = () => (
<div className="flex shrink-0 items-center justify-between gap-2">
<div className="flex-1 self-start text-lg font-semibold">Folders</div>
<AddFolderButton onClick={addNewFolder} disabled={isUpdatingFolder} />
<div className="mt-4 flex shrink-0 items-center justify-between gap-2">
<div className="text-md flex-1 font-semibold">Folders</div>
<UploadFolderButton
onClick={handleUploadFlowsToFolder}
disabled={isUpdatingFolder}
/>
<AddFolderButton onClick={addNewFolder} disabled={isUpdatingFolder} />
</div>
);

Expand All @@ -260,12 +267,12 @@ const SideBarFoldersButtonsComponent = ({
<Button
variant="primary"
size="icon"
className="px-2"
className="border-0"
onClick={onClick}
data-testid="add-folder-button"
disabled={disabled}
>
<IconComponent name="FolderPlus" className="w-4" />
<IconComponent name="Plus" className="w-5" />
</Button>
</ShadTooltip>
);
Expand All @@ -275,7 +282,7 @@ const SideBarFoldersButtonsComponent = ({
<Button
variant="primary"
size="icon"
className="px-2"
className="border-0"
onClick={onClick}
data-testid="upload-folder-button"
disabled={disabled}
Expand All @@ -285,11 +292,30 @@ const SideBarFoldersButtonsComponent = ({
</ShadTooltip>
);

const FolderSelectItem = ({ name, iconName }) => (
<div
className={cn(
name === "Delete" ? "text-error" : "",
"flex items-center font-medium",
)}
>
<IconComponent name={iconName} className="mr-2 w-4" />
<span>{name}</span>
</div>
);

const handleDoubleClick = (event, item) => {
if (item.name === "My Projects") {
return;
}

event.stopPropagation();
event.preventDefault();

handleSelectFolderToRename(item);
};

const handleSelectFolderToRename = (item) => {
if (!foldersNames[item.name]) {
setFoldersNames({ [item.name]: item.name });
}
Expand All @@ -303,8 +329,6 @@ const SideBarFoldersButtonsComponent = ({
});
setEditFolderName(newEditFolders);
takeSnapshot();
event.stopPropagation();
event.preventDefault();
return;
}

Expand All @@ -314,8 +338,6 @@ const SideBarFoldersButtonsComponent = ({
[item.name]: item.name,
}));
takeSnapshot();
event.stopPropagation();
event.preventDefault();
};

const handleKeyDownFn = (e, item) => {
Expand All @@ -340,6 +362,20 @@ const SideBarFoldersButtonsComponent = ({
}
};

const handleSelectChange = (option, folder) => {
switch (option) {
case "delete":
handleDeleteFolder!(folder);
break;
case "download":
handleDownloadFolder(folder.id!);
break;
case "rename":
handleSelectFolderToRename(folder);
break;
}
};

return (
<>
<HeaderButtons />
Expand All @@ -362,7 +398,7 @@ const SideBarFoldersButtonsComponent = ({
className={cn(
buttonVariants({ variant: "ghost" }),
checkPathName(item.id!)
? "border border-border bg-muted hover:bg-muted"
? "bg-muted hover:bg-muted"
: "border hover:bg-transparent lg:border-transparent lg:hover:border-border",
"group flex w-full shrink-0 cursor-pointer gap-2 opacity-100 lg:min-w-full",
folderIdDragging === item.id! ? "bg-border" : "",
Expand All @@ -373,79 +409,104 @@ const SideBarFoldersButtonsComponent = ({
onDoubleClick={(event) => {
handleDoubleClick(event, item);
}}
className="flex w-full items-center gap-2"
className="flex w-full items-center justify-between"
>
<IconComponent
name={"folder"}
className="mr-2 w-4 flex-shrink-0 justify-start stroke-[1.5] opacity-100"
/>
{editFolderName?.edit && !isUpdatingFolder ? (
<div>
<Input
className="w-36"
onChange={(e) => {
handleEditFolderName(e, item.name);
}}
ref={refInput}
onKeyDown={(e) => {
handleKeyDownFn(e, item);
handleKeyDown(e, e.key, "");
}}
autoFocus={true}
onBlur={() => {
if (refInput.current?.value !== item.name) {
handleEditNameFolder(item);
} else {
editFolderName.edit = false;
}
refInput.current?.blur();
}}
value={foldersNames[item.name]}
id={`input-folder-${item.name}`}
data-testid={`input-folder`}
/>
</div>
) : (
<span className="block w-full truncate opacity-100">
{item.name}
</span>
)}
{index > 0 && (
<Button
data-testid="btn-delete-folder"
className="hidden p-0 hover:bg-primary group-hover:block"
onClick={(e) => {
handleDeleteFolder!(item);
e.stopPropagation();
e.preventDefault();
}}
variant={"ghost"}
size={"icon"}
disabled={isUpdatingFolder}
<div className="flex items-center gap-2">
<IconComponent
name={"folder"}
className="mr-2 w-4 flex-shrink-0 justify-start stroke-[1.5] opacity-100"
/>
{editFolderName?.edit && !isUpdatingFolder ? (
<div>
<Input
className="w-36"
onChange={(e) => {
handleEditFolderName(e, item.name);
}}
ref={refInput}
onKeyDown={(e) => {
handleKeyDownFn(e, item);
handleKeyDown(e, e.key, "");
}}
autoFocus={true}
onBlur={(e) => {
// fixes autofocus problem where cursor isn't present
if (
e.relatedTarget?.id ===
`options-trigger-${item.name}`
) {
refInput.current?.focus();
return;
}

if (refInput.current?.value !== item.name) {
handleEditNameFolder(item);
} else {
editFolderName.edit = false;
}
refInput.current?.blur();
}}
value={foldersNames[item.name]}
id={`input-folder-${item.name}`}
data-testid={`input-folder`}
/>
</div>
) : (
<span className="block w-full grow truncate opacity-100">
{item.name}
</span>
)}
</div>
<Select
onValueChange={(value) => handleSelectChange(value, item)}
value=""
>
<SelectTrigger
className="w-fit"
id={`options-trigger-${item.name}`}
data-testid="more-options-button"
>
<IconComponent
name={"trash"}
className="w-4 stroke-[1.5] p-0"
name={"MoreHorizontal"}
className="hidden w-4 stroke-[1.5] px-0 text-primary group-hover:block"
/>
</Button>
)}
<Button
className="hidden px-0 hover:bg-primary group-hover:block"
onClick={(e) => {
handleDownloadFolder(item.id!);
e.stopPropagation();
e.preventDefault();
track("Folder Exported", { folderId: item.id! });
}}
variant={"ghost"}
size={"icon"}
disabled={isUpdatingFolder}
>
<IconComponent
name={"Download"}
className="w-4 stroke-[1.5] text-primary"
/>
</Button>
</SelectTrigger>
<SelectContent
align="end"
alignOffset={-16}
position="popper"
>
{item.name !== "My Projects" && (
<SelectItem
id="rename-button"
value="rename"
data-testid="btn-rename-folder"
>
<FolderSelectItem
name="Rename"
iconName="square-pen"
/>
</SelectItem>
)}
<SelectItem
value="download"
data-testid="btn-download-folder"
>
<FolderSelectItem
name="Download Content"
iconName="download"
/>
</SelectItem>
{index > 0 && (
<SelectItem
value="delete"
data-testid="btn-delete-folder"
>
<FolderSelectItem name="Delete" iconName="trash" />
</SelectItem>
)}
</SelectContent>
</Select>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export default function HorizontalScrollFadeComponent({
}, [divWidth, children]); // Depend on divWidth

return isFolder ? (
<div className="hidden w-full flex-col gap-2 lg:flex">{children}</div>
<div className="flex w-full flex-col gap-2">{children}</div>
) : (
<div ref={fadeContainerRef} className="fade-container flex">
<div ref={scrollContainerRef} className="scroll-container flex gap-2">
Expand Down
34 changes: 18 additions & 16 deletions src/frontend/src/components/pageLayout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,27 @@ export default function PageLayout({
betaIcon?: boolean;
}) {
return (
<div className="flex h-full w-full flex-col justify-between overflow-auto bg-background px-16 pt-6">
<div className="flex flex-col gap-4">
<CustomBanner />
<div className="flex w-full items-center justify-between gap-4 space-y-0.5 py-2">
<div className="flex w-full flex-col">
<h2
className="text-2xl font-bold tracking-tight"
data-testid="mainpage_title"
>
{title}
{betaIcon && <span className="store-beta-icon">BETA</span>}
</h2>
<p className="text-muted-foreground">{description}</p>
<div className="flex h-full w-full flex-col justify-between overflow-auto bg-background px-6 pt-10">
<div className="mx-auto h-full w-full max-w-[1440px]">
<div className="flex flex-col gap-4">
<CustomBanner />
<div className="flex w-full items-center justify-between gap-4 space-y-0.5 py-2">
<div className="flex w-full flex-col">
<h2
className="text-2xl font-bold tracking-tight"
data-testid="mainpage_title"
>
{title}
{betaIcon && <span className="store-beta-icon">BETA</span>}
</h2>
<p className="text-muted-foreground">{description}</p>
</div>
<div className="flex-shrink-0">{button && button}</div>
</div>
<div className="flex-shrink-0">{button && button}</div>
</div>
<Separator className="my-6 flex" />
{children}
</div>
<Separator className="my-6 flex" />
{children}
</div>
);
}
Loading
Loading