Skip to content

Commit

Permalink
Flav/new conversation landing page (#2880)
Browse files Browse the repository at this point in the history
* Move GalleryItem to its own file

* Handle variant in GalleryItem

* Refactor new conversation landing page for member

* 🎨

* Refactor builder/admin conversation landing page

* Implement connections and folders as data sources

* ✨ Move AssistantPreview to components

* 📖

* ✨

* Use Link instead of Button.onClick() and use proper flow
  • Loading branch information
flvndvd authored Dec 14, 2023
1 parent 4b671c4 commit 21167bd
Show file tree
Hide file tree
Showing 3 changed files with 302 additions and 316 deletions.
158 changes: 158 additions & 0 deletions front/components/assistant/AssistantPreview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import { Avatar, Button, Chip, MoreIcon, PlusIcon } from "@dust-tt/sparkle";
import { AgentConfigurationType, WorkspaceType } from "@dust-tt/types";
import { useContext, useState } from "react";

import { SendNotificationsContext } from "@app/components/sparkle/Notification";
import { PostAgentListStatusRequestBody } from "@app/pages/api/w/[wId]/members/me/agent_list_status";

type AssistantPreviewVariant = "gallery" | "home";

interface AssistantPreviewProps {
owner: WorkspaceType;
agentConfiguration: AgentConfigurationType;
onShowDetails: () => void;
onUpdate: () => void;
variant: AssistantPreviewVariant;
}

function getDescriptionClassName(variant: AssistantPreviewVariant): string {
switch (variant) {
case "home":
return "text-xs text-element-700";
default:
return "text-sm text-element-800";
}
}

function getNameClassName(variant: AssistantPreviewVariant): string {
switch (variant) {
case "home":
return "text-sm font-medium text-element-900";
default:
return "text-md font-medium text-element-900";
}
}

export function AssistantPreview({
owner,
agentConfiguration,
onShowDetails,
onUpdate,
variant,
}: AssistantPreviewProps) {
const [isAdding, setIsAdding] = useState<boolean>(false);
// TODO(flav) Move notification logic to the caller. This maintains the purity of the component by decoupling it from side-effect operations.
const sendNotification = useContext(SendNotificationsContext);

const addToAgentList = async () => {
setIsAdding(true);

try {
const body: PostAgentListStatusRequestBody = {
agentId: agentConfiguration.sId,
listStatus: "in-list",
};

const response = await fetch(
`/api/w/${owner.sId}/members/me/agent_list_status`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
}
);

if (!response.ok) {
const data = await response.json();
sendNotification({
title: `Error adding Assistant`,
description: data.error.message,
type: "error",
});
} else {
sendNotification({
title: `Assistant added`,
type: "success",
});
onUpdate();
}
} catch (error) {
sendNotification({
title: `Error adding Assistant`,
description: error instanceof Error ? error.message : String(error),
type: "error",
});
} finally {
setIsAdding(false);
}
};

const addButton = agentConfiguration.userListStatus !== "in-list" && (
<Button
variant="tertiary"
icon={PlusIcon}
disabled={isAdding}
size="xs"
label={"Add"}
onClick={addToAgentList}
/>
);

const showAssistantButton = (
<Button
icon={MoreIcon}
label={"Show Assistant"}
labelVisible={false}
size="xs"
variant="tertiary"
onClick={onShowDetails}
/>
);

const defaultButtons = [
showAssistantButton,
// <Button
// variant="tertiary"
// icon={PlayIcon}
// size="xs"
// label={"Test"}
// onClick={() => {
// // TODO: test
// }}
// />,
];

// Define button groups with JSX elements, including default buttons
const buttonGroups: Record<AssistantPreviewVariant, JSX.Element[]> = {
gallery: [addButton, showAssistantButton].filter(Boolean) as JSX.Element[],
home: defaultButtons,
};

const buttonsToRender = buttonGroups[variant] || [];

return (
<div className="flex flex-row gap-2">
<Avatar
visual={<img src={agentConfiguration.pictureUrl} alt="Agent Avatar" />}
size="md"
/>
<div className="flex flex-col gap-2">
<div className={getNameClassName(variant)}>
@{agentConfiguration.name}
</div>
<div className="flex flex-row gap-2">
{agentConfiguration.userListStatus === "in-list" &&
variant === "gallery" && (
<Chip color="emerald" size="xs" label="Added" />
)}
<Button.List isWrapping={true}>{buttonsToRender}</Button.List>
</div>
<div className={getDescriptionClassName(variant)}>
{agentConfiguration.description}
</div>
</div>
</div>
);
}
125 changes: 5 additions & 120 deletions front/pages/w/[wId]/assistant/gallery.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
import {
Avatar,
Button,
Chip,
MoreIcon,
Page,
PlusIcon,
Searchbar,
Tab,
} from "@dust-tt/sparkle";
import { Page, Searchbar, Tab } from "@dust-tt/sparkle";
import {
AgentConfigurationType,
AgentsGetViewType,
Expand All @@ -18,17 +9,16 @@ import {
} from "@dust-tt/types";
import { GetServerSideProps, InferGetServerSidePropsType } from "next";
import { useRouter } from "next/router";
import { useContext, useState } from "react";
import { useState } from "react";

import { AssistantDetails } from "@app/components/assistant/AssistantDetails";
import { AssistantPreview } from "@app/components/assistant/AssistantPreview";
import AppLayout from "@app/components/sparkle/AppLayout";
import { AppLayoutSimpleCloseTitle } from "@app/components/sparkle/AppLayoutTitle";
import { subNavigationConversations } from "@app/components/sparkle/navigation";
import { SendNotificationsContext } from "@app/components/sparkle/Notification";
import { Authenticator, getSession, getUserFromSession } from "@app/lib/auth";
import { useAgentConfigurations } from "@app/lib/swr";
import { subFilter } from "@app/lib/utils";
import { PostAgentListStatusRequestBody } from "@app/pages/api/w/[wId]/members/me/agent_list_status";

const { GA_TRACKING_ID = "" } = process.env;

Expand Down Expand Up @@ -86,112 +76,6 @@ export const getServerSideProps: GetServerSideProps<{
};
};

