BugFix and UI improvements
| @@ -2293,11 +2293,11 @@ | |||
| 2293 | 2293 | ||
| 2294 | </div> | 2294 | </div> |
| 2295 | </div> | 2295 | </div> |
| 2296 | <!-- <select id="featherless_model"> | 2296 | <select id="featherless_model" hidden> |
| 2297 | <option value="" data-i18n="-- Connect to the API --"> | 2297 | <option value="" data-i18n="-- Connect to the API --"> |
| 2298 | -- Connect to the API -- | 2298 | -- Connect to the API -- |
| 2299 | </option> | 2299 | </option> |
| 2300 | </select> --> | 2300 | </select> |
| 2301 | </div> | 2301 | </div> |
| 2302 | <div data-tg-type="vllm"> | 2302 | <div data-tg-type="vllm"> |
| 2303 | <div class="flex-container flexFlowColumn"> | 2303 | <div class="flex-container flexFlowColumn"> |
| @@ -267,6 +267,7 @@ export async function loadAphroditeModels(data) { | |||
| 267 | } | 267 | } |
| 268 | 268 | ||
| 269 | let selectedModelId = null; | 269 | let selectedModelId = null; |
| 270 | let currentPage = 1; | ||
| 270 | export async function loadFeatherlessModels(data) { | 271 | export async function loadFeatherlessModels(data) { |
| 271 | const searchBar = document.getElementById('model_search_bar'); | 272 | const searchBar = document.getElementById('model_search_bar'); |
| 272 | const modelCardBlock = document.getElementById('model_card_block'); | 273 | const modelCardBlock = document.getElementById('model_card_block'); |
| @@ -293,32 +294,30 @@ export async function loadFeatherlessModels(data) { | |||
| 293 | populateClassSelection(data); | 294 | populateClassSelection(data); |
| 294 | 295 | ||
| 295 | // Retrieve the stored number of items per page or default to 5 | 296 | // Retrieve the stored number of items per page or default to 5 |
| 296 | const perPage = Number(localStorage.getItem(storageKey)) || 6; | 297 | const perPage = Number(localStorage.getItem(storageKey)) || 10; |
| 297 | 298 | ||
| 298 | // Initialize pagination with the full set of models | 299 | // Initialize pagination with the full set of models |
| 299 | setupPagination(originalModels, perPage); | 300 | setupPagination(originalModels, perPage); |
| 300 | 301 | ||
| 301 | // Function to set up pagination (also used for filtered results) | 302 | // Function to set up pagination (also used for filtered results) |
| 302 | function setupPagination(models, perPage) { | 303 | function setupPagination(models, perPage, pageNumber = currentPage) { |
| 303 | paginationContainer.pagination({ | 304 | paginationContainer.pagination({ |
| 304 | dataSource: models, | 305 | dataSource: models, |
| 305 | pageSize: perPage, | 306 | pageSize: perPage, |
| 307 | pageNumber: pageNumber, | ||
| 306 | sizeChangerOptions: [6, 10, 26, 50, 100, 250, 500, 1000], | 308 | sizeChangerOptions: [6, 10, 26, 50, 100, 250, 500, 1000], |
| 307 | pageRange: 1, | 309 | pageRange: 1, |
| 308 | pageNumber: 1, | ||
| 309 | showPageNumbers: true, | 310 | showPageNumbers: true, |
| 310 | showSizeChanger: false, | 311 | showSizeChanger: false, |
| 311 | prevText: '<', | 312 | prevText: '<', |
| 312 | nextText: '>', | 313 | nextText: '>', |
| 313 | formatNavigator: function (currentPage, totalPage) { | 314 | formatNavigator: function (currentPage, totalPage) { |
| 314 | return (currentPage - 1) * perPage + 1 + ' - ' + currentPage * perPage + ' of ' + totalPage * perPage; | 315 | return (currentPage - 1) * perPage + 1 + ' - ' + currentPage * perPage + ' of ' + totalPage * perPage; |
| 315 | }, | 316 | }, |
| 316 | showNavigator: true, | 317 | showNavigator: true, |
| 317 | callback: function (modelsOnPage) { | 318 | callback: function (modelsOnPage, pagination) { |
| 318 | // Clear the model card block before adding new cards | ||
| 319 | modelCardBlock.innerHTML = ''; | 319 | modelCardBlock.innerHTML = ''; |
| 320 | 320 | ||
| 321 | // Loop through the models for the current page and create cards | ||
| 322 | modelsOnPage.forEach(model => { | 321 | modelsOnPage.forEach(model => { |
| 323 | const card = document.createElement('div'); | 322 | const card = document.createElement('div'); |
| 324 | card.classList.add('model-card'); | 323 | card.classList.add('model-card'); |
| @@ -342,41 +341,43 @@ export async function loadFeatherlessModels(data) { | |||
| 342 | contextLengthDiv.classList.add('model-context-length'); | 341 | contextLengthDiv.classList.add('model-context-length'); |
| 343 | contextLengthDiv.textContent = `Context Length: ${model.context_length}`; | 342 | contextLengthDiv.textContent = `Context Length: ${model.context_length}`; |
| 344 | 343 | ||
| 344 | const dateAddedDiv = document.createElement('div'); | ||
| 345 | dateAddedDiv.classList.add('model-date-added'); | ||
| 346 | dateAddedDiv.textContent = `Added On: ${new Date(model.updated_at).toLocaleDateString()}`; | ||
| 347 | |||
| 345 | detailsContainer.appendChild(modelClassDiv); | 348 | detailsContainer.appendChild(modelClassDiv); |
| 346 | detailsContainer.appendChild(contextLengthDiv); | 349 | detailsContainer.appendChild(contextLengthDiv); |
| 350 | detailsContainer.appendChild(dateAddedDiv); | ||
| 347 | 351 | ||
| 348 | card.appendChild(modelNameContainer); | 352 | card.appendChild(modelNameContainer); |
| 349 | card.appendChild(detailsContainer); | 353 | card.appendChild(detailsContainer); |
| 350 | 354 | ||
| 351 | // Append the card to the container | ||
| 352 | modelCardBlock.appendChild(card); | 355 | modelCardBlock.appendChild(card); |
| 353 | 356 | ||
| 354 | // Check if this card is the currently selected model | ||
| 355 | if (model.id === selectedModelId) { | 357 | if (model.id === selectedModelId) { |
| 356 | card.classList.add('selected'); // Keep the selected class if it's the same model | 358 | card.classList.add('selected'); |
| 357 | } | 359 | } |
| 358 | 360 | ||
| 359 | // Add click event listener to the card | ||
| 360 | card.addEventListener('click', function() { | 361 | card.addEventListener('click', function() { |
| 361 | // Remove the selected class from all other cards | ||
| 362 | document.querySelectorAll('.model-card').forEach(c => c.classList.remove('selected')); | 362 | document.querySelectorAll('.model-card').forEach(c => c.classList.remove('selected')); |
| 363 | |||
| 364 | // Add the selected class to the clicked card | ||
| 365 | card.classList.add('selected'); | 363 | card.classList.add('selected'); |
| 366 | |||
| 367 | // Call the onFeatherlessModelSelect function with the selected model ID | ||
| 368 | onFeatherlessModelSelect(model.id); | 364 | onFeatherlessModelSelect(model.id); |
| 369 | }); | 365 | }); |
| 370 | }); | 366 | }); |
| 367 | |||
| 368 | // Update the current page value whenever the page changes | ||
| 369 | currentPage = pagination.pageNumber; | ||
| 371 | }, | 370 | }, |
| 372 | afterSizeSelectorChange: function (e) { | 371 | afterSizeSelectorChange: function (e) { |
| 373 | const newPerPage = e.target.value; | 372 | const newPerPage = e.target.value; |
| 374 | localStorage.setItem('Models_PerPage', newPerPage); // Save the new value in localStorage | 373 | localStorage.setItem('Models_PerPage', newPerPage); |
| 375 | setupPagination(models, Number(newPerPage)); // Reinitialize pagination with the new per page value | 374 | setupPagination(models, Number(newPerPage), currentPage); // Use the stored current page number |
| 376 | }, | 375 | }, |
| 377 | }); | 376 | }); |
| 378 | } | 377 | } |
| 379 | 378 | ||
| 379 | |||
| 380 | |||
| 380 | // Add event listener for input on the search bar | 381 | // Add event listener for input on the search bar |
| 381 | searchBar.addEventListener('input', function() { | 382 | searchBar.addEventListener('input', function() { |
| 382 | applyFiltersAndSort(); | 383 | applyFiltersAndSort(); |
| @@ -399,6 +400,7 @@ export async function loadFeatherlessModels(data) { | |||
| 399 | // Function to populate class selection dropdown | 400 | // Function to populate class selection dropdown |
| 400 | function populateClassSelection(models) { | 401 | function populateClassSelection(models) { |
| 401 | const uniqueClasses = [...new Set(models.map(model => model.model_class).filter(Boolean))]; // Get unique class names | 402 | const uniqueClasses = [...new Set(models.map(model => model.model_class).filter(Boolean))]; // Get unique class names |
| 403 | uniqueClasses.sort((a, b) => a.localeCompare(b)); | ||
| 402 | uniqueClasses.forEach(className => { | 404 | uniqueClasses.forEach(className => { |
| 403 | const option = document.createElement('option'); | 405 | const option = document.createElement('option'); |
| 404 | option.value = className; | 406 | option.value = className; |
| @@ -420,7 +422,7 @@ export async function loadFeatherlessModels(data) { | |||
| 420 | featherlessTop = await fetchFeatherlessStats(); | 422 | featherlessTop = await fetchFeatherlessStats(); |
| 421 | } | 423 | } |
| 422 | const featherlessIds = featherlessTop.map(stat => stat.id); | 424 | const featherlessIds = featherlessTop.map(stat => stat.id); |
| 423 | if(selectedCategory === 'New') { | 425 | if (selectedCategory === 'New') { |
| 424 | featherlessNew = await fetchFeatherlessNew(); | 426 | featherlessNew = await fetchFeatherlessNew(); |
| 425 | } | 427 | } |
| 426 | const featherlessNewIds = featherlessNew.map(stat => stat.id); | 428 | const featherlessNewIds = featherlessNew.map(stat => stat.id); |
| @@ -445,7 +447,6 @@ export async function loadFeatherlessModels(data) { | |||
| 445 | } | 447 | } |
| 446 | }); | 448 | }); |
| 447 | 449 | ||
| 448 | // Sort the filtered models based on selected sort order (A-Z or Z-A) | ||
| 449 | if (selectedSortOrder === 'asc') { | 450 | if (selectedSortOrder === 'asc') { |
| 450 | filteredModels.sort((a, b) => a.id.localeCompare(b.id)); | 451 | filteredModels.sort((a, b) => a.id.localeCompare(b.id)); |
| 451 | } else if (selectedSortOrder === 'desc') { | 452 | } else if (selectedSortOrder === 'desc') { |
| @@ -456,9 +457,10 @@ export async function loadFeatherlessModels(data) { | |||
| 456 | filteredModels.sort((a, b) => b.updated_at.localeCompare(a.updated_at)); | 457 | filteredModels.sort((a, b) => b.updated_at.localeCompare(a.updated_at)); |
| 457 | } | 458 | } |
| 458 | 459 | ||
| 459 | // Reinitialize pagination with the filtered and sorted models | 460 | setupPagination(filteredModels, Number(localStorage.getItem(storageKey)) || perPage, currentPage); |
| 460 | setupPagination(filteredModels, Number(localStorage.getItem(storageKey)) || perPage); | ||
| 461 | } | 461 | } |
| 462 | |||
| 463 | |||
| 462 | } | 464 | } |
| 463 | 465 | ||
| 464 | async function fetchFeatherlessStats() { | 466 | async function fetchFeatherlessStats() { |
| @@ -480,15 +482,14 @@ function onFeatherlessModelSelect(modelId) { | |||
| 480 | textgen_settings.featherless_model = modelId; | 482 | textgen_settings.featherless_model = modelId; |
| 481 | $('#api_button_textgenerationwebui').trigger('click'); | 483 | $('#api_button_textgenerationwebui').trigger('click'); |
| 482 | setGenerationParamsFromPreset({ max_length: model.context_length }); | 484 | setGenerationParamsFromPreset({ max_length: model.context_length }); |
| 483 | toastr.info(`Selected model: ${modelId}`, '', { timeOut: 2000 }); | ||
| 484 | } | 485 | } |
| 485 | 486 | ||
| 486 | let isGridView = true; // Default state set to grid view | 487 | let isGridView = false; // Default state set to grid view |
| 487 | 488 | ||
| 488 | // Ensure the correct initial view is applied when the page loads | 489 | // Ensure the correct initial view is applied when the page loads |
| 489 | document.addEventListener('DOMContentLoaded', function() { | 490 | document.addEventListener('DOMContentLoaded', function() { |
| 490 | const modelCardBlock = document.getElementById('model_card_block'); | 491 | const modelCardBlock = document.getElementById('model_card_block'); |
| 491 | modelCardBlock.classList.add('grid-view'); | 492 | modelCardBlock.classList.add('list-view'); |
| 492 | 493 | ||
| 493 | const toggleButton = document.getElementById('model_grid_toggle'); | 494 | const toggleButton = document.getElementById('model_grid_toggle'); |
| 494 | toggleButton.addEventListener('click', function() { | 495 | toggleButton.addEventListener('click', function() { |
| @@ -5490,7 +5490,7 @@ body:not(.movingUI) .drawer-content.maximized { | |||
| 5490 | display: flex; | 5490 | display: flex; |
| 5491 | justify-content: space-between; | 5491 | justify-content: space-between; |
| 5492 | align-items: center; | 5492 | align-items: center; |
| 5493 | padding: 15px; | 5493 | padding: 5px; |
| 5494 | border: 1px solid #333; | 5494 | border: 1px solid #333; |
| 5495 | border-radius: 8px; | 5495 | border-radius: 8px; |
| 5496 | background-color: #222; | 5496 | background-color: #222; |
| @@ -5502,7 +5502,7 @@ body:not(.movingUI) .drawer-content.maximized { | |||
| 5502 | } | 5502 | } |
| 5503 | 5503 | ||
| 5504 | .model-card:hover { | 5504 | .model-card:hover { |
| 5505 | transform: scale(1.02); | 5505 | transform: scale(1.01); |
| 5506 | background-color: #444; | 5506 | background-color: #444; |
| 5507 | transition: transform 0.2s ease-in-out, background-color 0.2s ease-in-out; /* Smooth transition */ | 5507 | transition: transform 0.2s ease-in-out, background-color 0.2s ease-in-out; /* Smooth transition */ |
| 5508 | } | 5508 | } |
| @@ -5520,7 +5520,7 @@ body:not(.movingUI) .drawer-content.maximized { | |||
| 5520 | } | 5520 | } |
| 5521 | 5521 | ||
| 5522 | .model-title { | 5522 | .model-title { |
| 5523 | font-size: --mainFontSize; | 5523 | font-size: 13px; |
| 5524 | font-weight: bold; | 5524 | font-weight: bold; |
| 5525 | overflow: hidden; | 5525 | overflow: hidden; |
| 5526 | } | 5526 | } |
| @@ -5533,11 +5533,11 @@ body:not(.movingUI) .drawer-content.maximized { | |||
| 5533 | min-width: 120px; | 5533 | min-width: 120px; |
| 5534 | } | 5534 | } |
| 5535 | 5535 | ||
| 5536 | .model-class, .model-context-length { | 5536 | .model-class, .model-context-length, .model-date-added { |
| 5537 | font-size: calc(--mainFontSize - 3); | 5537 | font-size: 10px; |
| 5538 | } | 5538 | } |
| 5539 | 5539 | ||
| 5540 | .model-class { | 5540 | .model-class, .model-context-length { |
| 5541 | margin-bottom: 5px; | 5541 | margin-bottom: 5px; |
| 5542 | } | 5542 | } |
| 5543 | 5543 | ||
| @@ -5545,7 +5545,7 @@ body:not(.movingUI) .drawer-content.maximized { | |||
| 5545 | grid-template-columns: repeat(2, 1fr); | 5545 | grid-template-columns: repeat(2, 1fr); |
| 5546 | display: flex; | 5546 | display: flex; |
| 5547 | flex-wrap: wrap; | 5547 | flex-wrap: wrap; |
| 5548 | gap: 5px; | 5548 | /* gap: 3px; */ |
| 5549 | justify-content: flex-start; | 5549 | justify-content: flex-start; |
| 5550 | } | 5550 | } |
| 5551 | 5551 | ||
| @@ -5586,7 +5586,7 @@ body:not(.movingUI) .drawer-content.maximized { | |||
| 5586 | align-items: stretch; | 5586 | align-items: stretch; |
| 5587 | } | 5587 | } |
| 5588 | 5588 | ||
| 5589 | .model-info, .model-details { | 5589 | .model-info, .model-details, .model-date-added { |
| 5590 | width: 100%; | 5590 | width: 100%; |
| 5591 | text-align: left; | 5591 | text-align: left; |
| 5592 | } | 5592 | } |
| @@ -5595,7 +5595,4 @@ body:not(.movingUI) .drawer-content.maximized { | |||
| 5595 | width: 100%; | 5595 | width: 100%; |
| 5596 | } | 5596 | } |
| 5597 | 5597 | ||
| 5598 | #model_sort_order, #model_grid_toggle { | ||
| 5599 | margin-top: 10px; | ||
| 5600 | } | ||
| 5601 | } | 5598 | } |