Update index.html
Browse files- index.html +117 -81
index.html
CHANGED
|
@@ -1330,6 +1330,15 @@
|
|
| 1330 |
white-space: nowrap;
|
| 1331 |
overflow: hidden;
|
| 1332 |
text-overflow: ellipsis;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1333 |
}
|
| 1334 |
|
| 1335 |
.base-overlay-item:last-child {
|
|
@@ -1846,6 +1855,30 @@
|
|
| 1846 |
return latestDateInRange;
|
| 1847 |
}
|
| 1848 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1849 |
// Get bases within date range for a person
|
| 1850 |
function getBasesInDateRange(personKey, selectedTypes, dateRange) {
|
| 1851 |
const personData = uploadData.data[personKey];
|
|
@@ -1865,17 +1898,11 @@
|
|
| 1865 |
|
| 1866 |
// Check each model type
|
| 1867 |
for (const modelType of typesToCheck) {
|
| 1868 |
-
const
|
| 1869 |
-
if (
|
| 1870 |
-
//
|
| 1871 |
-
|
| 1872 |
-
|
| 1873 |
-
// Found a model of this type within the date range
|
| 1874 |
-
if (!bases.includes(modelType)) {
|
| 1875 |
-
bases.push(modelType);
|
| 1876 |
-
}
|
| 1877 |
-
break; // Found at least one, move to next type
|
| 1878 |
-
}
|
| 1879 |
}
|
| 1880 |
}
|
| 1881 |
}
|
|
@@ -1901,7 +1928,51 @@
|
|
| 1901 |
return baseNames[baseType] || baseType;
|
| 1902 |
}
|
| 1903 |
|
| 1904 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1905 |
function createBaseOverlay(personKey, selectedTypes, dateRange) {
|
| 1906 |
const basesInRange = getBasesInDateRange(personKey, selectedTypes, dateRange);
|
| 1907 |
|
|
@@ -1911,36 +1982,31 @@
|
|
| 1911 |
|
| 1912 |
// Sort bases by upload date (latest first)
|
| 1913 |
const sortedBases = basesInRange.sort((a, b) => {
|
| 1914 |
-
const
|
| 1915 |
-
const
|
| 1916 |
-
const modelsB = personData?.models?.[b] || [];
|
| 1917 |
|
| 1918 |
-
const
|
| 1919 |
-
|
| 1920 |
-
const date = new Date(model.uploadedAt);
|
| 1921 |
-
return !latest || date > latest ? date : latest;
|
| 1922 |
-
}
|
| 1923 |
-
return latest;
|
| 1924 |
-
}, null);
|
| 1925 |
|
| 1926 |
-
|
| 1927 |
-
if (model.uploadedAt && isWithinDateRange(model.uploadedAt, dateRange)) {
|
| 1928 |
-
const date = new Date(model.uploadedAt);
|
| 1929 |
-
return !latest || date > latest ? date : latest;
|
| 1930 |
-
}
|
| 1931 |
-
return latest;
|
| 1932 |
-
}, null);
|
| 1933 |
-
|
| 1934 |
-
return (latestDateB || 0) - (latestDateA || 0);
|
| 1935 |
});
|
| 1936 |
|
| 1937 |
// Create overlay element
|
| 1938 |
const overlay = document.createElement('div');
|
| 1939 |
overlay.className = 'base-overlay';
|
| 1940 |
-
overlay.innerHTML = sortedBases.map(base =>
|
| 1941 |
-
`<span class="base-overlay-item">${formatBaseName(base)}</span>`
|
| 1942 |
-
).join('');
|
| 1943 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1944 |
return overlay;
|
| 1945 |
}
|
| 1946 |
|
|
@@ -2160,7 +2226,7 @@
|
|
| 2160 |
</div>
|
| 2161 |
`;
|
| 2162 |
|
| 2163 |
-
// Add base overlay to the image container if date range is active
|
| 2164 |
const baseOverlay = createBaseOverlay(element.key, selectedTypes, dateRange);
|
| 2165 |
if (baseOverlay) {
|
| 2166 |
const imageContainer = card.querySelector('.imageContainer');
|
|
@@ -2275,13 +2341,13 @@
|
|
| 2275 |
return lines.join('\n');
|
| 2276 |
}
|
| 2277 |
|
| 2278 |
-
// Recent Updates Modal Functions
|
| 2279 |
function openDailyUploadsModal() {
|
| 2280 |
const modal = document.getElementById('dailyUploadsModal');
|
| 2281 |
const dateSelect = document.getElementById('dailyDateSelect');
|
| 2282 |
|
| 2283 |
// Populate date dropdown with sorted dates (newest first)
|
| 2284 |
-
const dates =
|
| 2285 |
dateSelect.innerHTML = dates.map(date => {
|
| 2286 |
const displayDate = new Date(date).toLocaleDateString('en-US', {
|
| 2287 |
weekday: 'long',
|
|
@@ -2326,6 +2392,9 @@
|
|
| 2326 |
return;
|
| 2327 |
}
|
| 2328 |
|
|
|
|
|
|
|
|
|
|
| 2329 |
// Find all people who had uploads on this date
|
| 2330 |
const modelTypeOrder = [
|
| 2331 |
'locon',
|
|
@@ -2346,16 +2415,14 @@
|
|
| 2346 |
for (const [personKey, personData] of Object.entries(uploadData.data)) {
|
| 2347 |
const modelsOnDate = [];
|
| 2348 |
const models = personData.models || {};
|
| 2349 |
-
|
| 2350 |
-
|
| 2351 |
-
|
| 2352 |
-
|
| 2353 |
-
|
| 2354 |
-
break; // Only add each model type once
|
| 2355 |
-
}
|
| 2356 |
-
}
|
| 2357 |
}
|
| 2358 |
}
|
|
|
|
| 2359 |
if (modelsOnDate.length > 0) {
|
| 2360 |
modelsOnDate.sort((a, b) => {
|
| 2361 |
const ai = orderIndex.get(String(a).toLowerCase()) ?? Number.POSITIVE_INFINITY;
|
|
@@ -2404,8 +2471,8 @@
|
|
| 2404 |
</div>
|
| 2405 |
<div class="daily-upload-models">
|
| 2406 |
${item.models.map(m => {
|
| 2407 |
-
const link =
|
| 2408 |
-
return `<a href="${link}" target="_blank" class="daily-upload-model" data-type="${m.toLowerCase()}" onclick="event.stopPropagation();">${m}</a>`;
|
| 2409 |
}).join('')}
|
| 2410 |
</div>
|
| 2411 |
</div>
|
|
@@ -2413,40 +2480,9 @@
|
|
| 2413 |
}
|
| 2414 |
|
| 2415 |
function getModelDownloadLink(personKey, modelType) {
|
| 2416 |
-
|
| 2417 |
-
|
| 2418 |
-
|
| 2419 |
-
embedding: 'embeddings',
|
| 2420 |
-
flux: 'flux',
|
| 2421 |
-
klein9: 'klein9',
|
| 2422 |
-
wan: 'wan',
|
| 2423 |
-
sdxl: 'sdxl',
|
| 2424 |
-
ltx: 'ltx',
|
| 2425 |
-
qwen: 'qwen',
|
| 2426 |
-
zimage: 'zimage',
|
| 2427 |
-
zbase: 'zbase'
|
| 2428 |
-
};
|
| 2429 |
-
|
| 2430 |
-
const folder = folderMap[modelType.toLowerCase()];
|
| 2431 |
-
if (!folder) {
|
| 2432 |
-
return '#';
|
| 2433 |
-
}
|
| 2434 |
-
|
| 2435 |
-
// Get the filename from filenames data
|
| 2436 |
-
const filenamesData = window.filenames || {};
|
| 2437 |
-
const personFilenames = filenamesData[personKey];
|
| 2438 |
-
const filenames = personFilenames?.[modelType.toLowerCase()];
|
| 2439 |
-
|
| 2440 |
-
if (!filenames || filenames.length === 0) {
|
| 2441 |
-
// Fallback to repo page
|
| 2442 |
-
return `https://huggingface.co/malcolmrey/${folder}`;
|
| 2443 |
-
}
|
| 2444 |
-
|
| 2445 |
-
const filename = filenames[0];
|
| 2446 |
-
// For WAN models, add wan2.1/ prefix
|
| 2447 |
-
const filePath = modelType.toLowerCase() === 'wan' ? `wan2.1/${filename}` : filename;
|
| 2448 |
-
|
| 2449 |
-
return `https://huggingface.co/malcolmrey/${folder}/resolve/main/${filePath}?download=true`;
|
| 2450 |
}
|
| 2451 |
|
| 2452 |
function yesNo(value) {
|
|
|
|
| 1330 |
white-space: nowrap;
|
| 1331 |
overflow: hidden;
|
| 1332 |
text-overflow: ellipsis;
|
| 1333 |
+
color: rgba(255, 255, 255, 0.85);
|
| 1334 |
+
text-decoration: none;
|
| 1335 |
+
transition: all 0.2s ease;
|
| 1336 |
+
}
|
| 1337 |
+
|
| 1338 |
+
.base-overlay-item:hover {
|
| 1339 |
+
color: #fff;
|
| 1340 |
+
text-decoration: underline;
|
| 1341 |
+
filter: brightness(1.2);
|
| 1342 |
}
|
| 1343 |
|
| 1344 |
.base-overlay-item:last-child {
|
|
|
|
| 1855 |
return latestDateInRange;
|
| 1856 |
}
|
| 1857 |
|
| 1858 |
+
// Get the latest model version for a specific base type within date range
|
| 1859 |
+
function getLatestModelForType(personKey, modelType, dateRange) {
|
| 1860 |
+
const personData = uploadData.data[personKey];
|
| 1861 |
+
if (!personData || !personData.models) return null;
|
| 1862 |
+
|
| 1863 |
+
const models = personData.models[modelType];
|
| 1864 |
+
if (!models || models.length === 0) return null;
|
| 1865 |
+
|
| 1866 |
+
let latestModel = null;
|
| 1867 |
+
let latestDate = null;
|
| 1868 |
+
|
| 1869 |
+
for (const model of models) {
|
| 1870 |
+
if (model.uploadedAt && isWithinDateRange(model.uploadedAt, dateRange)) {
|
| 1871 |
+
const modelDate = new Date(model.uploadedAt);
|
| 1872 |
+
if (!latestDate || modelDate > latestDate) {
|
| 1873 |
+
latestDate = modelDate;
|
| 1874 |
+
latestModel = model;
|
| 1875 |
+
}
|
| 1876 |
+
}
|
| 1877 |
+
}
|
| 1878 |
+
|
| 1879 |
+
return latestModel;
|
| 1880 |
+
}
|
| 1881 |
+
|
| 1882 |
// Get bases within date range for a person
|
| 1883 |
function getBasesInDateRange(personKey, selectedTypes, dateRange) {
|
| 1884 |
const personData = uploadData.data[personKey];
|
|
|
|
| 1898 |
|
| 1899 |
// Check each model type
|
| 1900 |
for (const modelType of typesToCheck) {
|
| 1901 |
+
const latestModel = getLatestModelForType(personKey, modelType, dateRange);
|
| 1902 |
+
if (latestModel) {
|
| 1903 |
+
// Found a model of this type within the date range
|
| 1904 |
+
if (!bases.includes(modelType)) {
|
| 1905 |
+
bases.push(modelType);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1906 |
}
|
| 1907 |
}
|
| 1908 |
}
|
|
|
|
| 1928 |
return baseNames[baseType] || baseType;
|
| 1929 |
}
|
| 1930 |
|
| 1931 |
+
// Get download URL for the latest model version
|
| 1932 |
+
function getLatestModelDownloadUrl(personKey, modelType, dateRange) {
|
| 1933 |
+
const latestModel = getLatestModelForType(personKey, modelType, dateRange);
|
| 1934 |
+
if (!latestModel) return null;
|
| 1935 |
+
|
| 1936 |
+
const folderMap = {
|
| 1937 |
+
locon: 'lycoris',
|
| 1938 |
+
lora: 'small-loras',
|
| 1939 |
+
embedding: 'embeddings',
|
| 1940 |
+
flux: 'flux',
|
| 1941 |
+
klein9: 'klein9',
|
| 1942 |
+
wan: 'wan',
|
| 1943 |
+
sdxl: 'sdxl',
|
| 1944 |
+
ltx: 'ltx',
|
| 1945 |
+
qwen: 'qwen',
|
| 1946 |
+
zimage: 'zimage',
|
| 1947 |
+
zbase: 'zbase'
|
| 1948 |
+
};
|
| 1949 |
+
|
| 1950 |
+
const folder = folderMap[modelType];
|
| 1951 |
+
if (!folder) return null;
|
| 1952 |
+
|
| 1953 |
+
// Get the filename from filenames data
|
| 1954 |
+
const filenamesData = window.filenames || {};
|
| 1955 |
+
const personFilenames = filenamesData[personKey];
|
| 1956 |
+
const filenames = personFilenames?.[modelType];
|
| 1957 |
+
|
| 1958 |
+
if (!filenames || filenames.length === 0) {
|
| 1959 |
+
// Fallback to repo page
|
| 1960 |
+
return `https://huggingface.co/malcolmrey/${folder}`;
|
| 1961 |
+
}
|
| 1962 |
+
|
| 1963 |
+
// Try to match the filename with the model data
|
| 1964 |
+
let filename = filenames[0];
|
| 1965 |
+
if (latestModel.filename && filenames.includes(latestModel.filename)) {
|
| 1966 |
+
filename = latestModel.filename;
|
| 1967 |
+
}
|
| 1968 |
+
|
| 1969 |
+
// For WAN models, add wan2.1/ prefix
|
| 1970 |
+
const filePath = modelType === 'wan' ? `wan2.1/${filename}` : filename;
|
| 1971 |
+
|
| 1972 |
+
return `https://huggingface.co/malcolmrey/${folder}/resolve/main/${filePath}?download=true`;
|
| 1973 |
+
}
|
| 1974 |
+
|
| 1975 |
+
// Create clickable base overlay element for page view cards
|
| 1976 |
function createBaseOverlay(personKey, selectedTypes, dateRange) {
|
| 1977 |
const basesInRange = getBasesInDateRange(personKey, selectedTypes, dateRange);
|
| 1978 |
|
|
|
|
| 1982 |
|
| 1983 |
// Sort bases by upload date (latest first)
|
| 1984 |
const sortedBases = basesInRange.sort((a, b) => {
|
| 1985 |
+
const modelA = getLatestModelForType(personKey, a, dateRange);
|
| 1986 |
+
const modelB = getLatestModelForType(personKey, b, dateRange);
|
|
|
|
| 1987 |
|
| 1988 |
+
const dateA = modelA ? new Date(modelA.uploadedAt) : null;
|
| 1989 |
+
const dateB = modelB ? new Date(modelB.uploadedAt) : null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1990 |
|
| 1991 |
+
return (dateB || 0) - (dateA || 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1992 |
});
|
| 1993 |
|
| 1994 |
// Create overlay element
|
| 1995 |
const overlay = document.createElement('div');
|
| 1996 |
overlay.className = 'base-overlay';
|
|
|
|
|
|
|
|
|
|
| 1997 |
|
| 1998 |
+
const itemsHtml = sortedBases.map(baseType => {
|
| 1999 |
+
const downloadUrl = getLatestModelDownloadUrl(personKey, baseType, dateRange);
|
| 2000 |
+
const displayName = formatBaseName(baseType);
|
| 2001 |
+
|
| 2002 |
+
if (downloadUrl) {
|
| 2003 |
+
return `<a href="${downloadUrl}" target="_blank" class="base-overlay-item" onclick="event.stopPropagation();">${displayName}</a>`;
|
| 2004 |
+
} else {
|
| 2005 |
+
return `<span class="base-overlay-item">${displayName}</span>`;
|
| 2006 |
+
}
|
| 2007 |
+
}).join('');
|
| 2008 |
+
|
| 2009 |
+
overlay.innerHTML = itemsHtml;
|
| 2010 |
return overlay;
|
| 2011 |
}
|
| 2012 |
|
|
|
|
| 2226 |
</div>
|
| 2227 |
`;
|
| 2228 |
|
| 2229 |
+
// Add clickable base overlay to the image container if date range is active
|
| 2230 |
const baseOverlay = createBaseOverlay(element.key, selectedTypes, dateRange);
|
| 2231 |
if (baseOverlay) {
|
| 2232 |
const imageContainer = card.querySelector('.imageContainer');
|
|
|
|
| 2341 |
return lines.join('\n');
|
| 2342 |
}
|
| 2343 |
|
| 2344 |
+
// Recent Updates Modal Functions - Updated to pick latest version within date range
|
| 2345 |
function openDailyUploadsModal() {
|
| 2346 |
const modal = document.getElementById('dailyUploadsModal');
|
| 2347 |
const dateSelect = document.getElementById('dailyDateSelect');
|
| 2348 |
|
| 2349 |
// Populate date dropdown with sorted dates (newest first)
|
| 2350 |
+
const dates = getAvailableUploadDates();
|
| 2351 |
dateSelect.innerHTML = dates.map(date => {
|
| 2352 |
const displayDate = new Date(date).toLocaleDateString('en-US', {
|
| 2353 |
weekday: 'long',
|
|
|
|
| 2392 |
return;
|
| 2393 |
}
|
| 2394 |
|
| 2395 |
+
// Create a date range for just this day
|
| 2396 |
+
const dateRange = { from: selectedDate, to: selectedDate };
|
| 2397 |
+
|
| 2398 |
// Find all people who had uploads on this date
|
| 2399 |
const modelTypeOrder = [
|
| 2400 |
'locon',
|
|
|
|
| 2415 |
for (const [personKey, personData] of Object.entries(uploadData.data)) {
|
| 2416 |
const modelsOnDate = [];
|
| 2417 |
const models = personData.models || {};
|
| 2418 |
+
|
| 2419 |
+
for (const modelType of modelTypeOrder) {
|
| 2420 |
+
const latestModel = getLatestModelForType(personKey, modelType, dateRange);
|
| 2421 |
+
if (latestModel) {
|
| 2422 |
+
modelsOnDate.push(modelType);
|
|
|
|
|
|
|
|
|
|
| 2423 |
}
|
| 2424 |
}
|
| 2425 |
+
|
| 2426 |
if (modelsOnDate.length > 0) {
|
| 2427 |
modelsOnDate.sort((a, b) => {
|
| 2428 |
const ai = orderIndex.get(String(a).toLowerCase()) ?? Number.POSITIVE_INFINITY;
|
|
|
|
| 2471 |
</div>
|
| 2472 |
<div class="daily-upload-models">
|
| 2473 |
${item.models.map(m => {
|
| 2474 |
+
const link = getLatestModelDownloadUrl(item.person, m, dateRange);
|
| 2475 |
+
return `<a href="${link || '#'}" target="_blank" class="daily-upload-model" data-type="${m.toLowerCase()}" onclick="event.stopPropagation();">${m}</a>`;
|
| 2476 |
}).join('')}
|
| 2477 |
</div>
|
| 2478 |
</div>
|
|
|
|
| 2480 |
}
|
| 2481 |
|
| 2482 |
function getModelDownloadLink(personKey, modelType) {
|
| 2483 |
+
// This is the old function - use getLatestModelDownloadUrl instead
|
| 2484 |
+
const dateRange = getDateRange();
|
| 2485 |
+
return getLatestModelDownloadUrl(personKey, modelType, dateRange) || '#';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2486 |
}
|
| 2487 |
|
| 2488 |
function yesNo(value) {
|