Commit
·
1e45463
1
Parent(s):
4bdf3bc
Add filter options for search and similar resources
Browse files- index.html +176 -8
index.html
CHANGED
@@ -111,7 +111,7 @@
|
|
111 |
Enter keywords to search through descriptions. The search will
|
112 |
automatically update as you type.
|
113 |
</p>
|
114 |
-
<div class="flex gap-2">
|
115 |
<select
|
116 |
id="searchTypeSelect"
|
117 |
class="text-sm border rounded-lg px-3 py-2 bg-white text-gray-700 focus:ring-2 focus:ring-blue-100 focus:border-blue-300 transition-all outline-none"
|
@@ -129,6 +129,54 @@
|
|
129 |
<option value="likes">Sort by likes</option>
|
130 |
<option value="downloads">Sort by downloads</option>
|
131 |
</select>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
</div>
|
133 |
</div>
|
134 |
<div class="relative">
|
@@ -156,7 +204,7 @@
|
|
156 |
Enter an ID to find similar resources. Popular items will appear
|
157 |
as you type.
|
158 |
</p>
|
159 |
-
<div class="flex gap-2">
|
160 |
<select
|
161 |
id="similarTypeSelect"
|
162 |
class="text-sm border rounded-lg px-3 py-2 bg-white text-gray-700 focus:ring-2 focus:ring-blue-100 focus:border-blue-300 transition-all outline-none"
|
@@ -174,6 +222,54 @@
|
|
174 |
<option value="likes">Sort by likes</option>
|
175 |
<option value="downloads">Sort by downloads</option>
|
176 |
</select>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
177 |
</div>
|
178 |
</div>
|
179 |
<div class="flex gap-3">
|
@@ -300,6 +396,8 @@
|
|
300 |
// Add these variables with other configurations
|
301 |
let currentSort = "similarity";
|
302 |
let currentType = INITIAL_TYPE;
|
|
|
|
|
303 |
|
304 |
// Initialize Lucide icons
|
305 |
lucide.createIcons();
|
@@ -629,7 +727,7 @@
|
|
629 |
const response = await fetch(
|
630 |
`${endpoint}?${paramName}=${encodeURIComponent(resourceId)}&k=${
|
631 |
RESULTS_PER_PAGE * page
|
632 |
-
}&sort_by=${currentSort}`
|
633 |
);
|
634 |
if (!response.ok) throw new Error("Similarity search failed");
|
635 |
|
@@ -928,11 +1026,15 @@
|
|
928 |
|
929 |
try {
|
930 |
const endpoint = `${API_URL}/search/${currentType}`;
|
931 |
-
const
|
932 |
-
|
933 |
-
|
934 |
-
|
935 |
-
|
|
|
|
|
|
|
|
|
936 |
if (!response.ok) throw new Error("Search failed");
|
937 |
|
938 |
const data = await response.json();
|
@@ -1031,6 +1133,72 @@
|
|
1031 |
}
|
1032 |
}
|
1033 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1034 |
</script>
|
1035 |
</body>
|
1036 |
</html>
|
|
|
111 |
Enter keywords to search through descriptions. The search will
|
112 |
automatically update as you type.
|
113 |
</p>
|
114 |
+
<div class="flex flex-wrap gap-2">
|
115 |
<select
|
116 |
id="searchTypeSelect"
|
117 |
class="text-sm border rounded-lg px-3 py-2 bg-white text-gray-700 focus:ring-2 focus:ring-blue-100 focus:border-blue-300 transition-all outline-none"
|
|
|
129 |
<option value="likes">Sort by likes</option>
|
130 |
<option value="downloads">Sort by downloads</option>
|
131 |
</select>
|
132 |
+
<div class="relative">
|
133 |
+
<button
|
134 |
+
onclick="toggleFilters('search')"
|
135 |
+
class="text-sm border rounded-lg px-3 py-2 bg-white text-gray-700 hover:bg-gray-50 focus:ring-2 focus:ring-blue-100 focus:border-blue-300 transition-all outline-none flex items-center gap-2"
|
136 |
+
>
|
137 |
+
<i data-lucide="filter"></i>
|
138 |
+
Filters
|
139 |
+
<span
|
140 |
+
id="searchActiveFilters"
|
141 |
+
class="hidden px-1.5 py-0.5 bg-blue-100 text-blue-700 text-xs rounded-full"
|
142 |
+
></span>
|
143 |
+
</button>
|
144 |
+
<div
|
145 |
+
id="searchFiltersPopover"
|
146 |
+
class="hidden absolute right-0 mt-2 w-64 bg-white border border-gray-200 rounded-lg shadow-lg p-4 z-10"
|
147 |
+
>
|
148 |
+
<div class="space-y-4">
|
149 |
+
<div>
|
150 |
+
<label
|
151 |
+
class="block text-sm font-medium text-gray-700 mb-1"
|
152 |
+
>Minimum Likes</label
|
153 |
+
>
|
154 |
+
<input
|
155 |
+
type="number"
|
156 |
+
id="searchMinLikes"
|
157 |
+
placeholder="0"
|
158 |
+
min="0"
|
159 |
+
class="w-full text-sm border rounded-lg px-3 py-2 bg-white text-gray-700 focus:ring-2 focus:ring-blue-100 focus:border-blue-300 transition-all outline-none"
|
160 |
+
onchange="handleFilterChange('search')"
|
161 |
+
/>
|
162 |
+
</div>
|
163 |
+
<div>
|
164 |
+
<label
|
165 |
+
class="block text-sm font-medium text-gray-700 mb-1"
|
166 |
+
>Minimum Downloads</label
|
167 |
+
>
|
168 |
+
<input
|
169 |
+
type="number"
|
170 |
+
id="searchMinDownloads"
|
171 |
+
placeholder="0"
|
172 |
+
min="0"
|
173 |
+
class="w-full text-sm border rounded-lg px-3 py-2 bg-white text-gray-700 focus:ring-2 focus:ring-blue-100 focus:border-blue-300 transition-all outline-none"
|
174 |
+
onchange="handleFilterChange('search')"
|
175 |
+
/>
|
176 |
+
</div>
|
177 |
+
</div>
|
178 |
+
</div>
|
179 |
+
</div>
|
180 |
</div>
|
181 |
</div>
|
182 |
<div class="relative">
|
|
|
204 |
Enter an ID to find similar resources. Popular items will appear
|
205 |
as you type.
|
206 |
</p>
|
207 |
+
<div class="flex flex-wrap gap-2">
|
208 |
<select
|
209 |
id="similarTypeSelect"
|
210 |
class="text-sm border rounded-lg px-3 py-2 bg-white text-gray-700 focus:ring-2 focus:ring-blue-100 focus:border-blue-300 transition-all outline-none"
|
|
|
222 |
<option value="likes">Sort by likes</option>
|
223 |
<option value="downloads">Sort by downloads</option>
|
224 |
</select>
|
225 |
+
<div class="relative">
|
226 |
+
<button
|
227 |
+
onclick="toggleFilters('similar')"
|
228 |
+
class="text-sm border rounded-lg px-3 py-2 bg-white text-gray-700 hover:bg-gray-50 focus:ring-2 focus:ring-blue-100 focus:border-blue-300 transition-all outline-none flex items-center gap-2"
|
229 |
+
>
|
230 |
+
<i data-lucide="filter"></i>
|
231 |
+
Filters
|
232 |
+
<span
|
233 |
+
id="similarActiveFilters"
|
234 |
+
class="hidden px-1.5 py-0.5 bg-blue-100 text-blue-700 text-xs rounded-full"
|
235 |
+
></span>
|
236 |
+
</button>
|
237 |
+
<div
|
238 |
+
id="similarFiltersPopover"
|
239 |
+
class="hidden absolute right-0 mt-2 w-64 bg-white border border-gray-200 rounded-lg shadow-lg p-4 z-10"
|
240 |
+
>
|
241 |
+
<div class="space-y-4">
|
242 |
+
<div>
|
243 |
+
<label
|
244 |
+
class="block text-sm font-medium text-gray-700 mb-1"
|
245 |
+
>Minimum Likes</label
|
246 |
+
>
|
247 |
+
<input
|
248 |
+
type="number"
|
249 |
+
id="similarMinLikes"
|
250 |
+
placeholder="0"
|
251 |
+
min="0"
|
252 |
+
class="w-full text-sm border rounded-lg px-3 py-2 bg-white text-gray-700 focus:ring-2 focus:ring-blue-100 focus:border-blue-300 transition-all outline-none"
|
253 |
+
onchange="handleFilterChange('similar')"
|
254 |
+
/>
|
255 |
+
</div>
|
256 |
+
<div>
|
257 |
+
<label
|
258 |
+
class="block text-sm font-medium text-gray-700 mb-1"
|
259 |
+
>Minimum Downloads</label
|
260 |
+
>
|
261 |
+
<input
|
262 |
+
type="number"
|
263 |
+
id="similarMinDownloads"
|
264 |
+
placeholder="0"
|
265 |
+
min="0"
|
266 |
+
class="w-full text-sm border rounded-lg px-3 py-2 bg-white text-gray-700 focus:ring-2 focus:ring-blue-100 focus:border-blue-300 transition-all outline-none"
|
267 |
+
onchange="handleFilterChange('similar')"
|
268 |
+
/>
|
269 |
+
</div>
|
270 |
+
</div>
|
271 |
+
</div>
|
272 |
+
</div>
|
273 |
</div>
|
274 |
</div>
|
275 |
<div class="flex gap-3">
|
|
|
396 |
// Add these variables with other configurations
|
397 |
let currentSort = "similarity";
|
398 |
let currentType = INITIAL_TYPE;
|
399 |
+
let currentMinLikes = 0;
|
400 |
+
let currentMinDownloads = 0;
|
401 |
|
402 |
// Initialize Lucide icons
|
403 |
lucide.createIcons();
|
|
|
727 |
const response = await fetch(
|
728 |
`${endpoint}?${paramName}=${encodeURIComponent(resourceId)}&k=${
|
729 |
RESULTS_PER_PAGE * page
|
730 |
+
}&sort_by=${currentSort}&min_likes=${currentMinLikes}&min_downloads=${currentMinDownloads}`
|
731 |
);
|
732 |
if (!response.ok) throw new Error("Similarity search failed");
|
733 |
|
|
|
1026 |
|
1027 |
try {
|
1028 |
const endpoint = `${API_URL}/search/${currentType}`;
|
1029 |
+
const params = new URLSearchParams({
|
1030 |
+
query: query,
|
1031 |
+
k: RESULTS_PER_PAGE * page,
|
1032 |
+
sort_by: currentSort,
|
1033 |
+
min_likes: currentMinLikes,
|
1034 |
+
min_downloads: currentMinDownloads,
|
1035 |
+
});
|
1036 |
+
|
1037 |
+
const response = await fetch(`${endpoint}?${params}`);
|
1038 |
if (!response.ok) throw new Error("Search failed");
|
1039 |
|
1040 |
const data = await response.json();
|
|
|
1133 |
}
|
1134 |
}
|
1135 |
}
|
1136 |
+
|
1137 |
+
// Add these new functions to handle the filters UI
|
1138 |
+
function toggleFilters(tab) {
|
1139 |
+
const popover = document.getElementById(`${tab}FiltersPopover`);
|
1140 |
+
popover.classList.toggle("hidden");
|
1141 |
+
|
1142 |
+
// Close other popovers
|
1143 |
+
const otherTab = tab === "search" ? "similar" : "search";
|
1144 |
+
document
|
1145 |
+
.getElementById(`${otherTab}FiltersPopover`)
|
1146 |
+
.classList.add("hidden");
|
1147 |
+
}
|
1148 |
+
|
1149 |
+
// Close filters when clicking outside
|
1150 |
+
document.addEventListener("click", (event) => {
|
1151 |
+
const searchPopover = document.getElementById("searchFiltersPopover");
|
1152 |
+
const similarPopover = document.getElementById("similarFiltersPopover");
|
1153 |
+
const searchButton = event.target.closest(
|
1154 |
+
"button[onclick=\"toggleFilters('search')\"]"
|
1155 |
+
);
|
1156 |
+
const similarButton = event.target.closest(
|
1157 |
+
"button[onclick=\"toggleFilters('similar')\"]"
|
1158 |
+
);
|
1159 |
+
|
1160 |
+
if (!searchButton && !event.target.closest("#searchFiltersPopover")) {
|
1161 |
+
searchPopover.classList.add("hidden");
|
1162 |
+
}
|
1163 |
+
if (!similarButton && !event.target.closest("#similarFiltersPopover")) {
|
1164 |
+
similarPopover.classList.add("hidden");
|
1165 |
+
}
|
1166 |
+
});
|
1167 |
+
|
1168 |
+
// Modify handleFilterChange to update the active filters indicator
|
1169 |
+
function handleFilterChange(tab) {
|
1170 |
+
const minLikesInput = document.getElementById(`${tab}MinLikes`);
|
1171 |
+
const minDownloadsInput = document.getElementById(`${tab}MinDownloads`);
|
1172 |
+
const activeFiltersSpan = document.getElementById(
|
1173 |
+
`${tab}ActiveFilters`
|
1174 |
+
);
|
1175 |
+
|
1176 |
+
currentMinLikes = parseInt(minLikesInput.value) || 0;
|
1177 |
+
currentMinDownloads = parseInt(minDownloadsInput.value) || 0;
|
1178 |
+
|
1179 |
+
// Update active filters indicator
|
1180 |
+
const activeCount =
|
1181 |
+
(currentMinLikes > 0 ? 1 : 0) + (currentMinDownloads > 0 ? 1 : 0);
|
1182 |
+
if (activeCount > 0) {
|
1183 |
+
activeFiltersSpan.textContent = activeCount;
|
1184 |
+
activeFiltersSpan.classList.remove("hidden");
|
1185 |
+
} else {
|
1186 |
+
activeFiltersSpan.classList.add("hidden");
|
1187 |
+
}
|
1188 |
+
|
1189 |
+
// Re-run the current search with new filters
|
1190 |
+
if (tab === "search") {
|
1191 |
+
const searchQuery = document.getElementById("searchInput").value;
|
1192 |
+
if (searchQuery.length >= MIN_SEARCH_LENGTH) {
|
1193 |
+
searchResources(searchQuery, 1);
|
1194 |
+
}
|
1195 |
+
} else {
|
1196 |
+
const resourceId = document.getElementById("resourceInput").value;
|
1197 |
+
if (resourceId) {
|
1198 |
+
findSimilarResources(1);
|
1199 |
+
}
|
1200 |
+
}
|
1201 |
+
}
|
1202 |
</script>
|
1203 |
</body>
|
1204 |
</html>
|