smolagents-and-tools / index.html
davidberenstein1957's picture
Restore agents filter button and update search filter logic
7350e8f
raw
history blame
11.4 kB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Smolagents and tools gallery</title>
<meta name="description" content="Discover all smolagents and tools created by the community." />
<meta property="og:url" content="https://smolagents-tools-gallery.hf.space/" />
<meta property="og:type" content="website" />
<meta property="og:title" content="smolagents and tools gallery" />
<meta property="og:description" content="Discover all smolagents and tools created by the community." />
<meta property="og:image" content="https://huggingface-projects-diffusers-gallery.hf.space/Fo6vR6JX0AEjbw1.jpeg" />
<meta name="twitter:card" content="player" />
<meta property="twitter:url" content="https://davidberenstein1957-smolagents-and-tools.static.hf.space" />
<meta name="twitter:description" content="Discover all smolagents and tools created by the community." />
<meta name="twitter:site" content="@huggingface" />
<meta name="twitter:title" content="smolagents and tools gallery" />
<meta name="twitter:image" content="https://huggingface-projects-diffusers-gallery.hf.space/Fo6vR6JX0AEjbw1.jpeg" />
<meta name="twitter:player" content="https://davidberenstein1957-smolagents-and-tools.static.hf.space" />
<meta name="twitter:player:width" content="100%" />
<meta name="twitter:player:height" content="600" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.1/iframeResizer.contentWindow.min.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<style>
iframe {
display: block;
border: none;
width: 100%;
height: 600px;
pointer-events: none;
margin-top: 48px; /* Match header height */
}
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
grid-gap: 10px;
margin-top: 3.5rem;
}
.grid-item {
position: relative;
overflow-y: hidden;
border-radius: 10px;
border: 1px solid rgb(55 65 81);
}
.grid-item:hover {
filter: brightness(75%);
}
.grid-item a {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: block;
z-index: 1;
}
.grid-item-header {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 48px;
background: rgba(0,0,0,0.75);
padding: 8px 16px;
z-index: 10;
display: flex;
align-items: center;
width: 100%;
}
.grid-item-header h2 {
width: 100%;
overflow-wrap: break-word;
word-wrap: break-word;
hyphens: auto;
max-height: 32px;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
line-height: 1.2;
}
</style>
<script type="module">
import Alpine from "https://cdn.skypack.dev/[email protected]";
import Intersect from "https://cdn.skypack.dev/@alpinejs/intersect";
Alpine.plugin(Intersect);
Alpine.data("themesData", () => ({
async init() {
const data = await this.getThemes(this.page, this.sort, this.useTestData);
this.themes = data.themes;
this.totalPages = data.totalPages;
},
themes: [],
filter: "tool",
sort: "likes",
page: 1,
totalPages: -1,
useTestData: false,
searchQuery: "",
searchType: "keyword",
buttonClass(attr, filter) {
if (this[attr] === filter) {
return "text-orange-600 bg-gradient-to-br from-orange-300 to-orange-100 px-2 md:px-3 py-1 rounded-full";
}
return "text-gray-800 hover:to-orange-300/100 hover:text-orange-600 dark:hover:bg-white";
},
async switchData() {
this.page = 1;
this.useTestData = !this.useTestData;
const data = await this.getThemes(this.page, this.sort, this.useTestData);
this.themes = data.themes;
this.totalPages = data.totalPages;
},
async sortThemes(sort) {
this.sort = sort;
this.page = 1;
const data = await this.getThemes(this.page, this.sort, this.useTestData);
this.themes = data.themes;
this.totalPages = data.totalPages;
},
async filterType(filter) {
this.filter = filter;
this.page = 1;
if (this.searchQuery) {
await this.searchThemes();
} else {
const data = await this.getThemes(this.page, this.sort, this.useTestData);
this.themes = data.themes;
this.totalPages = data.totalPages;
}
},
async searchThemes() {
this.page = 1;
const data = await this.getThemes(this.page, this.sort, this.useTestData);
this.themes = data.themes;
this.totalPages = data.totalPages;
},
async switchSearchType(type) {
this.searchType = type;
if (this.searchQuery) {
await this.searchThemes();
}
},
async getThemes(page, sort, useTestData) {
let data;
if (useTestData) {
const res = await fetch(
`https://huggingface.co/datasets/freddyaboulton/gradio-theme-subdomains/resolve/main/test_data.json`
);
data = await res.json();
} else {
const searchFilters = this.filter === 'tool' ? 'tool' : 'smolagents';
let searchUrl;
if (this.searchQuery) {
if (this.searchType === 'semantic') {
searchUrl = `https://huggingface.co/api/spaces/semantic-search?limit=100&filter=${searchFilters}&q=${encodeURIComponent(this.searchQuery)}&expand[]=subdomain&expand[]=lastModified&expand[]=likes&expand[]=runtime`;
} else {
searchUrl = `https://huggingface.co/api/spaces?limit=100&filter=${searchFilters}&search=${encodeURIComponent(this.searchQuery)}&expand[]=subdomain&expand[]=lastModified&expand[]=likes&expand[]=runtime`;
}
} else {
searchUrl = `https://huggingface.co/api/spaces?limit=100&filter=${encodeURIComponent(searchFilters)}&expand[]=subdomain&expand[]=lastModified&expand[]=likes&expand[]=runtime`;
}
const res = await fetch(searchUrl);
data = await res.json();
console.log(data)
// Transform the API response to match the expected format
data = data.filter(item => item.runtime?.stage === "RUNNING").map(item => ({
id: item.id,
subdomain: `https://${item.subdomain}.hf.space`,
likes: item.likes,
lastModified: item.lastModified
}));
}
if (sort === 'likes') {
data.sort((a, b) => (b.likes - a.likes));
} else {
data.sort((a, b) => (new Date(b.lastModified) - new Date(a.lastModified)));
}
const pageThemes = data.slice((page - 1) * 15, page * 15);
console.log(pageThemes);
return {
themes: pageThemes,
totalPages: Math.ceil(data.length / 15)
};
},
async nextPage() {
if (this.page < this.totalPages) {
this.page += 1;
const data = await this.getThemes(this.page, this.sort, this.useTestData);
this.themes = this.themes.concat(data.themes);
this.totalPages = data.totalPages;
}
},
}));
Alpine.start();
</script>
</head>
<body class="pb-10 pt-5 bg-white relative">
<section
x-data="themesData"
>
<section class="container px-6 grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-14 mx-auto relative">
<div class="col-span-2 lg:col-span-1 flex flex-col gap-14 row-start">
<div class="flex items-center gap-2">
<img src="https://camo.githubusercontent.com/a8c1f1d12aa3114010c6e74b29d47fee91d8da10a915f065c38e6d0ea7f16568/68747470733a2f2f68756767696e67666163652e636f2f64617461736574732f68756767696e67666163652f646f63756d656e746174696f6e2d696d616765732f7265736f6c76652f6d61696e2f736d6f6c6167656e74732f6d6173636f742e706e67" alt="Smolagents mascot" class="w-14 h-14 flex-shrink-0">
<h1 class="text-xl font-semibold text-gray-800 break-words">smolagents and tools gallery</h1>
</div>
</div>
<div class="col-span-2 md:col-span-3 flex items-center gap-14 flex flex-wrap lg-auto lg:ml-auto text-sm">
<div class="flex flex-col gap-2">
<div class="flex items-center">
<input
type="text"
x-model="searchQuery"
@input="searchThemes()"
placeholder="Search..."
class="px-3 py-1 border rounded-lg"
>
<!-- <div class="flex border border-l-0 rounded-r-lg overflow-hidden">
<button
@click="switchSearchType('semantic')"
:class="searchType === 'semantic' ? 'bg-orange-300 text-white' : 'bg-white text-gray-800'"
class="px-3 py-1"
>
Semantic
</button>
<button
@click="switchSearchType('keyword')"
:class="searchType === 'keyword' ? 'bg-orange-300 text-white' : 'bg-white text-gray-800'"
class="px-3 py-1 border-l"
>
Keyword
</button>
</div> -->
</div>
</div>
<div class="flex gap-2">
<span class="md:px-3 py-1 text-gray-800">type</span>
<button
:class="buttonClass('filter', 'tool')"
@click="filterType('tool')"
>
Tools
</button>
<button
:class="buttonClass('filter', 'agent')"
@click="filterType('agent')"
>
Agents
</button>
</div>
<div class="flex gap-2">
<span class="md:px-3 py-1 text-gray-800">sort by</span>
<button
:class="buttonClass('sort', 'likes')"
@click="sortThemes('likes')"
>
Most Likes
</button>
<button
:class="buttonClass('sort', 'recent')"
@click="sortThemes('recent')"
>
Recent
</button>
</div>
</div>
</section>
<div class="container px-6 grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2 mx-auto my-8 relative">
<template x-for="theme in themes" :key="theme.id">
<div class="grid-item">
<div class="grid-item-header">
<h2 class="text-sm font-medium text-white" x-text="theme.id"></h2>
</div>
<iframe :src="`${theme.subdomain}?_=${new Date().getTime()}`" :alt="theme.id" scrolling="no" frameborder="0" loading="lazy"></iframe>
<a :href="`https://huggingface.co/spaces/${theme.id}`" target="_blank"></a>
</div>
</template>
</div>
<div class="h-12 relative" x-intersect="nextPage" data-iframe-height></div>
</section>
</body>
</html>