From e2f8c876d96b34381078813586bfc01e931ff45f Mon Sep 17 00:00:00 2001 From: maver Date: Sat, 3 Jun 2023 18:13:05 +0200 Subject: [PATCH] Refactor render functions of prompt manager Improve readability and extendability --- public/scripts/PromptManager.js | 283 ++++++++++++-------------------- 1 file changed, 101 insertions(+), 182 deletions(-) diff --git a/public/scripts/PromptManager.js b/public/scripts/PromptManager.js index 6bad6019f..7a48d3e24 100644 --- a/public/scripts/PromptManager.js +++ b/public/scripts/PromptManager.js @@ -448,224 +448,143 @@ PromptManagerModule.prototype.getChatCompletion = function () { return chatCompletion; } -// Empties, then re-assembles the container cointaining the prompt list. +// Empties, then re-assembles the container containing the prompt list. PromptManagerModule.prototype.renderPromptManager = function () { const promptManagerDiv = this.containerElement; promptManagerDiv.innerHTML = ''; - const rangeBlockTitleDiv = document.createElement('div'); - rangeBlockTitleDiv.classList.add('range-block-title'); - rangeBlockTitleDiv.textContent = 'Prompts '; + const showAdvancedSettings = this.serviceSettings.prompt_manager_settings.showAdvancedSettings; + const checkSpanClass = showAdvancedSettings ? 'fa-solid fa-toggle-on' : 'fa-solid fa-toggle-off'; - const notesLink = document.createElement('a'); - notesLink.href = '/notes#openaipromptmanager'; - notesLink.setAttribute('target', '_blank'); - notesLink.classList.add('notes-link'); + promptManagerDiv.insertAdjacentHTML('beforeend', ` +
+ Prompts + + ? + +
+
+
+
+ + Show advanced options +
+
Total Tokens: ${this.totalActiveTokens}
+
+ +
+ `); - const noteLinkSpan = document.createElement('span'); - noteLinkSpan.classList.add('note-link-span'); - noteLinkSpan.textContent = '?'; - - notesLink.appendChild(noteLinkSpan); - rangeBlockTitleDiv.appendChild(notesLink); - promptManagerDiv.appendChild(rangeBlockTitleDiv); - - const rangeBlockDiv = document.createElement('div'); - rangeBlockDiv.classList.add('range-block'); - - const promptManagerHeaderDiv = document.createElement('div'); - promptManagerHeaderDiv.classList.add(this.configuration.prefix + 'prompt_manager_header'); - - const advancedDiv = document.createElement('div'); - advancedDiv.classList.add(this.configuration.prefix + 'prompt_manager_header_advanced'); - - const checkLabelSpan = document.createElement('span'); - checkLabelSpan.classList.add('checkbox_label'); - checkLabelSpan.textContent = 'Show advanced options'; - - const checkSpan = document.createElement('span'); - if (true === this.serviceSettings.prompt_manager_settings.showAdvancedSettings) - checkSpan.classList.add('fa-solid', 'fa-toggle-on'); - else checkSpan.classList.add('fa-solid', 'fa-toggle-off'); + const checkSpan = promptManagerDiv.querySelector(`.${this.configuration.prefix}prompt_manager_header_advanced span`); checkSpan.addEventListener('click', this.handleAdvancedSettingsToggle); - advancedDiv.append(checkSpan); - advancedDiv.append(checkLabelSpan); - - const tokensDiv = document.createElement('div'); - tokensDiv.textContent = 'Total Tokens: ' + this.totalActiveTokens; - - promptManagerHeaderDiv.appendChild(advancedDiv); - promptManagerHeaderDiv.appendChild(tokensDiv); - rangeBlockDiv.appendChild(promptManagerHeaderDiv); - - const promptManagerList = document.createElement('ul'); - promptManagerList.id = this.configuration.prefix + 'prompt_manager_list'; - promptManagerList.classList.add('text_pole'); - - rangeBlockDiv.appendChild(promptManagerList); - this.listElement = promptManagerList; + this.listElement = promptManagerDiv.querySelector(`#${this.configuration.prefix}prompt_manager_list`); if (null !== this.activeCharacter) { - const promptManagerFooterDiv = document.createElement('div'); - promptManagerFooterDiv.classList.add(this.configuration.prefix + 'prompt_manager_footer'); - - // Create a list of prompts to add to the current character - const selectElement = document.createElement('select'); - selectElement.id = this.configuration.prefix + 'prompt_manager_footer_append_prompt'; - selectElement.classList.add('text_pole'); - selectElement.name = 'append-prompt'; - - // Create a prompt copy, sort them alphabetically and generate the prompt options. - [...this.serviceSettings.prompts] + const prompts = [...this.serviceSettings.prompts] .filter(prompt => !prompt.system_prompt) .sort((promptA, promptB) => promptA.name.localeCompare(promptB.name)) - .forEach((prompt) => { - const option = document.createElement('option'); - option.value = prompt.identifier; - option.textContent = prompt.name; + .reduce((acc, prompt) => acc + ``, ''); - selectElement.append(option); - }); + const footerHtml = ` + + `; - // Append an existing prompt to the list - const appendPromptLink = document.createElement('a'); - appendPromptLink.classList.add('menu_button'); - appendPromptLink.textContent = 'Add'; - appendPromptLink.addEventListener('click', this.handleAppendPrompt); + const rangeBlockDiv = promptManagerDiv.querySelector('.range-block'); + rangeBlockDiv.insertAdjacentHTML('beforeend', footerHtml); - // Delete an existing prompt from the settings - const deletePromptLink = document.createElement('a'); - deletePromptLink.classList.add('caution', 'menu_button'); - deletePromptLink.textContent = 'Delete'; - deletePromptLink.addEventListener('click', this.handleDeletePrompt); - - // Create a new prompt - const newPromptLink = document.createElement('a'); - newPromptLink.classList.add('menu_button'); - newPromptLink.textContent = 'New'; - newPromptLink.addEventListener('click', this.handleNewPrompt); - - promptManagerFooterDiv.append(selectElement); - promptManagerFooterDiv.append(appendPromptLink); - promptManagerFooterDiv.append(deletePromptLink); - promptManagerFooterDiv.append(newPromptLink); - - rangeBlockDiv.appendChild(promptManagerFooterDiv); + const footerDiv = rangeBlockDiv.querySelector(`.${this.configuration.prefix}prompt_manager_footer`); + footerDiv.querySelector('.menu_button:nth-child(2)').addEventListener('click', this.handleAppendPrompt); + footerDiv.querySelector('.caution').addEventListener('click', this.handleDeletePrompt); + footerDiv.querySelector('.menu_button:last-child').addEventListener('click', this.handleNewPrompt); } - - promptManagerDiv.appendChild(rangeBlockDiv); }; // Empties, then re-assembles the prompt list. PromptManagerModule.prototype.renderPromptManagerListItems = function () { if (!this.serviceSettings.prompts) return; - const promptManagerList = this.listElement + const promptManagerList = this.listElement; promptManagerList.innerHTML = ''; - const promptManagerListHead = document.createElement('li'); - promptManagerListHead.classList.add(this.configuration.prefix + 'prompt_manager_list_head'); + const { prefix } = this.configuration; - const nameSpan = document.createElement('span'); - nameSpan.textContent = 'Name'; - - const tokensSpan = document.createElement('span'); - tokensSpan.classList.add('prompt_manager_prompt_tokens'); - tokensSpan.textContent = 'Tokens'; - - promptManagerListHead.appendChild(nameSpan); - promptManagerListHead.appendChild(document.createElement('span')); - promptManagerListHead.appendChild(tokensSpan); - - promptManagerList.appendChild(promptManagerListHead); - - const promptManagerListSeparator = document.createElement('li'); - promptManagerListSeparator.classList.add(this.configuration.prefix + 'prompt_manager_list_separator'); - - const hrElement = document.createElement('hr'); - promptManagerListSeparator.appendChild(hrElement); + let listItemHtml = ` +
  • + Name + + Tokens +
  • +
  • +
    +
  • + `; this.getPromptsForCharacter(this.activeCharacter).forEach(prompt => { - // Marker offer almost no interaction except being draggable. const advancedEnabled = this.serviceSettings.prompt_manager_settings.showAdvancedSettings; let draggableEnabled = true; - if (true === prompt.system_prompt && false === advancedEnabled) draggableEnabled = false; + if (prompt.system_prompt && !advancedEnabled) draggableEnabled = false; - if (prompt.marker) { - if (prompt.identifier !== 'newMainChat' && - prompt.identifier !== 'chatHistory' && - false === advancedEnabled) return; - } - - const listItem = document.createElement('li'); - listItem.classList.add(this.configuration.prefix + 'prompt_manager_prompt'); - if (true === draggableEnabled) listItem.classList.add('draggable'); - - if (prompt.marker) listItem.classList.add(this.configuration.prefix + 'prompt_manager_marker'); + if (prompt.marker && + prompt.identifier !== 'newMainChat' && + prompt.identifier !== 'chatHistory' && + !advancedEnabled) return; const listEntry = this.getPromptListEntry(this.activeCharacter, prompt.identifier); - if (false === listEntry.enabled) listItem.classList.add(this.configuration.prefix + 'prompt_manager_prompt_disabled'); - listItem.classList.add('dropAllowed'); - listItem.setAttribute('draggable', String(draggableEnabled)); - listItem.setAttribute('data-pm-identifier', prompt.identifier); + const enabledClass = listEntry.enabled ? '' : `${prefix}prompt_manager_prompt_disabled`; + const draggableClass = draggableEnabled ? 'draggable' : ''; + const markerClass = prompt.marker ? `${prefix}prompt_manager_marker` : ''; + const calculatedTokens = prompt.calculated_tokens ? prompt.calculated_tokens : '-'; - const nameSpan = document.createElement('span'); - nameSpan.setAttribute('data-pm-name', prompt.name); - - if (prompt.marker) { - const markerIconSpan = document.createElement('span'); - markerIconSpan.classList.add('fa-solid', 'fa-thumb-tack'); - nameSpan.appendChild(markerIconSpan); + let detachSpanHtml = ''; + if (this.isPromptDeletionAllowed(prompt)) { + detachSpanHtml = ` + + `; } - const nameTextSpan = document.createElement('span'); - nameTextSpan.textContent = prompt.name; - nameSpan.appendChild(nameTextSpan); - - const tokensSpan = document.createElement('span'); - tokensSpan.classList.add('prompt_manager_prompt_tokens') - tokensSpan.setAttribute('data-pm-tokens', prompt.calculated_tokens); - tokensSpan.textContent = prompt.calculated_tokens ? prompt.calculated_tokens : '-'; - - const actionsSpan = document.createElement('span'); - actionsSpan.classList.add('prompt_manager_prompt_controls'); - - // Don't add delete control to system prompts - if (true === this.isPromptDeletionAllowed(prompt)) { - const detachSpan = document.createElement('span'); - detachSpan.title = 'delete'; - detachSpan.classList.add('caution', 'fa-solid', 'fa-x'); - - detachSpan.addEventListener('click', this.handleDetach); - actionsSpan.appendChild(detachSpan); - } - - const editSpan = document.createElement('span'); - editSpan.title = 'edit'; - editSpan.classList.add('fa-solid', 'fa-pencil'); - editSpan.addEventListener('click', this.handleEdit) - - const checkSpan = document.createElement('span'); - if (true === listEntry.enabled) checkSpan.classList.add('fa-solid', 'fa-toggle-on'); - else checkSpan.classList.add('fa-solid', 'fa-toggle-off'); - - checkSpan.addEventListener('click', this.handleToggle); - - actionsSpan.appendChild(editSpan); - actionsSpan.appendChild(checkSpan); - - const controlSpan = document.createElement('span'); - controlSpan.append(actionsSpan); - - listItem.appendChild(nameSpan); - if (prompt.marker) listItem.appendChild(document.createElement('span')); - else listItem.appendChild(controlSpan); - listItem.appendChild(tokensSpan); - - promptManagerList.appendChild(listItem); + listItemHtml += ` +
  • + + ${prompt.marker ? '' : ''} + ${prompt.name} + + ${prompt.marker ? '' : ` + + + ${detachSpanHtml} + + + + + `} + ${calculatedTokens} +
  • + `; }); -} + + promptManagerList.insertAdjacentHTML('beforeend', listItemHtml); + + // Now that the new elements are in the DOM, you can add the event listeners. + Array.from(promptManagerList.getElementsByClassName('fa-x')).forEach(el => { + el.addEventListener('click', this.handleDetach); + }); + + Array.from(promptManagerList.getElementsByClassName('fa-pencil')).forEach(el => { + el.addEventListener('click', this.handleEdit); + }); + + Array.from(promptManagerList.querySelectorAll('.prompt_manager_prompt_controls span:last-child')).forEach(el => { + el.addEventListener('click', this.handleToggle); + }); +}; // Makes the prompt list draggable and handles swapping of two entries in the list. PromptManagerModule.prototype.makeDraggable = function () {