Add advanced formatting presets renaming buttons

90ef3e51c05ada24d87326566fa3a3210c76eecc

Yokayo <nonameutubecomm@gmail.com>

3 files changed, +155 -51Ignore whitespace
public/index.html+6 -3
@@ -3173,9 +3173,10 @@
31733173 </h4>
31743174 <div class="flex-container" title="Select your current Context Template" data-i18n="[title]Select your current Context Template">
31753175 <select id="context_presets" data-preset-manager-for="context" class="flex1 text_pole"></select>
31763176 <div class="flex-container justifyCenter gap3px">
31773177 <input type="file" hidden data-preset-manager-file="context" accept=".json, .settings">
31783178 <i data-preset-manager-update="context" class="menu_button fa-solid fa-save" title="Update current template" data-i18n="[title]Update current template"></i>
3179+ <i data-preset-manager-rename="context" class="menu_button fa-pencil fa-solid" title="Rename current template" data-i18n="[title]Rename current template"></i>
31793180 <i data-preset-manager-new="context" class="menu_button fa-solid fa-file-circle-plus" title="Save template as" data-i18n="[title]Save template as"></i>
31803181 <i data-preset-manager-import="context" class="displayNone menu_button fa-solid fa-file-import" title="Import template" data-i18n="[title]Import template"></i>
31813182 <i data-preset-manager-export="context" class="displayNone menu_button fa-solid fa-file-export" title="Export template" data-i18n="[title]Export template"></i>
@@ -3284,9 +3285,10 @@
32843285
32853286 <div class="flex-container" title="Select your current Instruct Template" data-i18n="[title]Select your current Instruct Template">
32863287 <select id="instruct_presets" data-preset-manager-for="instruct" class="flex1 text_pole"></select>
32873288 <div class="flex-container margin0 justifyCenter gap3px">
32883289 <input type="file" hidden data-preset-manager-file="instruct" accept=".json, .settings">
32893290 <i data-preset-manager-update="instruct" class="menu_button fa-solid fa-save" title="Update current template" data-i18n="[title]Update current template"></i>
3291+ <i data-preset-manager-rename="instruct" class="menu_button fa-pencil fa-solid" title="Rename current template" data-i18n="[title]Rename current template"></i>
32903292 <i data-preset-manager-new="instruct" class="menu_button fa-solid fa-file-circle-plus" title="Save template as" data-i18n="[title]Save template as"></i>
32913293 <i data-preset-manager-import="instruct" class="displayNone menu_button fa-solid fa-file-import" title="Import template" data-i18n="[title]Import template"></i>
32923294 <i data-preset-manager-export="instruct" class="displayNone menu_button fa-solid fa-file-export" title="Export template" data-i18n="[title]Export template"></i>
@@ -3464,9 +3466,10 @@
34643466
34653467 <div class="flex-container" title="Select your current System Prompt" data-i18n="[title]Select your current System Prompt">
34663468 <select id="sysprompt_select" data-preset-manager-for="sysprompt" class="flex1 text_pole"></select>
34673469 <div class="flex-container margin0 justifyCenter gap3px">
34683470 <input type="file" hidden data-preset-manager-file="sysprompt" accept=".json, .settings">
34693471 <i data-preset-manager-update="sysprompt" class="menu_button fa-solid fa-save" title="Update current prompt" data-i18n="[title]Update current prompt"></i>
3472+ <i data-preset-manager-rename="sysprompt" class="menu_button fa-pencil fa-solid" title="Rename current prompt" data-i18n="[title]Rename current prompt"></i>
34703473 <i data-preset-manager-new="sysprompt" class="menu_button fa-solid fa-file-circle-plus" title="Save prompt as" data-i18n="[title]Save prompt as"></i>
34713474 <i data-preset-manager-import="sysprompt" class="displayNone menu_button fa-solid fa-file-import" title="Import template" data-i18n="[title]Import template"></i>
34723475 <i data-preset-manager-export="sysprompt" class="displayNone menu_button fa-solid fa-file-export" title="Export template" data-i18n="[title]Export template"></i>
public/locales/ru-ru.json+65 -5
@@ -1720,7 +1720,7 @@
17201720 "Proxy Preset": "Пресет для прокси",
17211721 "Enter a name:": "Введите название:",
17221722 "Are you sure you want to delete the selected profile?": "Вы точно хотите удалить выбранный профиль?",
17231723 "instruct_enabled": "ВключитьВкл/выкл Instruct-режим",
17241724 "Instruct Template": "Шаблон Instruct-режима",
17251725 "instruct_template_activation_regex_desc": "Автоматически активировать этот шаблон в момент подключения к API или выбора модели, если название модели соответствует этому рег. выражению.",
17261726 "instruct_bind_to_context": "При включении этой опции Шаблон контекста будет выбираться, исходя из выбранного в текущий момент Шаблона Instruct-режима, либо по вашему желанию.",
@@ -1730,11 +1730,11 @@
17301730 "Export Advanced Formatting settings": "Экспорт настроек Расширенного форматирования",
17311731 "Select your current System Prompt": "Выберите текущий системный промпт",
17321732 "Prompt Content": "Текст промпта",
17331733 "Update current prompt": "Обновить текущийСохранить промпт",
17341734 "Save prompt as": "Сохранить как...",
17351735 "Import template": "Импорт шаблона",
17361736 "Export template": "Экспорт шаблона",
17371737 "Restore current prompt": "Восстановить текущий промпт",
17381738 "comma delimited,no spaces between": "через запятую,без пробелов в промежутках",
17391739 "User Message Sequences": "Строки для сообщений пользователя",
17401740 "Assistant Message Sequences": "Строки для сообщений ассистента",
@@ -1757,7 +1757,7 @@
17571757 "Preset was not deleted from server": "Пресет не удалён с сервера",
17581758 "Preset deleted": "Пресет удалён",
17591759 "Delete the preset?": "Удалить пресет?",
17601760 "Preset updated": "Пресет обновлёнсохранён",
17611761 "Entered reverse proxy address is not a valid URL": "Введённый адрес прокси невалиден",
17621762 "An error occurred while counting tokens: Token budget exceeded.": "Ошибка при подсчёте токенов: Превышен бюджет токенов",
17631763 "An error occurred while counting tokens: Invalid character name": "Ошибка при подсчёте токенов: Невалидное имя персонажа",
@@ -1893,5 +1893,65 @@
18931893 "Base": "Основание",
18941894 "DRY_Base_desc": "Определяет, насколько быстро возрастает штраф с увеличением длины строки.",
18951895 "Allowed Length": "Допустимая длина",
18961896 "DRY_Allowed_Length_desc": "Длина повторяющейся строки, при превышении которой DRY начинает налагать штраф.",
1897+ "Invalid data provided for master import": "Глоб. импорт не может быть выполнен по причине невалидности данных",
1898+ "Importing instruct template...": "Импортируем...",
1899+ "Instruct template detected": "Обнаружен шаблон Instruct-режима",
1900+ "Importing as context template...": "Импортируем...",
1901+ "Context template detected": "Обнаружен шаблон контекста",
1902+ "Importing as system prompt...": "Импортируем...",
1903+ "System prompt detected": "Обнаружен системный промпт",
1904+ "Importing as settings preset...": "Импортируем...",
1905+ "Text Completion settings detected": "Обнаружены настройки Text Completion",
1906+ "No valid sections found in imported data": "Не найдено ни одной валидной секции данных",
1907+ "No sections selected for import": "Не выбрано ни одной секции для импорта",
1908+ "Import": "Импортировать",
1909+ "Imported ${0} settings: ${1}": "Импортировано ${0} настроек: ${1}",
1910+ "Export": "Экспортировать",
1911+ "No sections selected for export": "Не выбрано ни одной секции для экспорта",
1912+ "Cannot update GUI preset": "Пресет для GUI обновить невозможно",
1913+ "Template updated": "Шаблон сохранён",
1914+ "Hint: Use a character/group name to bind preset to a specific chat.": "Совет: введите имя персонажа/группы, чтобы привязать пресет к определённому чату.",
1915+ "Preset name:": "Название пресета:",
1916+ "Template name:": "Название шаблона:",
1917+ "Preset saved": "Пресет сохранён",
1918+ "Template saved": "Шаблон сохранён",
1919+ "Preset could not be saved": "Не удалось сохранить пресет",
1920+ "Preset could not be renamed": "Не удалось обновить пресет",
1921+ "Preset renamed": "Пресет переименован",
1922+ "Template renamed": "Шаблон переименован",
1923+ "Cannot delete GUI preset": "Пресет для GUI удалить невозможно",
1924+ "Failed to restore default preset": "Не удалось восстановить пресет по умолчанию",
1925+ "Failed to restore default template": "Не удалось восстановить шаблон по умолчанию",
1926+ "Rename preset": "Переименовать пресет",
1927+ "Rename template": "Переименовать шаблон",
1928+ "Enter a new name:": "Введите новое название:",
1929+ "Preset imported": "Пресет импортирован",
1930+ "Template imported": "Шаблон импортирован",
1931+ "Delete this preset?": "Удалить этот пресет?",
1932+ "Delete this template?": "Удалить этот шаблон?",
1933+ "This action is irreversible and your current settings will be overwritten.": "Отменить это действие невозможно. Ваши текущие настройки будут перезаписаны.",
1934+ "Preset deleted": "Пресет удалён",
1935+ "Template deleted": "Шаблон удалён",
1936+ "Template was not deleted from server": "Шаблон не удалён с сервера",
1937+ "Cannot restore GUI preset": "Пресет для Gui восстановить нельзя",
1938+ "Default preset cannot be restored": "Невозможно восстановить пресет по умолчанию",
1939+ "Default template cannot be restored": "Невозможно восстановить шаблон по умолчанию",
1940+ "Resetting a <b>default preset</b> will restore the default settings": "Сброс <b>стандартного пресета</b> восстановит настройки по умолчанию.",
1941+ "Resetting a <b>default template</b> will restore the default settings.": "Сброс <b>стандартного шаблона</b> восстановит настройки по умолчанию.",
1942+ "Are you sure?": "Вы уверены?",
1943+ "Default preset restored": "Стандартный пресет восстановлен",
1944+ "Default template restored": "Стандартный шаблон восстановлен",
1945+ "Resetting a <b>custom preset</b> will restore to the last saved state.": "Сброс <b>пользовательского пресета</b> откатит его к последнему сохранённому состоянию.",
1946+ "Resetting a <b>custom template</b> will restore to the last saved state.": "Сброс <b>пользовательского шаблона</b> откатит его к последнему сохранённому состоянию.",
1947+ "Preset restored": "Пресет восстановлен",
1948+ "Template restored": "Шаблон восстановлен",
1949+ "Update current template": "Сохранить шаблон",
1950+ "Rename current template": "Переименовать шаблон",
1951+ "Save template as": "Сохранить как...",
1952+ "Restore current template": "Восстановить шаблон",
1953+ "Delete the template": "Удалить шаблон",
1954+ "Rename current prompt": "Переименовать промпт",
1955+ "Select your current Context Template": "Выберите активный шаблон контекста",
1956+ "Select your current Instruct Template": "Выберите активный шаблон Instruct-режима"
18971957}
public/scripts/preset-manager.js+84 -43
@@ -34,6 +34,7 @@ import {
3434 textgenerationwebui_settings as textgen_settings,
3535} from './textgen-settings.js';
3636import { download, parseJsonFile, waitUntilCondition } from './utils.js';
37+import { t } from './i18n.js';
3738
3839const presetManagers = {};
3940
@@ -194,32 +195,32 @@ class PresetManager {
194195 */
195196 static async performMasterImport(data, fileName) {
196197 if (!data || typeof data !== 'object') {
197198 toastr.error('t`Invalid data provided for master import'`);
198199 return;
199200 }
200201
201202 // Check for legacy file imports
202203 // 1. Instruct Template
203204 if (this.isPossiblyInstructData(data)) {
204205 toastr.info('t`Importing instruct template...'`, 't`Instruct template detected'`);
205206 return await getPresetManager('instruct').savePreset(data.name, data);
206207 }
207208
208209 // 2. Context Template
209210 if (this.isPossiblyContextData(data)) {
210211 toastr.info('t`Importing as context template...'`, 't`Context template detected'`);
211212 return await getPresetManager('context').savePreset(data.name, data);
212213 }
213214
214215 // 3. System Prompt
215216 if (this.isPossiblySystemPromptData(data)) {
216217 toastr.info('t`Importing as system prompt...'`, 't`System prompt detected'`);
217218 return await getPresetManager('sysprompt').savePreset(data.name, data);
218219 }
219220
220221 // 4. Text Completion settings
221222 if (this.isPossiblyTextCompletionData(data)) {
222223 toastr.info('t`Importing as settings preset...'`, 't`Text Completion settings detected'`);
223224 return await getPresetManager('textgenerationwebui').savePreset(fileName, data);
224225 }
225226
@@ -231,7 +232,7 @@ class PresetManager {
231232 }
232233
233234 if (validSections.length === 0) {
234235 toastr.error('t`No valid sections found in imported data'`);
235236 return;
236237 }
237238
@@ -242,8 +243,8 @@ class PresetManager {
242243
243244 const html = $(await renderTemplateAsync('masterImport', { sections: sectionNames }));
244245 const popup = new Popup(html, POPUP_TYPE.CONFIRM, '', {
245246 okButton: 't`Import'`,
246247 cancelButton: 't`Cancel'`,
247248 });
248249
249250 const result = await popup.show();
@@ -257,7 +258,7 @@ class PresetManager {
257258 const confirmedSections = html.find('input:checked').map((_, el) => el instanceof HTMLInputElement && el.value).get();
258259
259260 if (confirmedSections.length === 0) {
260261 toastr.info('t`No sections selected for import'`);
261262 return;
262263 }
263264
@@ -270,7 +271,7 @@ class PresetManager {
270271 }
271272 }
272273
273274 toastr.success(t`Imported ${importedSections.length} settings: ${importedSections.join(', ')}`);
274275 }
275276
276277 /**
@@ -285,8 +286,8 @@ class PresetManager {
285286 const html = $(await renderTemplateAsync('masterExport', { sections: sectionNames }));
286287
287288 const popup = new Popup(html, POPUP_TYPE.CONFIRM, '', {
288289 okButton: 't`Export'`,
289290 cancelButton: 't`Cancel'`,
290291 });
291292
292293 const result = await popup.show();
@@ -300,7 +301,7 @@ class PresetManager {
300301 const data = {};
301302
302303 if (confirmedSections.length === 0) {
303304 toastr.info('t`No sections selected for export'`);
304305 return;
305306 }
306307
@@ -366,21 +367,21 @@ class PresetManager {
366367 console.log(selected);
367368
368369 if (selected.val() == 'gui') {
369370 toastr.info('t`Cannot update GUI preset'`);
370371 return;
371372 }
372373
373374 const name = selected.text();
374375 await this.savePreset(name);
375376
376377 const successToast = !this.isAdvancedFormatting() ? 't`Preset updated'` : 't`Template updated'`;
377378 toastr.success(successToast);
378379 }
379380
380381 async savePresetAs() {
381382 const inputValue = this.getSelectedPresetName();
382383 const popupText = !this.isAdvancedFormatting() ? '<h4>' + t`Hint: Use a character/group name to bind preset to a specific chat.` + '</h4>' : '';
383384 const headerText = !this.isAdvancedFormatting() ? 't`Preset name:'` : 't`Template name:'`;
384385 const name = await Popup.show.input(headerText, popupText, inputValue);
385386 if (!name) {
386387 console.log('Preset name not provided');
@@ -389,7 +390,7 @@ class PresetManager {
389390
390391 await this.savePreset(name);
391392
392393 const successToast = !this.isAdvancedFormatting() ? 't`Preset saved'` : 't`Template saved'`;
393394 toastr.success(successToast);
394395 }
395396
@@ -411,7 +412,7 @@ class PresetManager {
411412 });
412413
413414 if (!response.ok) {
414415 toastr.error('t`Check the server connection and reload the page to prevent data loss.'`, 't`Preset could not be saved'`);
415416 console.error('Preset could not be saved', response);
416417 throw new Error('Preset could not be saved');
417418 }
@@ -421,6 +422,19 @@ class PresetManager {
421422
422423 this.updateList(name, preset);
423424 }
425+
426+ async renamePreset(newName) {
427+ const oldName = this.getSelectedPresetName();
428+ try {
429+ await this.savePreset(newName);
430+ await this.deletePreset(oldName);
431+ } catch (error) {
432+ toastr.error(t`Check the server connection and reload the page to prevent data loss.`, t`Preset could not be renamed`);
433+ console.error('Preset could not be renamed', error);
434+ throw new Error('Preset could not be renamed');
435+ }
436+
437+ }
424438
425439 getPresetList() {
426440 let presets = [];
@@ -585,13 +599,14 @@ class PresetManager {
585599 return settings;
586600 }
587601
588- async deleteCurrentPreset() {
602+ // pass no arguments to delete current preset
603+ async deletePreset(name) {
589604 const { preset_names, presets } = this.getPresetList();
590605 const value = name ? this.isKeyedApi() ? this.findPreset(name) : name : this.getSelectedPreset();
591606 const nameToDelete = name || this.getSelectedPresetName();
592607
593608 if (value == 'gui') {
594609 toastr.info('t`Cannot delete GUI preset'`);
595610 return;
596611 }
597612
@@ -604,8 +619,11 @@ class PresetManager {
604619 } else {
605620 delete preset_names[nameToDelete];
606621 }
607-
622+
608- if (Object.keys(preset_names).length) {
623+ // switch in UI only when deleting currently selected preset
624+ const switchPresets = !name || this.getSelectedPresetName() == name;
625+
626+ if (Object.keys(preset_names).length && switchPresets) {
609627 const nextPresetName = Object.keys(preset_names)[0];
610628 const newValue = preset_names[nextPresetName];
611629 $(this.select).find(`option[value="${newValue}"]`).attr('selected', 'true');
@@ -629,7 +647,7 @@ class PresetManager {
629647 });
630648
631649 if (!response.ok) {
632650 const errorToast = !this.isAdvancedFormatting() ? 't`Failed to restore default preset'` : 't`Failed to restore default template'`;
633651 toastr.error(errorToast);
634652 return;
635653 }
@@ -773,6 +791,29 @@ export async function initPresetManager() {
773791
774792 await presetManager.savePresetAs();
775793 });
794+
795+ $(document).on('click', '[data-preset-manager-rename]', async function () {
796+ const apiId = $(this).data('preset-manager-rename');
797+ const presetManager = getPresetManager(apiId);
798+
799+ if (!presetManager) {
800+ console.warn(`Preset Manager not found for API: ${apiId}`);
801+ return;
802+ }
803+
804+ const popupHeader = !presetManager.isAdvancedFormatting() ? t`Rename preset` : t`Rename template`;
805+ const oldName = name;
806+ const newName = await Popup.show.input(popupHeader, t`Enter a new name:`, oldName);
807+ if (oldName === newName || !newName) {
808+ console.debug(!presetManager.isAdvancedFormatting() ? 'Preset rename cancelled' : 'Template rename cancelled');
809+ return;
810+ }
811+
812+ await presetManager.renamePreset(newName);
813+
814+ const successToast = !presetManager.isAdvancedFormatting() ? t`Preset renamed` : t`Template renamed`;
815+ toastr.success(successToast);
816+ });
776817
777818 $(document).on('click', '[data-preset-manager-export]', async function () {
778819 const apiId = $(this).data('preset-manager-export');
@@ -816,7 +857,7 @@ export async function initPresetManager() {
816857 data['name'] = name;
817858
818859 await presetManager.savePreset(name, data);
819860 const successToast = !presetManager.isAdvancedFormatting() ? 't`Preset imported'` : 't`Template imported'`;
820861 toastr.success(successToast);
821862 e.target.value = null;
822863 });
@@ -830,19 +871,19 @@ export async function initPresetManager() {
830871 return;
831872 }
832873
833874 const headerText = !presetManager.isAdvancedFormatting() ? 't`Delete this preset?'` : 't`Delete this template?'`;
834875 const confirm = await Popup.show.confirm(headerText, 't`This action is irreversible and your current settings will be overwritten.'`);
835876 if (!confirm) {
836877 return;
837878 }
838879
839880 const result = await presetManager.deleteCurrentPresetdeletePreset();
840881
841882 if (result) {
842883 const successToast = !presetManager.isAdvancedFormatting() ? 't`Preset deleted'` : 't`Template deleted'`;
843884 toastr.success(successToast);
844885 } else {
845886 const warningToast = !presetManager.isAdvancedFormatting() ? 't`Preset was not deleted from server'` : 't`Template was not deleted from server'`;
846887 toastr.warning(warningToast);
847888 }
848889
@@ -862,7 +903,7 @@ export async function initPresetManager() {
862903 const data = await presetManager.getDefaultPreset(name);
863904
864905 if (name == 'gui') {
865906 toastr.info('t`Cannot restore GUI preset'`);
866907 return;
867908 }
868909
@@ -872,37 +913,37 @@ export async function initPresetManager() {
872913
873914 if (data.isDefault) {
874915 if (Object.keys(data.preset).length === 0) {
875916 const errorToast = !presetManager.isAdvancedFormatting() ? 't`Default preset cannot be restored'` : 't`Default template cannot be restored'`;
876917 toastr.error(errorToast);
877918 return;
878919 }
879920
880921 const confirmText = !presetManager.isAdvancedFormatting()
881922 ? 't`Resetting a <b>default preset</b> will restore the default settings.'`
882923 : 't`Resetting a <b>default template</b> will restore the default settings.'`;
883924 const confirm = await Popup.show.confirm('t`Are you sure?'`, confirmText);
884925 if (!confirm) {
885926 return;
886927 }
887928
888929 await presetManager.deleteCurrentPresetdeletePreset();
889930 await presetManager.savePreset(name, data.preset);
890931 const option = presetManager.findPreset(name);
891932 presetManager.selectPreset(option);
892933 const successToast = !presetManager.isAdvancedFormatting() ? 't`Default preset restored'` : 't`Default template restored'`;
893934 toastr.success(successToast);
894935 } else {
895936 const confirmText = !presetManager.isAdvancedFormatting()
896937 ? 't`Resetting a <b>custom preset</b> will restore to the last saved state.'`
897938 : 't`Resetting a <b>custom template</b> will restore to the last saved state.'`;
898939 const confirm = await Popup.show.confirm('t`Are you sure?'`, confirmText);
899940 if (!confirm) {
900941 return;
901942 }
902943
903944 const option = presetManager.findPreset(name);
904945 presetManager.selectPreset(option);
905946 const successToast = !presetManager.isAdvancedFormatting() ? 't`Preset restored'` : 't`Template restored'`;
906947 toastr.success(successToast);
907948 }
908949 });