Skip to content

Commit

Permalink
feat(ui): Add agent ui improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
TonyRamirezLecca committed Dec 29, 2024
1 parent 2854b8d commit 7f8ecab
Show file tree
Hide file tree
Showing 14 changed files with 153 additions and 76 deletions.
8 changes: 8 additions & 0 deletions packages/ui/public/icons/discord.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions packages/ui/public/icons/github.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/ui/public/icons/lecca-digital.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 changes: 48 additions & 1 deletion packages/ui/src/components/layouts/application-side-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,51 @@ export function AdditionalSideNavContent({
title: 'Docs',
to: 'https://lecca.io/docs/overview',
newTab: true,
icon: Icons.infoCircle,
icon: (props: any) => (
<img
src="/icons/lecca-digital.png"
alt="Lecca Digital"
style={{
backgroundColor: 'white',
borderRadius: '50%',
padding: '.5px',
}}
{...props}
/>
),
},
{
title: 'Discord',
to: 'https://discord.gg/86wrJnN7',
newTab: true,
icon: (props: any) => (
<img
src="/icons/discord.svg"
className="size-4"
alt="Discord"
{...props}
/>
),
},
{
title: 'Github',
to: 'https://github.com/lecca-digital/lecca-io',
newTab: true,
icon: (props: any) => (
<div>
<img
src="/icons/github.svg"
className="size-4"
style={{
backgroundColor: 'white',
borderRadius: '50%',
padding: '.5px',
}}
alt="Github"
{...props}
/>
</div>
),
},
{
title: 'Settings',
Expand Down Expand Up @@ -517,6 +561,9 @@ export function Nav({ links, isCollapsed, isSheet, className }: NavProps) {
{link.dropdownMenuContent}
</DropdownMenu>
)}
{link.newTab && (
<Icons.externalLink className="absolute right-0 top-0 h-4 w-4 mr-2 mt-2" />
)}
</Link>
);

Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/ui/avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const AvatarFallback = React.forwardRef<
<AvatarPrimitive.Fallback
ref={ref}
className={cn(
`flex h-full w-full items-center justify-center rounded-full text-xs cursor-default bg-muted`,
`flex h-full w-full items-center justify-center rounded-full text-xs bg-muted`,
className,
)}
{...props}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Link } from 'react-router-dom';

import { Icons } from '../../../../components/icons';
import { MarkdownViewer } from '../../../../components/markdown-viewer';
import { Avatar } from '../../../../components/ui/avatar';
import { Agent } from '../../../../models/agent/agent-model';

