Spaces:
Running
Running
Upload index.html
Browse filesSorting by date asc/desc including model type, done by: https://huggingface.co/Symbiomatrix
(thanks! ❤️❤️❤️)
- index.html +167 -14
index.html
CHANGED
|
@@ -1346,6 +1346,8 @@
|
|
| 1346 |
<option value="name-desc">Name (Z-A)</option>
|
| 1347 |
<option value="date-desc">Update Date (Newest)</option>
|
| 1348 |
<option value="date-asc">Update Date (Oldest)</option>
|
|
|
|
|
|
|
| 1349 |
</select>
|
| 1350 |
</div>
|
| 1351 |
|
|
@@ -1603,9 +1605,34 @@
|
|
| 1603 |
currentPage = 1;
|
| 1604 |
}
|
| 1605 |
|
| 1606 |
-
function getPersonUploadDate(personKey) {
|
| 1607 |
const personData = uploadData.data[personKey];
|
| 1608 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1609 |
}
|
| 1610 |
|
| 1611 |
function isWithinPeriod(dateStr, period) {
|
|
@@ -1629,7 +1656,7 @@
|
|
| 1629 |
}
|
| 1630 |
}
|
| 1631 |
|
| 1632 |
-
function sortModels(models, sortBy) {
|
| 1633 |
const sorted = [...models];
|
| 1634 |
|
| 1635 |
switch (sortBy) {
|
|
@@ -1639,20 +1666,50 @@
|
|
| 1639 |
case 'name-desc':
|
| 1640 |
sorted.sort((a, b) => b.key.localeCompare(a.key));
|
| 1641 |
break;
|
| 1642 |
-
case 'date-desc':
|
| 1643 |
sorted.sort((a, b) => {
|
| 1644 |
-
const dateA = getPersonUploadDate(a.key) || '1970-01-01';
|
| 1645 |
-
const dateB = getPersonUploadDate(b.key) || '1970-01-01';
|
| 1646 |
return dateB.localeCompare(dateA);
|
| 1647 |
});
|
| 1648 |
break;
|
| 1649 |
-
case 'date-asc':
|
| 1650 |
sorted.sort((a, b) => {
|
| 1651 |
-
const dateA = getPersonUploadDate(a.key) || '2100-01-01';
|
| 1652 |
-
const dateB = getPersonUploadDate(b.key) || '2100-01-01';
|
| 1653 |
return dateA.localeCompare(dateB);
|
| 1654 |
});
|
| 1655 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1656 |
}
|
| 1657 |
|
| 1658 |
return sorted;
|
|
@@ -1734,6 +1791,7 @@
|
|
| 1734 |
|
| 1735 |
function renderCurrentPage() {
|
| 1736 |
const pageSize = getPageSize();
|
|
|
|
| 1737 |
const contentDiv = document.getElementById('mainContent');
|
| 1738 |
contentDiv.innerHTML = '';
|
| 1739 |
|
|
@@ -1746,7 +1804,39 @@
|
|
| 1746 |
pageItems = filteredResults.slice(start, end);
|
| 1747 |
}
|
| 1748 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1749 |
pageItems.forEach((element) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1750 |
const card = document.createElement('div');
|
| 1751 |
card.className = 'element';
|
| 1752 |
|
|
@@ -1775,6 +1865,49 @@
|
|
| 1775 |
|
| 1776 |
updatePaginationControls();
|
| 1777 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1778 |
|
| 1779 |
function getPersonUpdateTooltip(personKey) {
|
| 1780 |
const personData = uploadData.data?.[personKey];
|
|
@@ -2339,6 +2472,11 @@
|
|
| 2339 |
const periodFilter = getPeriodFilter();
|
| 2340 |
const pageSize = getPageSize();
|
| 2341 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2342 |
// Filter by search term and type
|
| 2343 |
let filtered = presenceModels.filter((element) => {
|
| 2344 |
return (
|
|
@@ -2347,16 +2485,31 @@
|
|
| 2347 |
);
|
| 2348 |
});
|
| 2349 |
|
| 2350 |
-
// Filter by period
|
| 2351 |
if (periodFilter !== 'all') {
|
| 2352 |
filtered = filtered.filter((element) => {
|
| 2353 |
-
|
| 2354 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2355 |
});
|
| 2356 |
}
|
| 2357 |
|
| 2358 |
-
// Sort
|
| 2359 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2360 |
|
| 2361 |
// Store for pagination
|
| 2362 |
filteredResults = filtered;
|
|
|
|
| 1346 |
<option value="name-desc">Name (Z-A)</option>
|
| 1347 |
<option value="date-desc">Update Date (Newest)</option>
|
| 1348 |
<option value="date-asc">Update Date (Oldest)</option>
|
| 1349 |
+
<option value="daily-desc">Daily (Newest)</option>
|
| 1350 |
+
<option value="daily-asc">Daily (Oldest)</option>
|
| 1351 |
</select>
|
| 1352 |
</div>
|
| 1353 |
|
|
|
|
| 1605 |
currentPage = 1;
|
| 1606 |
}
|
| 1607 |
|
| 1608 |
+
function getPersonUploadDate(personKey, selectedTypes = null, dateOnly = false) {
|
| 1609 |
const personData = uploadData.data[personKey];
|
| 1610 |
+
if (!personData || !personData.models) return null;
|
| 1611 |
+
|
| 1612 |
+
// If no specific types requested, return the global lastUpdated
|
| 1613 |
+
if (!selectedTypes) {
|
| 1614 |
+
const dateStr = personData.lastUpdated;
|
| 1615 |
+
return dateOnly && dateStr ? dateStr.split('T')[0] : dateStr;
|
| 1616 |
+
}
|
| 1617 |
+
|
| 1618 |
+
// Find the most recent upload date among selected model types
|
| 1619 |
+
let mostRecentDate = null;
|
| 1620 |
+
|
| 1621 |
+
for (const modelType of selectedTypes) {
|
| 1622 |
+
const models = personData.models[modelType];
|
| 1623 |
+
if (models && models.length > 0) {
|
| 1624 |
+
// Models are typically sorted with newest first in the array
|
| 1625 |
+
const latestModel = models[0];
|
| 1626 |
+
if (latestModel.uploadedAt) {
|
| 1627 |
+
const modelDate = latestModel.uploadedAt;
|
| 1628 |
+
if (!mostRecentDate || modelDate > mostRecentDate) {
|
| 1629 |
+
mostRecentDate = modelDate;
|
| 1630 |
+
}
|
| 1631 |
+
}
|
| 1632 |
+
}
|
| 1633 |
+
}
|
| 1634 |
+
|
| 1635 |
+
return dateOnly && mostRecentDate ? mostRecentDate.split('T')[0] : mostRecentDate;
|
| 1636 |
}
|
| 1637 |
|
| 1638 |
function isWithinPeriod(dateStr, period) {
|
|
|
|
| 1656 |
}
|
| 1657 |
}
|
| 1658 |
|
| 1659 |
+
function sortModels(models, sortBy, selectedTypes = null) {
|
| 1660 |
const sorted = [...models];
|
| 1661 |
|
| 1662 |
switch (sortBy) {
|
|
|
|
| 1666 |
case 'name-desc':
|
| 1667 |
sorted.sort((a, b) => b.key.localeCompare(a.key));
|
| 1668 |
break;
|
| 1669 |
+
case 'date-desc': // "Update Date (Newest)"
|
| 1670 |
sorted.sort((a, b) => {
|
| 1671 |
+
const dateA = getPersonUploadDate(a.key, selectedTypes) || '1970-01-01';
|
| 1672 |
+
const dateB = getPersonUploadDate(b.key, selectedTypes) || '1970-01-01';
|
| 1673 |
return dateB.localeCompare(dateA);
|
| 1674 |
});
|
| 1675 |
break;
|
| 1676 |
+
case 'date-asc': // "Update Date (Oldest)"
|
| 1677 |
sorted.sort((a, b) => {
|
| 1678 |
+
const dateA = getPersonUploadDate(a.key, selectedTypes) || '2100-01-01';
|
| 1679 |
+
const dateB = getPersonUploadDate(b.key, selectedTypes) || '2100-01-01';
|
| 1680 |
return dateA.localeCompare(dateB);
|
| 1681 |
});
|
| 1682 |
break;
|
| 1683 |
+
case 'daily-desc': // "Daily (Newest)" - Group by date, newest days first, then A-Z
|
| 1684 |
+
sorted.sort((a, b) => {
|
| 1685 |
+
// Get just the date portion (YYYY-MM-DD) for grouping
|
| 1686 |
+
const dateA = getPersonUploadDate(a.key, selectedTypes, true) || '1970-01-01';
|
| 1687 |
+
const dateB = getPersonUploadDate(b.key, selectedTypes, true) || '1970-01-01';
|
| 1688 |
+
|
| 1689 |
+
// First, sort by date descending (newest days first)
|
| 1690 |
+
if (dateB !== dateA) {
|
| 1691 |
+
return dateB.localeCompare(dateA);
|
| 1692 |
+
}
|
| 1693 |
+
|
| 1694 |
+
// If same date, sort by name A-Z
|
| 1695 |
+
return a.key.localeCompare(b.key);
|
| 1696 |
+
});
|
| 1697 |
+
break;
|
| 1698 |
+
case 'daily-asc': // "Daily (Oldest)" - Group by date, oldest days first, then A-Z
|
| 1699 |
+
sorted.sort((a, b) => {
|
| 1700 |
+
// Get just the date portion (YYYY-MM-DD) for grouping
|
| 1701 |
+
const dateA = getPersonUploadDate(a.key, selectedTypes, true) || '2100-01-01';
|
| 1702 |
+
const dateB = getPersonUploadDate(b.key, selectedTypes, true) || '2100-01-01';
|
| 1703 |
+
|
| 1704 |
+
// First, sort by date ascending (oldest days first)
|
| 1705 |
+
if (dateA !== dateB) {
|
| 1706 |
+
return dateA.localeCompare(dateB);
|
| 1707 |
+
}
|
| 1708 |
+
|
| 1709 |
+
// If same date, sort by name A-Z
|
| 1710 |
+
return a.key.localeCompare(b.key);
|
| 1711 |
+
});
|
| 1712 |
+
break;
|
| 1713 |
}
|
| 1714 |
|
| 1715 |
return sorted;
|
|
|
|
| 1791 |
|
| 1792 |
function renderCurrentPage() {
|
| 1793 |
const pageSize = getPageSize();
|
| 1794 |
+
const sortBy = getSortBy();
|
| 1795 |
const contentDiv = document.getElementById('mainContent');
|
| 1796 |
contentDiv.innerHTML = '';
|
| 1797 |
|
|
|
|
| 1804 |
pageItems = filteredResults.slice(start, end);
|
| 1805 |
}
|
| 1806 |
|
| 1807 |
+
// Get selected types for date calculation
|
| 1808 |
+
const selectedTypes = getSelectedTypes();
|
| 1809 |
+
const showAllTypes = selectedTypes.length === 0;
|
| 1810 |
+
|
| 1811 |
+
let lastDate = null;
|
| 1812 |
+
|
| 1813 |
pageItems.forEach((element) => {
|
| 1814 |
+
// Get the date for this element (respecting selected types)
|
| 1815 |
+
const dateStr = showAllTypes
|
| 1816 |
+
? getPersonUploadDate(element.key, null, true)
|
| 1817 |
+
: getPersonUploadDate(element.key, selectedTypes, true);
|
| 1818 |
+
|
| 1819 |
+
// Add date header if doing daily sort and date changed
|
| 1820 |
+
if (sortBy.startsWith('daily-') && dateStr && dateStr !== lastDate) {
|
| 1821 |
+
const formattedDate = formatDateForDisplay(dateStr);
|
| 1822 |
+
const dateHeader = document.createElement('div');
|
| 1823 |
+
dateHeader.className = 'date-header';
|
| 1824 |
+
dateHeader.style.cssText = `
|
| 1825 |
+
grid-column: 1 / -1;
|
| 1826 |
+
margin: 20px 0 10px;
|
| 1827 |
+
padding: 12px 16px;
|
| 1828 |
+
background: var(--card-bg);
|
| 1829 |
+
border-radius: 12px;
|
| 1830 |
+
border-left: 4px solid var(--accent-blue);
|
| 1831 |
+
font-weight: 600;
|
| 1832 |
+
color: var(--accent-blue);
|
| 1833 |
+
font-size: 16px;
|
| 1834 |
+
box-shadow: 0 2px 8px var(--shadow-color);
|
| 1835 |
+
`;
|
| 1836 |
+
dateHeader.innerHTML = `📅 ${formattedDate}`;
|
| 1837 |
+
contentDiv.appendChild(dateHeader);
|
| 1838 |
+
lastDate = dateStr;
|
| 1839 |
+
}
|
| 1840 |
const card = document.createElement('div');
|
| 1841 |
card.className = 'element';
|
| 1842 |
|
|
|
|
| 1865 |
|
| 1866 |
updatePaginationControls();
|
| 1867 |
}
|
| 1868 |
+
|
| 1869 |
+
// Helper function to get selected types
|
| 1870 |
+
function getSelectedTypes() {
|
| 1871 |
+
const selectedTypes = [];
|
| 1872 |
+
if (document.getElementById('selectedLocon').checked) selectedTypes.push('locon');
|
| 1873 |
+
if (document.getElementById('selectedLora').checked) selectedTypes.push('lora');
|
| 1874 |
+
if (document.getElementById('selectedEmbedding').checked) selectedTypes.push('embedding');
|
| 1875 |
+
if (document.getElementById('selectedFlux').checked) selectedTypes.push('flux');
|
| 1876 |
+
if (document.getElementById('selectedWan').checked) selectedTypes.push('wan');
|
| 1877 |
+
if (document.getElementById('selectedSdxl').checked) selectedTypes.push('sdxl');
|
| 1878 |
+
if (document.getElementById('selectedZimage').checked) selectedTypes.push('zimage');
|
| 1879 |
+
if (document.getElementById('selectedQwen').checked) selectedTypes.push('qwen');
|
| 1880 |
+
if (document.getElementById('selectedLtx').checked) selectedTypes.push('ltx');
|
| 1881 |
+
if (document.getElementById('selectedKlein9').checked) selectedTypes.push('klein9');
|
| 1882 |
+
return selectedTypes;
|
| 1883 |
+
}
|
| 1884 |
+
|
| 1885 |
+
// Helper function to format date for display
|
| 1886 |
+
function formatDateForDisplay(dateStr) {
|
| 1887 |
+
if (!dateStr) return 'Unknown Date';
|
| 1888 |
+
const date = new Date(dateStr);
|
| 1889 |
+
const today = new Date();
|
| 1890 |
+
const yesterday = new Date(today);
|
| 1891 |
+
yesterday.setDate(yesterday.getDate() - 1);
|
| 1892 |
+
|
| 1893 |
+
// Check if it's today
|
| 1894 |
+
if (date.toDateString() === today.toDateString()) {
|
| 1895 |
+
return 'Today';
|
| 1896 |
+
}
|
| 1897 |
+
|
| 1898 |
+
// Check if it's yesterday
|
| 1899 |
+
if (date.toDateString() === yesterday.toDateString()) {
|
| 1900 |
+
return 'Yesterday';
|
| 1901 |
+
}
|
| 1902 |
+
|
| 1903 |
+
// Otherwise format normally
|
| 1904 |
+
return date.toLocaleDateString('en-US', {
|
| 1905 |
+
weekday: 'long',
|
| 1906 |
+
year: 'numeric',
|
| 1907 |
+
month: 'long',
|
| 1908 |
+
day: 'numeric'
|
| 1909 |
+
});
|
| 1910 |
+
}
|
| 1911 |
|
| 1912 |
function getPersonUpdateTooltip(personKey) {
|
| 1913 |
const personData = uploadData.data?.[personKey];
|
|
|
|
| 2472 |
const periodFilter = getPeriodFilter();
|
| 2473 |
const pageSize = getPageSize();
|
| 2474 |
|
| 2475 |
+
// Get which model types are selected
|
| 2476 |
+
const selectedTypes = getSelectedTypes();
|
| 2477 |
+
|
| 2478 |
+
// If no types are selected, we should show all types
|
| 2479 |
+
const showAllTypes = selectedTypes.length === 0;
|
| 2480 |
// Filter by search term and type
|
| 2481 |
let filtered = presenceModels.filter((element) => {
|
| 2482 |
return (
|
|
|
|
| 2485 |
);
|
| 2486 |
});
|
| 2487 |
|
| 2488 |
+
// Filter by period - use the appropriate date based on selected types
|
| 2489 |
if (periodFilter !== 'all') {
|
| 2490 |
filtered = filtered.filter((element) => {
|
| 2491 |
+
// Get the appropriate date based on what we're showing
|
| 2492 |
+
const relevantDate = showAllTypes
|
| 2493 |
+
? getPersonUploadDate(element.key) // Global date when showing all types
|
| 2494 |
+
: getPersonUploadDate(element.key, selectedTypes); // Date only for selected types
|
| 2495 |
+
|
| 2496 |
+
// If showing selected types only, and person has no models of those types,
|
| 2497 |
+
// they shouldn't appear in the results at all
|
| 2498 |
+
if (!showAllTypes && !relevantDate) {
|
| 2499 |
+
return false;
|
| 2500 |
+
}
|
| 2501 |
+
|
| 2502 |
+
return isWithinPeriod(relevantDate, periodFilter);
|
| 2503 |
});
|
| 2504 |
}
|
| 2505 |
|
| 2506 |
+
// Sort - pass selectedTypes when sorting by date
|
| 2507 |
+
const isSortingByDate = sortBy.includes('date') || sortBy.includes('daily');
|
| 2508 |
+
filtered = sortModels(
|
| 2509 |
+
filtered,
|
| 2510 |
+
sortBy,
|
| 2511 |
+
(isSortingByDate && !showAllTypes) ? selectedTypes : null
|
| 2512 |
+
);
|
| 2513 |
|
| 2514 |
// Store for pagination
|
| 2515 |
filteredResults = filtered;
|