Refactor render functions of prompt manager

Improve readability and extendability
This commit is contained in:
maver 2023-06-03 18:13:05 +02:00
parent 137b979302
commit e2f8c876d9
1 changed files with 101 additions and 182 deletions

View File

@ -448,224 +448,143 @@ PromptManagerModule.prototype.getChatCompletion = function () {
return chatCompletion; 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 () { PromptManagerModule.prototype.renderPromptManager = function () {
const promptManagerDiv = this.containerElement; const promptManagerDiv = this.containerElement;
promptManagerDiv.innerHTML = ''; promptManagerDiv.innerHTML = '';
const rangeBlockTitleDiv = document.createElement('div'); const showAdvancedSettings = this.serviceSettings.prompt_manager_settings.showAdvancedSettings;
rangeBlockTitleDiv.classList.add('range-block-title'); const checkSpanClass = showAdvancedSettings ? 'fa-solid fa-toggle-on' : 'fa-solid fa-toggle-off';
rangeBlockTitleDiv.textContent = 'Prompts ';
const notesLink = document.createElement('a'); promptManagerDiv.insertAdjacentHTML('beforeend', `
notesLink.href = '/notes#openaipromptmanager'; <div class="range-block-title">
notesLink.setAttribute('target', '_blank'); Prompts
notesLink.classList.add('notes-link'); <a href="/notes#openaipromptmanager" target="_blank" class="notes-link">
<span class="note-link-span">?</span>
</a>
</div>
<div class="range-block">
<div class="${this.configuration.prefix}prompt_manager_header">
<div class="${this.configuration.prefix}prompt_manager_header_advanced">
<span class="${checkSpanClass}"></span>
<span class="checkbox_label">Show advanced options</span>
</div>
<div>Total Tokens: ${this.totalActiveTokens}</div>
</div>
<ul id="${this.configuration.prefix}prompt_manager_list" class="text_pole"></ul>
</div>
`);
const noteLinkSpan = document.createElement('span'); const checkSpan = promptManagerDiv.querySelector(`.${this.configuration.prefix}prompt_manager_header_advanced 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');
checkSpan.addEventListener('click', this.handleAdvancedSettingsToggle); checkSpan.addEventListener('click', this.handleAdvancedSettingsToggle);
advancedDiv.append(checkSpan); this.listElement = promptManagerDiv.querySelector(`#${this.configuration.prefix}prompt_manager_list`);
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;
if (null !== this.activeCharacter) { if (null !== this.activeCharacter) {
const promptManagerFooterDiv = document.createElement('div'); const prompts = [...this.serviceSettings.prompts]
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]
.filter(prompt => !prompt.system_prompt) .filter(prompt => !prompt.system_prompt)
.sort((promptA, promptB) => promptA.name.localeCompare(promptB.name)) .sort((promptA, promptB) => promptA.name.localeCompare(promptB.name))
.forEach((prompt) => { .reduce((acc, prompt) => acc + `<option value="${prompt.identifier}">${prompt.name}</option>`, '');
const option = document.createElement('option');
option.value = prompt.identifier;
option.textContent = prompt.name;
selectElement.append(option); const footerHtml = `
}); <div class="${this.configuration.prefix}prompt_manager_footer">
<select id="${this.configuration.prefix}prompt_manager_footer_append_prompt" class="text_pole" name="append-prompt">
${prompts}
</select>
<a class="menu_button">Add</a>
<a class="caution menu_button">Delete</a>
<a class="menu_button">New</a>
</div>
`;
// Append an existing prompt to the list const rangeBlockDiv = promptManagerDiv.querySelector('.range-block');
const appendPromptLink = document.createElement('a'); rangeBlockDiv.insertAdjacentHTML('beforeend', footerHtml);
appendPromptLink.classList.add('menu_button');
appendPromptLink.textContent = 'Add';
appendPromptLink.addEventListener('click', this.handleAppendPrompt);
// Delete an existing prompt from the settings const footerDiv = rangeBlockDiv.querySelector(`.${this.configuration.prefix}prompt_manager_footer`);
const deletePromptLink = document.createElement('a'); footerDiv.querySelector('.menu_button:nth-child(2)').addEventListener('click', this.handleAppendPrompt);
deletePromptLink.classList.add('caution', 'menu_button'); footerDiv.querySelector('.caution').addEventListener('click', this.handleDeletePrompt);
deletePromptLink.textContent = 'Delete'; footerDiv.querySelector('.menu_button:last-child').addEventListener('click', this.handleNewPrompt);
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);
} }
promptManagerDiv.appendChild(rangeBlockDiv);
}; };
// Empties, then re-assembles the prompt list. // Empties, then re-assembles the prompt list.
PromptManagerModule.prototype.renderPromptManagerListItems = function () { PromptManagerModule.prototype.renderPromptManagerListItems = function () {
if (!this.serviceSettings.prompts) return; if (!this.serviceSettings.prompts) return;
const promptManagerList = this.listElement const promptManagerList = this.listElement;
promptManagerList.innerHTML = ''; promptManagerList.innerHTML = '';
const promptManagerListHead = document.createElement('li'); const { prefix } = this.configuration;
promptManagerListHead.classList.add(this.configuration.prefix + 'prompt_manager_list_head');
const nameSpan = document.createElement('span'); let listItemHtml = `
nameSpan.textContent = 'Name'; <li class="${prefix}prompt_manager_list_head">
<span>Name</span>
const tokensSpan = document.createElement('span'); <span></span>
tokensSpan.classList.add('prompt_manager_prompt_tokens'); <span class="prompt_manager_prompt_tokens">Tokens</span>
tokensSpan.textContent = 'Tokens'; </li>
<li class="${prefix}prompt_manager_list_separator">
promptManagerListHead.appendChild(nameSpan); <hr>
promptManagerListHead.appendChild(document.createElement('span')); </li>
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);
this.getPromptsForCharacter(this.activeCharacter).forEach(prompt => { this.getPromptsForCharacter(this.activeCharacter).forEach(prompt => {
// Marker offer almost no interaction except being draggable.
const advancedEnabled = this.serviceSettings.prompt_manager_settings.showAdvancedSettings; const advancedEnabled = this.serviceSettings.prompt_manager_settings.showAdvancedSettings;
let draggableEnabled = true; let draggableEnabled = true;
if (true === prompt.system_prompt && false === advancedEnabled) draggableEnabled = false; if (prompt.system_prompt && !advancedEnabled) draggableEnabled = false;
if (prompt.marker) { if (prompt.marker &&
if (prompt.identifier !== 'newMainChat' && prompt.identifier !== 'newMainChat' &&
prompt.identifier !== 'chatHistory' && prompt.identifier !== 'chatHistory' &&
false === advancedEnabled) return; !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');
const listEntry = this.getPromptListEntry(this.activeCharacter, prompt.identifier); const listEntry = this.getPromptListEntry(this.activeCharacter, prompt.identifier);
if (false === listEntry.enabled) listItem.classList.add(this.configuration.prefix + 'prompt_manager_prompt_disabled'); const enabledClass = listEntry.enabled ? '' : `${prefix}prompt_manager_prompt_disabled`;
listItem.classList.add('dropAllowed'); const draggableClass = draggableEnabled ? 'draggable' : '';
listItem.setAttribute('draggable', String(draggableEnabled)); const markerClass = prompt.marker ? `${prefix}prompt_manager_marker` : '';
listItem.setAttribute('data-pm-identifier', prompt.identifier); const calculatedTokens = prompt.calculated_tokens ? prompt.calculated_tokens : '-';
const nameSpan = document.createElement('span'); let detachSpanHtml = '';
nameSpan.setAttribute('data-pm-name', prompt.name); if (this.isPromptDeletionAllowed(prompt)) {
detachSpanHtml = `
if (prompt.marker) { <span title="delete" class="caution fa-solid fa-x"></span>
const markerIconSpan = document.createElement('span'); `;
markerIconSpan.classList.add('fa-solid', 'fa-thumb-tack');
nameSpan.appendChild(markerIconSpan);
} }
const nameTextSpan = document.createElement('span'); listItemHtml += `
nameTextSpan.textContent = prompt.name; <li class="${prefix}prompt_manager_prompt ${draggableClass} ${enabledClass} ${markerClass}" draggable="${draggableEnabled}" data-pm-identifier="${prompt.identifier}">
nameSpan.appendChild(nameTextSpan); <span data-pm-name="${prompt.name}">
${prompt.marker ? '<span class="fa-solid fa-thumb-tack"></span>' : ''}
const tokensSpan = document.createElement('span'); <span>${prompt.name}</span>
tokensSpan.classList.add('prompt_manager_prompt_tokens') </span>
tokensSpan.setAttribute('data-pm-tokens', prompt.calculated_tokens); ${prompt.marker ? '<span></span>' : `
tokensSpan.textContent = prompt.calculated_tokens ? prompt.calculated_tokens : '-'; <span>
<span class="prompt_manager_prompt_controls">
const actionsSpan = document.createElement('span'); ${detachSpanHtml}
actionsSpan.classList.add('prompt_manager_prompt_controls'); <span title="edit" class="fa-solid fa-pencil"></span>
<span class="${listEntry.enabled ? 'fa-solid fa-toggle-on' : 'fa-solid fa-toggle-off'}"></span>
// Don't add delete control to system prompts </span>
if (true === this.isPromptDeletionAllowed(prompt)) { </span>
const detachSpan = document.createElement('span'); `}
detachSpan.title = 'delete'; <span class="prompt_manager_prompt_tokens" data-pm-tokens="${calculatedTokens}">${calculatedTokens}</span>
detachSpan.classList.add('caution', 'fa-solid', 'fa-x'); </li>
`;
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);
}); });
}
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. // Makes the prompt list draggable and handles swapping of two entries in the list.
PromptManagerModule.prototype.makeDraggable = function () { PromptManagerModule.prototype.makeDraggable = function () {