import { MessageCardWrapper } from './message-card-wrapper';
Expand All @@ -25,9 +26,21 @@ export const MessageAgentCard = ({
<MessageCardWrapper text={textContent} createdAt={createdAt}>
<Link to={`/redirect?redirect=/agents/${agent.id}`}>
<div className="flex items-center space-x-2">
<div className="border rounded-md p-1.5 mr-1">
<Icons.messageAgent className="size-5" />
</div>
{agent.profileImageUrl ? (
<Avatar className="size-9 border mr-1">
<Avatar.Image
src={agent.profileImageUrl ?? undefined}
alt="Agent icon url"
/>
<Avatar.Fallback className="text-lg">
{agent.name![0].toUpperCase()}
</Avatar.Fallback>
</Avatar>
) : (
<div className="border rounded-md p-1.5 mr-1">
<Icons.messageAgent className="size-5" />
</div>
)}
<div className="flex items-center space-x-1.5 text-sm">
<span className="font-medium">{agent.name}</span>
{status === 'loading' && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,17 @@ export const MessageUserCard = ({
);
} else if (agentAsMessageUser) {
name = agentAsMessageUser.name;
icon = (
icon = agentAsMessageUser.profileImageUrl ? (
<Avatar className="size-9 border mr-1">
<Avatar.Image
src={agentAsMessageUser.profileImageUrl ?? undefined}
alt="Agent icon url"
/>
<Avatar.Fallback className="text-lg">
{agentAsMessageUser.name![0].toUpperCase()}
</Avatar.Fallback>
</Avatar>
) : (
<div className="border rounded-md p-1.5 mr-1">
<Icons.messageAgent className="size-5" />
</div>
Expand Down
107 changes: 49 additions & 58 deletions packages/ui/src/pages/agents/components/table/agents-table-columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Avatar } from '../../../../components/ui/avatar';
import { Dialog } from '../../../../components/ui/dialog';
import { Popover } from '../../../../components/ui/popover';
import { Agent } from '../../../../models/agent/agent-model';
import { WorkflowApp } from '../../../../models/workflow/workflow-app-model';
import { toLocaleDateStringOrUndefined } from '../../../../utils/dates';
import { AppOverviewContent } from '../../../apps/components/app-overview-content';

Expand All @@ -19,30 +20,37 @@ export const columns: ColumnDef<Agent>[] = [
id: 'Name',
accessorFn: (row) => row.name,
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Name" />
<DataTableColumnHeader column={column} title="Name" className="pl-10" />
),
cell: ({ getValue, row }) => {
const description = row.original.description;
const agent = row.original;

return (
<div className="flex items-center space-x-4">
<Link
to={`/projects/${row.original.project?.id}/agents/${row.original.id}`}
>
<Link to={`/projects/${agent.project?.id}/agents/${agent.id}`}>
<div className="flex space-x-2 text-blue-400 hover:underline">
<span className="max-w-[500px] truncate ">
{getValue() as string}
</span>
<div className="flex items-center space-x-4 max-w-[500px]">
<Avatar className="size-8 border">
<Avatar.Image
src={agent.profileImageUrl ?? undefined}
alt="Agent icon url"
/>
<Avatar.Fallback className="text-muted-foreground">
<Icons.agent className="size-5" />
</Avatar.Fallback>
</Avatar>
<span className="truncate">{getValue() as string}</span>
</div>
</div>
</Link>
{description && (
{agent.description && (
<Popover>
<Popover.Trigger>
<Icons.infoCircle className="w-4 h-4 text-muted-foreground hover:text-primary" />
</Popover.Trigger>
<Popover.Content>
<div className="p-4 text-sm">
<p>{description}</p>
<p>{agent.description}</p>
</div>
</Popover.Content>
</Popover>
Expand All @@ -52,58 +60,55 @@ export const columns: ColumnDef<Agent>[] = [
},
},
{
id: 'Apps',
id: 'Tools',
accessorFn: (row) => row.connections,
enableSorting: false,
header: ({ column }) => (
<DataTableColumnHeader column={column} title="" className="border-r" />
<DataTableColumnHeader
column={column}
title="Tools"
className="border-r"
/>
),
cell: ({ getValue }) => {
cell: ({ row }) => {
const agent = row.original;
// eslint-disable-next-line react-hooks/rules-of-hooks
const { data: apps, isLoading: isLoadingApps } = useApiQuery({
service: 'workflowApps',
method: 'getList',
apiLibraryArgs: {},
});

const { data: connections, isLoading: isLoadingConnections } =
// eslint-disable-next-line react-hooks/rules-of-hooks
useApiQuery({
service: 'connections',
method: 'getList',
apiLibraryArgs: {
config: {
params: {
includeType: ['all'],
},
},
},
});

const agentConnections = getValue() as Agent['connections'];

// eslint-disable-next-line react-hooks/rules-of-hooks
const workflowApps = useMemo(() => {
const fullAgentConnections = connections?.filter((connection) =>
agentConnections?.some(
(agentConnection) => agentConnection.id === connection.id,
),
);
const mappedApps = useMemo(() => {
if (!apps) {
return {};
}

return fullAgentConnections?.map((connection) => {
const app = apps?.find((app) => app.id === connection.workflowAppId);
return app;
});
}, [agentConnections, apps, connections]);
return apps.reduce(
(acc, app) => {
acc[app.id] = app;
return acc;
},
{} as { [key: string]: WorkflowApp },
);
}, [apps]);

if (isLoadingApps || isLoadingConnections || !workflowApps) {
if (isLoadingApps) {
return null;
}

return (
<Avatar.Group limit={3} className="items-center mr-4">
<Avatar.GroupList>
{workflowApps!.map((app, index) => {
{agent.toolIds!.map((toolId, index) => {
const appId = toolId.split('_action_')[0];

const app = mappedApps[appId];
const action = app?.actions.find((a) => a.id === toolId);

const imgUrl = action?.iconUrl ?? app?.logoUrl;

return (
<Avatar
key={app!.id + index}
Expand All @@ -112,7 +117,7 @@ export const columns: ColumnDef<Agent>[] = [
<Dialog>
<Dialog.Trigger asChild>
<Avatar.Image
src={app!.logoUrl ?? undefined}
src={imgUrl}
className="rounded-none object-contain size-5"
/>
</Dialog.Trigger>
Expand All @@ -124,21 +129,7 @@ export const columns: ColumnDef<Agent>[] = [
);
})}
</Avatar.GroupList>
<Popover>
<Popover.Trigger asChild>
<Avatar.OverflowIndicator className="border cursor-pointer object-contain size-9" />
</Popover.Trigger>
<Popover.Content>
<div className="p-4 text-sm">
<p>
{workflowApps
.slice(3)!
.map((app) => app!.name)
.join(', ')}
</p>
</div>
</Popover.Content>
</Popover>
<Avatar.OverflowIndicator className="border cursor-pointer object-contain size-9" />
</Avatar.Group>
);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ export function HomeSectionAgents() {
<div key={agent.id}>
<Link
to={`/agents/${agent.id}`}
className="flex flex-col items-center rounded-full hover:brightness-125"
className="flex flex-col items-center rounded-full cursor-pointer group"
>
<Avatar className="size-16 border">
<Avatar className="size-16 border group-hover:border-primary">
<Avatar.Image
src={agent.profileImageUrl ?? undefined}
alt="Agent icon url"
/>
<Avatar.Fallback className="text-lg">
<Avatar.Fallback className="text-lg text-muted-foreground group-hover:text-primary">
{agent.name![0].toUpperCase()}
</Avatar.Fallback>
</Avatar>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function TemplateCarousel() {
return (
templates?.length &&
apps && (
<div className="flex max-w-full gap-6 overflow-x-auto py-2">
<div className="flex max-w-full gap-6 overflow-x-auto overflow-y-hidden py-2">
{templates.map((template) => (
<WorkflowTemplateCard
apps={apps}
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/pages/home/home-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export default function HomePage() {
<HomeSectionNoAgentOrWorkflow />
</HomeSection>

<HomeSection className="gap-10 flex flex-col 3xl:flex-row overflow-x-auto">
<HomeSection className="gap-10 flex flex-col 4xl:flex-row overflow-x-hidden">
<HomeSectionRecentTasks />
<HomeSectionRecentExecutions />
</HomeSection>
Expand Down
2 changes: 0 additions & 2 deletions packages/ui/src/providers/application-side-nav-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ export const ApplicationSideNavProvider = ({
const resize = () => {
if (window.innerWidth < 1280) {
setIsCollapsed(true);
} else {
setIsCollapsed(false);
}
};
window.addEventListener('resize', resize);
Expand Down
15 changes: 10 additions & 5 deletions packages/ui/src/tailwind/tailwind.output.css
Original file line number Diff line number Diff line change
Expand Up @@ -4073,11 +4073,6 @@ body {
--tw-ring-offset-width: 2px;
}

.hover\:brightness-125:hover {
--tw-brightness: brightness(1.25);
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}

.hover\:before\:translate-x-\[0\%\]:hover::before {
content: var(--tw-content);
--tw-translate-x: 0%;
Expand Down Expand Up @@ -4256,6 +4251,10 @@ body {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

.group:hover .group-hover\:border-primary {
border-color: hsl(var(--primary));
}

.group:hover .group-hover\:bg-muted {
background-color: hsl(var(--muted));
}
Expand Down Expand Up @@ -5125,6 +5124,12 @@ body {
}
}

@media (min-width: 1920px) {
.\34xl\:flex-row {
flex-direction: row;
}
}

.\[\&\+div\]\:text-xs+div {
font-size: 0.75rem;
line-height: 1rem;
Expand Down
Loading

0 comments on commit 7f8ecab

Please sign in to comment.