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: update agent hub navigation and filtering #321

Merged
merged 9 commits into from
Nov 17, 2024
24 changes: 7 additions & 17 deletions agenthub/app/agents/ContentLayout/DatasetsHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,18 @@

import { FilterSVG, SortSVG } from '@/ui/svgs'
import { Input } from '@nextui-org/react'
import { AgentListGenerator } from '../const';
import { useState } from 'react'

import { useState, useEffect } from 'react'
interface DatasetsHeaderProps {
filteredCount?: number;
}

export function DatasetsHeader() {
useEffect(() => {
const _ = async () => {
const AgentList = await AgentListGenerator();
setAgentNumber(AgentList.length);
}

_();

}, []);

const [agentNumber, setAgentNumber] = useState(0);

export function DatasetsHeader({ filteredCount = 0 }: DatasetsHeaderProps) {
return (
<div className="mb-4 items-center space-y-3 md:flex md:space-y-0 lg:mb-6">
<div className="flex items-center text-lg">
<h1>Agents</h1>
<div className="ml-3 w-16 font-normal text-gray-400">{agentNumber}</div>
<div className="ml-3 w-16 font-normal text-gray-400">{filteredCount}</div>
</div>
<div className="flex-1 md:mx-4 opacity-0">
<div className="relative w-full md:max-w-xs">
Expand All @@ -44,7 +34,7 @@ export function DatasetsHeader() {
<div className="relative inline-block">
<button className=" btn w-full cursor-pointer text-sm" type="button">
<SortSVG />
Sort:  Trending
Sort: Trending
</button>
</div>
</div>
Expand Down
144 changes: 81 additions & 63 deletions agenthub/app/agents/TabsLayout/index.client.tsx
Original file line number Diff line number Diff line change
@@ -1,77 +1,95 @@
'use client'

import { useState } from 'react'
import { useState, useEffect } from 'react'
import classNames from 'classnames'

import { DatasetsTabList } from '../const'
import { DatasetsTabItem } from '../type'

import FilterTab from './FilterTab'
import TabTasks from './TabTasks'
import TabOther from './TabOther'
import TabLicenses from './TabLicenses'
import TabLanguages from './TabLanguages'
import TabSubTasks from './TabSubTasks'
import TabSizes from './TabSizes'
import { ApplySVG, ExitSVG } from '@/ui/svgs'
import { AgentTabList } from '../const'
import { DatasetsTabItem, AgentItem } from '../type'
import { ExitSVG } from '@/ui/svgs'
import { baseUrl } from '@/lib/env'
import AgentCard from '../ContentLayout/AgentCard'
import { DatasetsHeader } from '../ContentLayout/DatasetsHeader'

export default function LeftTabsLayout() {
const [currentTab, setCurrentTab] = useState<DatasetsTabItem>('Tasks')
//linter
// const [isAddFilterModalDisplay, setIsAddFilterModalDisplay] = useState<boolean>(false)
const [currentTab, setCurrentTab] = useState<DatasetsTabItem>('Academic')
const [agents, setAgents] = useState<AgentItem[]>([])
const isAddFilterModalDisplay = false;

useEffect(() => {
const fetchAgents = async () => {
const res = await fetch(`${baseUrl}/api/get_all_agents/light`, { cache: 'no-store' });
const data = await res.json();
setAgents(Object.values(data));
};

fetchAgents();
}, []);

const onTabClick = (tabName: DatasetsTabItem) => {
setCurrentTab(tabName)
}

// Filter agents based on current selected category
const filteredAgents = agents.filter(agent => {
const name = agent.name.toLowerCase();
switch(currentTab) {
case 'Academic':
return name.includes('academic') || name.includes('math');
case 'Creative':
return name.includes('creator') || name.includes('designer') || name.includes('composer');
case 'Lifestyle':
return name.includes('therapist') || name.includes('trainer') || name.includes('mixologist');
case 'Entertainment':
return name.includes('entertainment') || name.includes('game');
default:
return true;
}
});

return (
<section
className={classNames(
'pt-8 border-gray-100 bg-white lg:static lg:px-0 lg:col-span-4 xl:col-span-3 lg:border-r lg:bg-gradient-to-l from-gray-50-to-white',
isAddFilterModalDisplay ? 'fixed overflow-y-auto overflow-x-hidden z-40 inset-0 !px-4 !pt-4' : 'hidden lg:block'
)}
>
<div className="mb-4 flex items-center justify-between lg:hidden">
<h3 className="text-base font-semibold">Edit Datasets filters</h3>
<button className="text-xl" type="button">
<ExitSVG />
</button>
</div>
<ul className="flex gap-1 text-sm flex-wrap mt-1.5 mb-5">
{DatasetsTabList.map((tabName, index) => (
<li key={index}>
<button
className={classNames(
'flex items-center whitespace-nowrap rounded-lg px-2',
currentTab === tabName
? 'bg-black text-white dark:bg-gray-800'
: 'text-gray-500 hover:bg-gray-100 hover:text-gray-700 dark:hover:bg-gray-900 dark:hover:text-gray-300'
)}
onClick={() => {
onTabClick(tabName)
}}
>
{tabName}
</button>
</li>
))}
</ul>
<FilterTab />
<div className="mb-3">
{currentTab === 'Tasks' && <TabTasks />}
{currentTab === 'Sizes' && <TabSizes />}
{currentTab === 'Sub-tasks' && <TabSubTasks />}
{currentTab === 'Languages' && <TabLanguages />}
{currentTab === 'Licenses' && <TabLicenses />}
{currentTab === 'Other' && <TabOther />}
</div>
<div className="fixed inset-x-4 bottom-0 flex h-16 items-center border-t bg-white dark:bg-gray-950 lg:hidden">
<button className="btn btn-lg -mt-px w-full font-semibold" type="button">
<ApplySVG />
Apply filters
</button>
</div>
</section>
<>
<section
className={classNames(
'pt-8 border-gray-100 bg-white lg:static lg:px-0 lg:col-span-4 xl:col-span-3 lg:border-r lg:bg-gradient-to-l from-gray-50-to-white',
isAddFilterModalDisplay ? 'fixed overflow-y-auto overflow-x-hidden z-40 inset-0 !px-4 !pt-4' : ''
)}
>
{/* Left sidebar category menu */}
<div className="mb-4 flex items-center justify-between lg:hidden">
<h3 className="text-base font-semibold">Agent Categories</h3>
<button className="text-xl" type="button">
<ExitSVG />
</button>
</div>
<ul className="flex gap-1 text-sm flex-wrap mt-1.5 mb-5">
{AgentTabList.map((tabName, index) => (
<li key={index}>
<button
className={classNames(
'flex items-center whitespace-nowrap rounded-lg px-3 py-1.5',
currentTab === tabName
? 'bg-black text-white dark:bg-gray-800'
: 'text-gray-500 hover:bg-gray-100 hover:text-gray-700 dark:hover:bg-gray-900 dark:hover:text-gray-300'
)}
onClick={() => {
onTabClick(tabName)
}}
>
{tabName}
</button>
</li>
))}
</ul>
</section>

{/* Main content section with filtered agents */}
<section className="pt-8 col-span-full lg:col-span-6 xl:col-span-7 pb-12">
<DatasetsHeader filteredCount={filteredAgents.length} />
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3">
{filteredAgents.map((agent) => (
<AgentCard key={agent.id} item={agent} />
))}
</div>
</section>
</>
)
}
27 changes: 21 additions & 6 deletions agenthub/app/agents/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,33 @@ export const AgentList: AgentItem[] = [];
// export const AgentList =

export const AgentListGenerator: () => Promise<AgentItem[]> = async () => {
const res = await fetch(`${baseUrl}/api/get_all_agents/light`, { cache: 'no-store' });
const res_ = await res.json();
try {
const res = await fetch(`${baseUrl}/api/get_all_agents/light`, { cache: 'no-store' });
const res_ = await res.json();

const values: AgentItem[] = Object.values(res_);
if (!res_ || typeof res_ !== 'object') {
console.error('Invalid response format:', res_);
return [];
}

console.log('length', res_)
const values: AgentItem[] = Object.values(res_);
console.log('Response data:', res_);
console.log('Parsed values:', values);

return values;
return values;
} catch (error) {
console.error('Error fetching agents:', error);
return [];
}
}

// export const DatasetsTabList: DatasetsTabItem[] = ['Tasks', 'Sizes', 'Sub-tasks', 'Languages', 'Licenses', 'Other']
export const AgentTabList: DatasetsTabItem[] = ['Recommended', 'Writing', 'Entertainment', 'Programming']
export const AgentTabList: DatasetsTabItem[] = [
'Academic',
'Creative',
'Lifestyle',
'Entertainment'
]

export const DatasetOther = [
'Trained with AutoTrain',
Expand Down
17 changes: 6 additions & 11 deletions agenthub/app/agents/page.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
import TabsLayout from './TabsLayout/index.client'
import ContentLayout from './ContentLayout'
import LeftTabsLayout from './TabsLayout/index.client'

export default function Datasets({ searchParams }:
{ searchParams: { [key: string]: string | string[] | undefined } }) {
export default function Datasets() {
return (
<main className="flex flex-1 flex-col">
<div className="SVELTE_HYDRATER contents" data-props="" data-target="DatasetList">
<div className="container relative flex flex-col lg:grid lg:space-y-0 w-full lg:grid-cols-10 md:flex-1 md:grid-rows-full md:gap-6 ">
<TabsLayout />
<ContentLayout searchParams={searchParams} />
</div>
<div className="flex min-h-[calc(100vh_-_64px)]">
<div className="container relative flex flex-col lg:grid lg:space-y-0 w-full lg:grid-cols-10 md:flex-1 md:grid-rows-full md:gap-6">
<LeftTabsLayout />
</div>
</main>
</div>
)
}
4 changes: 2 additions & 2 deletions agenthub/app/agents/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ export interface DatasetItem {
favorites: string
}

export type DatasetsTabItem = 'Recommended' | 'Writing' | 'Entertainment' | 'Programming' | 'Tasks' | 'Sizes' | 'Sub-tasks' | 'Languages' | 'Licenses' | 'Other';
export type DatasetsTabItem = 'Recommended' | 'Writing' | 'Entertainment' | 'Programming' | 'Tasks' | 'Sizes' | 'Sub-tasks' | 'Languages' | 'Licenses' | 'Other' | 'Academic' | 'Creative' | 'Lifestyle' | 'Entertainment';

export type AgentTabItem = 'Tasks' | 'Sizes' | 'Sub-tasks' | 'Languages' | 'Licenses' | 'Other'
export type AgentTabItem = 'Tasks' | 'Sizes' | 'Sub-tasks' | 'Languages' | 'Licenses' | 'Other' | 'Academic' | 'Creative' | 'Lifestyle' | 'Entertainment';


export interface AgentItem {
Expand Down
2 changes: 1 addition & 1 deletion agenthub/components/homepage/Products.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const Examples = [
author_url: 'https://github.com/vercel',
author_img: 'https://avatars.githubusercontent.com/u/14985020',
repo_name: 'vercel/nextjs-subscription-payments',
repo_url: 'https://my.aios.foundation/agents',
repo_url: 'http://localhost:3000/agents',
vercel_deploy_url:
'https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fnextjs-subscription-payments&env=NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY,STRIPE_SECRET_KEY&envDescription=Enter%20your%20Stripe%20API%20keys.&envLink=https%3A%2F%2Fdashboard.stripe.com%2Fapikeys&project-name=nextjs-subscription-payments&repository-name=nextjs-subscription-payments&integration-ids=oac_VqOgBHqhEoFTPzGkPd7L0iH6&external-id=https%3A%2F%2Fgithub.com%2Fvercel%2Fnextjs-subscription-payments%2Ftree%2Fmain',
demo_url: 'https://subscription-payments.vercel.app/',
Expand Down
8 changes: 6 additions & 2 deletions agenthub/lib/env.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
export const inDevEnvironment = !!process && process.env.NODE_ENV === 'development';
// export const serverUrl = inDevEnvironment ? 'http://localhost:8000' : 'https://myapp-y5z35kuonq-uk.a.run.app'
export const baseUrl = inDevEnvironment ? 'http://localhost:3000' : 'https://my.aios.foundation'
export const baseUrl = process.env.NODE_ENV === 'development'
? 'http://localhost:3000'
: 'https://my.aios.foundation';
// export const serverUrl = inDevEnvironment ? 'http://localhost:8000' : 'http://35.232.56.61:8000'
export const serverUrl = 'http://35.232.56.61:8000';
export const serverUrl = process.env.NODE_ENV === 'development'
? 'http://localhost:8000'
: 'https://api.aios.chat';