mirror of
				https://github.com/SillyTavern/SillyTavern.git
				synced 2025-06-05 21:59:27 +02:00 
			
		
		
		
	Add filters to data bank manager
This commit is contained in:
		| @@ -620,11 +620,38 @@ async function deleteAttachment(attachment, source, callback) { | ||||
|  */ | ||||
| async function openAttachmentManager() { | ||||
|     /** | ||||
|      * | ||||
|      * Renders a list of attachments. | ||||
|      * @param {FileAttachment[]} attachments List of attachments | ||||
|      * @param {string} source Source of the attachments | ||||
|      */ | ||||
|     async function renderList(attachments, source) { | ||||
|         /** | ||||
|          * Sorts attachments by sortField and sortOrder. | ||||
|          * @param {FileAttachment} a First attachment | ||||
|          * @param {FileAttachment} b Second attachment | ||||
|          * @returns {number} Sort order | ||||
|          */ | ||||
|         function sortFn(a, b) { | ||||
|             const sortValueA = a[sortField]; | ||||
|             const sortValueB = b[sortField]; | ||||
|             if (typeof sortValueA === 'string' && typeof sortValueB === 'string') { | ||||
|                 return sortValueA.localeCompare(sortValueB) * (sortOrder === 'asc' ? 1 : -1); | ||||
|             } | ||||
|             return (sortValueA - sortValueB) * (sortOrder === 'asc' ? 1 : -1); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Filters attachments by name. | ||||
|          * @param {FileAttachment} a Attachment | ||||
|          * @returns {boolean} True if attachment matches the filter, false otherwise. | ||||
|          */ | ||||
|         function filterFn(a) { | ||||
|             if (!filterString) { | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             return a.name.toLowerCase().includes(filterString.toLowerCase()); | ||||
|         } | ||||
|         const sources = { | ||||
|             [ATTACHMENT_SOURCE.GLOBAL]: '.globalAttachmentsList', | ||||
|             [ATTACHMENT_SOURCE.CHARACTER]: '.characterAttachmentsList', | ||||
| @@ -632,16 +659,37 @@ async function openAttachmentManager() { | ||||
|         }; | ||||
|  | ||||
|         template.find(sources[source]).empty(); | ||||
|         for (const attachment of attachments) { | ||||
|  | ||||
|         // Sort attachments by sortField and sortOrder, and apply filter | ||||
|         const sortedAttachmentList = attachments.slice().filter(filterFn).sort(sortFn); | ||||
|  | ||||
|         for (const attachment of sortedAttachmentList) { | ||||
|             const attachmentTemplate = template.find('.attachmentListItemTemplate .attachmentListItem').clone(); | ||||
|             attachmentTemplate.find('.attachmentListItemName').text(attachment.name); | ||||
|             attachmentTemplate.find('.attachmentListItemSize').text(humanFileSize(attachment.size)); | ||||
|             attachmentTemplate.find('.attachmentListItemCreated').text(new Date(attachment.created).toLocaleString()); | ||||
|             attachmentTemplate.find('.viewAttachmentButton').on('click', () => openFilePopup(attachment)); | ||||
|             attachmentTemplate.find('.deleteAttachmentButton').on('click', () => deleteAttachment(attachment, source, renderAttachments)); | ||||
|             template.find(sources[source]).append(attachmentTemplate); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Renders buttons for the attachment manager. | ||||
|      * @param {string} source Source of the buttons | ||||
|      */ | ||||
|     function renderButtons(source) { | ||||
|         const sources = { | ||||
|             [ATTACHMENT_SOURCE.GLOBAL]: '.globalAttachmentsTitle', | ||||
|             [ATTACHMENT_SOURCE.CHARACTER]: '.characterAttachmentsTitle', | ||||
|             [ATTACHMENT_SOURCE.CHAT]: '.chatAttachmentsTitle', | ||||
|         }; | ||||
|  | ||||
|         const buttonsList = template.find('.actionButtonsTemplate .actionButtons').clone(); | ||||
|         buttonsList.find('.menu_button').data('attachment-manager-target', source); | ||||
|         template.find(sources[source]).append(buttonsList); | ||||
|     } | ||||
|  | ||||
|     async function renderAttachments() { | ||||
|         /** @type {FileAttachment[]} */ | ||||
|         const globalAttachments = extension_settings.attachments ?? []; | ||||
| @@ -666,8 +714,14 @@ async function openAttachmentManager() { | ||||
|         template.find('.chatAttachmentsName').text(chatName); | ||||
|     } | ||||
|  | ||||
|     let sortField = localStorage.getItem('DataBank_sortField') || 'created'; | ||||
|     let sortOrder = localStorage.getItem('DataBank_sortOrder') || 'desc'; | ||||
|     let filterString = ''; | ||||
|     const hasFandomPlugin = await isFandomPluginAvailable(); | ||||
|     const template = $(await renderExtensionTemplateAsync('attachments', 'manager', {})); | ||||
|     renderButtons(ATTACHMENT_SOURCE.GLOBAL); | ||||
|     renderButtons(ATTACHMENT_SOURCE.CHARACTER); | ||||
|     renderButtons(ATTACHMENT_SOURCE.CHAT); | ||||
|     template.find('.scrapeWebpageButton').on('click', function () { | ||||
|         openWebpageScraper(String($(this).data('attachment-manager-target')), renderAttachments); | ||||
|     }); | ||||
| @@ -677,6 +731,21 @@ async function openAttachmentManager() { | ||||
|     template.find('.uploadFileButton').on('click', function () { | ||||
|         openFileUploader(String($(this).data('attachment-manager-target')), renderAttachments); | ||||
|     }); | ||||
|     template.find('.attachmentSearch').on('input', function () { | ||||
|         filterString = String($(this).val()); | ||||
|         renderAttachments(); | ||||
|     }); | ||||
|     template.find('.attachmentSort').on('change', function () { | ||||
|         if (!(this instanceof HTMLSelectElement) || this.selectedOptions.length === 0)  { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         sortField = this.selectedOptions[0].dataset.sortField; | ||||
|         sortOrder = this.selectedOptions[0].dataset.sortOrder; | ||||
|         localStorage.setItem('DataBank_sortField', sortField); | ||||
|         localStorage.setItem('DataBank_sortOrder', sortOrder); | ||||
|         renderAttachments(); | ||||
|     }); | ||||
|     await renderAttachments(); | ||||
|     callGenericPopup(template, POPUP_TYPE.TEXT, '', { wide: true, large: true, okButton: 'Close' }); | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| <div class="wide100p paddingTopBot5"> | ||||
| <div class="wide100p padding5"> | ||||
|     <h2 class="marginBot5"> | ||||
|         <span data-i18n="Data Bank"> | ||||
|             Data Bank | ||||
| @@ -10,31 +10,35 @@ | ||||
|     <div data-i18n="Supported file types: Plain Text, PDF, Markdown, HTML." class="marginTopBot5"> | ||||
|         Supported file types: Plain Text, PDF, Markdown, HTML. | ||||
|     </div> | ||||
|     <div class="flex-container marginTopBot5"> | ||||
|         <input type="search" id="attachmentSearch" class="attachmentSearch text_pole margin0 flex1" placeholder="Search..."> | ||||
|         <select id="attachmentSort" class="attachmentSort text_pole margin0 flex1"> | ||||
|             <option data-sort-field="created" data-sort-order="desc" data-i18n="Date (Newest First)"> | ||||
|                 Date (Newest First) | ||||
|             </option> | ||||
|             <option data-sort-field="created" data-sort-order="asc" data-i18n="Date (Oldest First)"> | ||||
|                 Date (Oldest First) | ||||
|             </option> | ||||
|             <option data-sort-field="name" data-sort-order="asc" data-i18n="Name (A-Z)"> | ||||
|                 Name (A-Z) | ||||
|             </option> | ||||
|             <option data-sort-field="name" data-sort-order="desc" data-i18n="Name (Z-A)"> | ||||
|                 Name (Z-A) | ||||
|             </option> | ||||
|             <option data-sort-field="size" data-sort-order="asc" data-i18n="Size (Smallest First)"> | ||||
|                 Size (Smallest First) | ||||
|             </option> | ||||
|             <option data-sort-field="size" data-sort-order="desc" data-i18n="Size (Largest First)"> | ||||
|                 Size (Largest First) | ||||
|             </option> | ||||
|         </select> | ||||
|  | ||||
|     </div> | ||||
|     <div class="justifyLeft globalAttachmentsBlock marginBot10"> | ||||
|         <h3 class="margin0 title_restorable"> | ||||
|         <h3 class="globalAttachmentsTitle margin0 title_restorable"> | ||||
|             <span data-i18n="Global Attachments"> | ||||
|                 Global Attachments | ||||
|             </span> | ||||
|             <div class="flex-container flexGap10"> | ||||
|                 <div class="scrapeWebpageButton menu_button_icon menu_button" data-attachment-manager-target="global" title="Download a page from the web."> | ||||
|                     <i class="fa-fw fa-solid fa-globe"></i> | ||||
|                     <span data-i18n="From Web"> | ||||
|                         From Web | ||||
|                     </span> | ||||
|                 </div> | ||||
|                 <div class="scrapeFandomButton menu_button_icon menu_button" data-attachment-manager-target="global" title="Download a page from the Fandom wiki."> | ||||
|                     <i class="fa-fw fa-solid fa-fire"></i> | ||||
|                     <span data-i18n="From Fandom"> | ||||
|                         From Fandom | ||||
|                     </span> | ||||
|                 </div> | ||||
|                 <div class="uploadFileButton menu_button_icon menu_button" data-attachment-manager-target="global" title="Upload a file from your computer."> | ||||
|                     <i class="fa-fw fa-solid fa-upload"></i> | ||||
|                     <span data-i18n="From File"> | ||||
|                         From File | ||||
|                     </span> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </h3> | ||||
|         <small data-i18n="These files are available for all characters in all chats."> | ||||
|             These files are available for all characters in all chats. | ||||
| @@ -43,30 +47,10 @@ | ||||
|         <hr> | ||||
|     </div> | ||||
|     <div class="justifyLeft characterAttachmentsBlock marginBot10"> | ||||
|         <h3 class="margin0 title_restorable"> | ||||
|         <h3 class="characterAttachmentsTitle margin0 title_restorable"> | ||||
|             <span data-i18n="Character Attachments"> | ||||
|                 Character Attachments | ||||
|             </span> | ||||
|             <div class="flex-container flexGap10"> | ||||
|                 <div class="scrapeWebpageButton menu_button_icon menu_button" data-attachment-manager-target="character" title="Download a page from the web."> | ||||
|                     <i class="fa-fw fa-solid fa-globe"></i> | ||||
|                     <span data-i18n="From Web"> | ||||
|                         From Web | ||||
|                     </span> | ||||
|                 </div> | ||||
|                 <div class="scrapeFandomButton menu_button_icon menu_button" data-attachment-manager-target="character" title="Download a page from the Fandom wiki."> | ||||
|                     <i class="fa-fw fa-solid fa-fire"></i> | ||||
|                     <span data-i18n="From Fandom"> | ||||
|                         From Fandom | ||||
|                     </span> | ||||
|                 </div> | ||||
|                 <div class="uploadFileButton menu_button_icon menu_button" data-attachment-manager-target="character" title="Upload a file from your computer."> | ||||
|                     <i class="fa-fw fa-solid fa-upload"></i> | ||||
|                     <span data-i18n="From File"> | ||||
|                         From File | ||||
|                     </span> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </h3> | ||||
|         <div class="flex-container flexFlowColumn"> | ||||
|             <strong><small class="characterAttachmentsName"></small></strong> | ||||
| @@ -78,30 +62,10 @@ | ||||
|         <hr> | ||||
|     </div> | ||||
|     <div class="justifyLeft chatAttachmentsBlock marginBot10"> | ||||
|         <h3 class="margin0 title_restorable"> | ||||
|         <h3 class="chatAttachmentsTitle margin0 title_restorable"> | ||||
|             <span data-i18n="Chat Attachments"> | ||||
|                 Chat Attachments | ||||
|             </span> | ||||
|             <div class="flex-container flexGap10"> | ||||
|                 <div class="scrapeWebpageButton menu_button_icon menu_button" data-attachment-manager-target="chat" title="Download a page from the web."> | ||||
|                     <i class="fa-fw fa-solid fa-globe"></i> | ||||
|                     <span data-i18n="From Web"> | ||||
|                         From Web | ||||
|                     </span> | ||||
|                 </div> | ||||
|                 <div class="scrapeFandomButton menu_button_icon menu_button" data-attachment-manager-target="chat" title="Download a page from the Fandom wiki."> | ||||
|                     <i class="fa-fw fa-solid fa-fire"></i> | ||||
|                     <span data-i18n="From Fandom"> | ||||
|                         From Fandom | ||||
|                     </span> | ||||
|                 </div> | ||||
|                 <div class="uploadFileButton menu_button_icon menu_button" data-attachment-manager-target="chat" title="Upload a file from your computer."> | ||||
|                     <i class="fa-fw fa-solid fa-upload"></i> | ||||
|                     <span data-i18n="From File"> | ||||
|                         From File | ||||
|                     </span> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </h3> | ||||
|         <div class="flex-container flexFlowColumn"> | ||||
|             <strong><small class="chatAttachmentsName"></small></strong> | ||||
| @@ -116,9 +80,33 @@ | ||||
|         <div class="attachmentListItem flex-container alignItemsCenter flexGap10"> | ||||
|             <div class="attachmentFileIcon fa-solid fa-file-alt"></div> | ||||
|             <div class="attachmentListItemName flex1"></div> | ||||
|             <small class="attachmentListItemCreated"></small> | ||||
|             <small class="attachmentListItemSize"></small> | ||||
|             <div class="viewAttachmentButton right_menu_button fa-solid fa-magnifying-glass" title="View attachment content"></div> | ||||
|             <div class="deleteAttachmentButton right_menu_button fa-solid fa-trash" title="Delete attachment"></div> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     <div class="actionButtonsTemplate template_element"> | ||||
|         <div class="actionButtons flex-container flexGap10"> | ||||
|             <div class="scrapeWebpageButton menu_button_icon menu_button" data-attachment-manager-target="" title="Download a page from the web."> | ||||
|                 <i class="fa-fw fa-solid fa-globe"></i> | ||||
|                 <span data-i18n="From Web"> | ||||
|                     From Web | ||||
|                 </span> | ||||
|             </div> | ||||
|             <div class="scrapeFandomButton menu_button_icon menu_button" data-attachment-manager-target="" title="Download a page from the Fandom wiki."> | ||||
|             <i class="fa-fw fa-solid fa-fire"></i> | ||||
|                 <span data-i18n="From Fandom"> | ||||
|                     From Fandom | ||||
|                 </span> | ||||
|             </div> | ||||
|             <div class="uploadFileButton menu_button_icon menu_button" data-attachment-manager-target="" title="Upload a file from your computer."> | ||||
|                 <i class="fa-fw fa-solid fa-upload"></i> | ||||
|                 <span data-i18n="From File"> | ||||
|                     From File | ||||
|                 </span> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
|   | ||||
| @@ -18,3 +18,12 @@ | ||||
| .attachmentListItem { | ||||
|     padding: 10px; | ||||
| } | ||||
|  | ||||
| .attachmentListItemSize { | ||||
|     min-width: 4em; | ||||
|     text-align: right; | ||||
| } | ||||
|  | ||||
| .attachmentListItemCreated { | ||||
|     text-align: right; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user