const GalleryItem = function ({
owner,
agentConfiguration,
onShowDetails,
onUpdate,
}: {
owner: WorkspaceType;
agentConfiguration: AgentConfigurationType;
onShowDetails: () => void;
onUpdate: () => void;
}) {
const [isAdding, setIsAdding] = useState<boolean>(false);
const sendNotification = useContext(SendNotificationsContext);

return (
<div className="flex flex-row gap-2">
<Avatar
visual={<img src={agentConfiguration.pictureUrl} alt="Agent Avatar" />}
size="md"
/>
<div className="flex flex-col gap-2">
<div className="text-md font-medium text-element-900">
@{agentConfiguration.name}
</div>
<div className="flex flex-row gap-2">
{agentConfiguration.userListStatus === "in-list" && (
<Chip color="emerald" size="xs" label="Added" />
)}
<Button.List isWrapping={true}>
{agentConfiguration.userListStatus !== "in-list" && (
<>
<Button
variant="tertiary"
icon={PlusIcon}
disabled={isAdding}
size="xs"
label={"Add"}
onClick={async () => {
setIsAdding(true);

const body: PostAgentListStatusRequestBody = {
agentId: agentConfiguration.sId,
listStatus: "in-list",
};

const res = await fetch(
`/api/w/${owner.sId}/members/me/agent_list_status`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
}
);
if (!res.ok) {
const data = await res.json();
sendNotification({
title: `Error adding Assistant`,
description: data.error.message,
type: "error",
});
} else {
sendNotification({
title: `Assistant added`,
type: "success",
});
onUpdate();
}

setIsAdding(false);
}}
/>
{/*
<Button
variant="tertiary"
icon={PlayIcon}
size="xs"
label={"Test"}
onClick={() => {
// TODO: test
}}
/>
*/}
</>
)}
<Button
variant="tertiary"
icon={MoreIcon}
size="xs"
label={"Show Assistant"}
labelVisible={false}
onClick={() => {
onShowDetails();
}}
/>
</Button.List>
</div>
<div className="text-sm text-element-800">
{agentConfiguration.description}
</div>
</div>
</div>
);
};

export default function AssistantsGallery({
user,
owner,
Expand Down Expand Up @@ -302,7 +186,7 @@ export default function AssistantsGallery({
<div className="flex flex-col gap-2">
<div className="grid grid-cols-2 gap-8 sm:grid-cols-2">
{filtered.map((a) => (
<GalleryItem
<AssistantPreview
key={a.sId}
owner={owner}
agentConfiguration={a}
Expand All @@ -312,6 +196,7 @@ export default function AssistantsGallery({
onUpdate={() => {
void mutateAgentConfigurations();
}}
variant="gallery"
/>
))}
</div>
Expand Down
Loading

0 comments on commit 21167bd

Please sign in to comment.