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 @@
3173 </h4>3173 </h4>
3174 <div class="flex-container" title="Select your current Context Template" data-i18n="[title]Select your current Context Template">3174 <div class="flex-container" title="Select your current Context Template" data-i18n="[title]Select your current Context Template">
3175 <select id="context_presets" data-preset-manager-for="context" class="flex1 text_pole"></select>3175 <select id="context_presets" data-preset-manager-for="context" class="flex1 text_pole"></select>
3176 <div class="flex-container justifyCenter">3176 <div class="flex-container justifyCenter gap3px">
3177 <input type="file" hidden data-preset-manager-file="context" accept=".json, .settings">3177 <input type="file" hidden data-preset-manager-file="context" accept=".json, .settings">
3178 <i data-preset-manager-update="context" class="menu_button fa-solid fa-save" title="Update current template" data-i18n="[title]Update current template"></i>3178 <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>
3179 <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>3180 <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>
3180 <i data-preset-manager-import="context" class="displayNone menu_button fa-solid fa-file-import" title="Import template" data-i18n="[title]Import template"></i>3181 <i data-preset-manager-import="context" class="displayNone menu_button fa-solid fa-file-import" title="Import template" data-i18n="[title]Import template"></i>
3181 <i data-preset-manager-export="context" class="displayNone menu_button fa-solid fa-file-export" title="Export template" data-i18n="[title]Export template"></i>3182 <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
3285 <div class="flex-container" title="Select your current Instruct Template" data-i18n="[title]Select your current Instruct Template">3286 <div class="flex-container" title="Select your current Instruct Template" data-i18n="[title]Select your current Instruct Template">
3286 <select id="instruct_presets" data-preset-manager-for="instruct" class="flex1 text_pole"></select>3287 <select id="instruct_presets" data-preset-manager-for="instruct" class="flex1 text_pole"></select>
3287 <div class="flex-container margin0 justifyCenter">3288 <div class="flex-container margin0 justifyCenter gap3px">
3288 <input type="file" hidden data-preset-manager-file="instruct" accept=".json, .settings">3289 <input type="file" hidden data-preset-manager-file="instruct" accept=".json, .settings">
3289 <i data-preset-manager-update="instruct" class="menu_button fa-solid fa-save" title="Update current template" data-i18n="[title]Update current template"></i>3290 <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>
3290 <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>3292 <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>
3291 <i data-preset-manager-import="instruct" class="displayNone menu_button fa-solid fa-file-import" title="Import template" data-i18n="[title]Import template"></i>3293 <i data-preset-manager-import="instruct" class="displayNone menu_button fa-solid fa-file-import" title="Import template" data-i18n="[title]Import template"></i>
3292 <i data-preset-manager-export="instruct" class="displayNone menu_button fa-solid fa-file-export" title="Export template" data-i18n="[title]Export template"></i>3294 <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
3465 <div class="flex-container" title="Select your current System Prompt" data-i18n="[title]Select your current System Prompt">3467 <div class="flex-container" title="Select your current System Prompt" data-i18n="[title]Select your current System Prompt">
3466 <select id="sysprompt_select" data-preset-manager-for="sysprompt" class="flex1 text_pole"></select>3468 <select id="sysprompt_select" data-preset-manager-for="sysprompt" class="flex1 text_pole"></select>
3467 <div class="flex-container margin0 justifyCenter">3469 <div class="flex-container margin0 justifyCenter gap3px">
3468 <input type="file" hidden data-preset-manager-file="sysprompt" accept=".json, .settings">3470 <input type="file" hidden data-preset-manager-file="sysprompt" accept=".json, .settings">
3469 <i data-preset-manager-update="sysprompt" class="menu_button fa-solid fa-save" title="Update current prompt" data-i18n="[title]Update current prompt"></i>3471 <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>
3470 <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>3473 <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>
3471 <i data-preset-manager-import="sysprompt" class="displayNone menu_button fa-solid fa-file-import" title="Import template" data-i18n="[title]Import template"></i>3474 <i data-preset-manager-import="sysprompt" class="displayNone menu_button fa-solid fa-file-import" title="Import template" data-i18n="[title]Import template"></i>
3472 <i data-preset-manager-export="sysprompt" class="displayNone menu_button fa-solid fa-file-export" title="Export template" data-i18n="[title]Export template"></i>3475 <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 @@
1720 "Proxy Preset": "Пресет для прокси",1720 "Proxy Preset": "Пресет для прокси",
1721 "Enter a name:": "Введите название:",1721 "Enter a name:": "Введите название:",
1722 "Are you sure you want to delete the selected profile?": "Вы точно хотите удалить выбранный профиль?",1722 "Are you sure you want to delete the selected profile?": "Вы точно хотите удалить выбранный профиль?",
1723 "instruct_enabled": "Включить Instruct-режим",1723 "instruct_enabled": "Вкл/выкл Instruct-режим",
1724 "Instruct Template": "Шаблон Instruct-режима",1724 "Instruct Template": "Шаблон Instruct-режима",
1725 "instruct_template_activation_regex_desc": "Автоматически активировать этот шаблон в момент подключения к API или выбора модели, если название модели соответствует этому рег. выражению.",1725 "instruct_template_activation_regex_desc": "Автоматически активировать этот шаблон в момент подключения к API или выбора модели, если название модели соответствует этому рег. выражению.",
1726 "instruct_bind_to_context": "При включении этой опции Шаблон контекста будет выбираться, исходя из выбранного в текущий момент Шаблона Instruct-режима, либо по вашему желанию.",1726 "instruct_bind_to_context": "При включении этой опции Шаблон контекста будет выбираться, исходя из выбранного в текущий момент Шаблона Instruct-режима, либо по вашему желанию.",
@@ -1730,11 +1730,11 @@
1730 "Export Advanced Formatting settings": "Экспорт настроек Расширенного форматирования",1730 "Export Advanced Formatting settings": "Экспорт настроек Расширенного форматирования",
1731 "Select your current System Prompt": "Выберите текущий системный промпт",1731 "Select your current System Prompt": "Выберите текущий системный промпт",
1732 "Prompt Content": "Текст промпта",1732 "Prompt Content": "Текст промпта",
1733 "Update current prompt": "Обновить текущий промпт",1733 "Update current prompt": "Сохранить промпт",
1734 "Save prompt as": "Сохранить как...",1734 "Save prompt as": "Сохранить как...",
1735 "Import template": "Импорт шаблона",1735 "Import template": "Импорт шаблона",
1736 "Export template": "Экспорт шаблона",1736 "Export template": "Экспорт шаблона",
1737 "Restore current prompt": "Восстановить текущий промпт",1737 "Restore current prompt": "Восстановить промпт",
1738 "comma delimited,no spaces between": "через запятую,без пробелов в промежутках",1738 "comma delimited,no spaces between": "через запятую,без пробелов в промежутках",
1739 "User Message Sequences": "Строки для сообщений пользователя",1739 "User Message Sequences": "Строки для сообщений пользователя",
1740 "Assistant Message Sequences": "Строки для сообщений ассистента",1740 "Assistant Message Sequences": "Строки для сообщений ассистента",
@@ -1757,7 +1757,7 @@
1757 "Preset was not deleted from server": "Пресет не удалён с сервера",1757 "Preset was not deleted from server": "Пресет не удалён с сервера",
1758 "Preset deleted": "Пресет удалён",1758 "Preset deleted": "Пресет удалён",
1759 "Delete the preset?": "Удалить пресет?",1759 "Delete the preset?": "Удалить пресет?",
1760 "Preset updated": "Пресет обновлён",1760 "Preset updated": "Пресет сохранён",
1761 "Entered reverse proxy address is not a valid URL": "Введённый адрес прокси невалиден",1761 "Entered reverse proxy address is not a valid URL": "Введённый адрес прокси невалиден",
1762 "An error occurred while counting tokens: Token budget exceeded.": "Ошибка при подсчёте токенов: Превышен бюджет токенов",1762 "An error occurred while counting tokens: Token budget exceeded.": "Ошибка при подсчёте токенов: Превышен бюджет токенов",
1763 "An error occurred while counting tokens: Invalid character name": "Ошибка при подсчёте токенов: Невалидное имя персонажа",1763 "An error occurred while counting tokens: Invalid character name": "Ошибка при подсчёте токенов: Невалидное имя персонажа",
@@ -1893,5 +1893,65 @@
1893 "Base": "Основание",1893 "Base": "Основание",
1894 "DRY_Base_desc": "Определяет, насколько быстро возрастает штраф с увеличением длины строки.",1894 "DRY_Base_desc": "Определяет, насколько быстро возрастает штраф с увеличением длины строки.",
1895 "Allowed Length": "Допустимая длина",1895 "Allowed Length": "Допустимая длина",
1896 "DRY_Allowed_Length_desc": "Длина повторяющейся строки, при превышении которой DRY начинает налагать штраф."1896 "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-режима"
1897}1957}
public/scripts/preset-manager.js+84 -43
@@ -34,6 +34,7 @@ import {
34 textgenerationwebui_settings as textgen_settings,34 textgenerationwebui_settings as textgen_settings,
35} from './textgen-settings.js';35} from './textgen-settings.js';
36import { download, parseJsonFile, waitUntilCondition } from './utils.js';36import { download, parseJsonFile, waitUntilCondition } from './utils.js';
37import { t } from './i18n.js';
3738
38const presetManagers = {};39const presetManagers = {};
3940
@@ -194,32 +195,32 @@ class PresetManager {
194 */195 */
195 static async performMasterImport(data, fileName) {196 static async performMasterImport(data, fileName) {
196 if (!data || typeof data !== 'object') {197 if (!data || typeof data !== 'object') {
197 toastr.error('Invalid data provided for master import');198 toastr.error(t`Invalid data provided for master import`);
198 return;199 return;
199 }200 }
200201
201 // Check for legacy file imports202 // Check for legacy file imports
202 // 1. Instruct Template203 // 1. Instruct Template
203 if (this.isPossiblyInstructData(data)) {204 if (this.isPossiblyInstructData(data)) {
204 toastr.info('Importing instruct template...', 'Instruct template detected');205 toastr.info(t`Importing instruct template...`, t`Instruct template detected`);
205 return await getPresetManager('instruct').savePreset(data.name, data);206 return await getPresetManager('instruct').savePreset(data.name, data);
206 }207 }
207208
208 // 2. Context Template209 // 2. Context Template
209 if (this.isPossiblyContextData(data)) {210 if (this.isPossiblyContextData(data)) {
210 toastr.info('Importing as context template...', 'Context template detected');211 toastr.info(t`Importing as context template...`, t`Context template detected`);
211 return await getPresetManager('context').savePreset(data.name, data);212 return await getPresetManager('context').savePreset(data.name, data);
212 }213 }
213214
214 // 3. System Prompt215 // 3. System Prompt
215 if (this.isPossiblySystemPromptData(data)) {216 if (this.isPossiblySystemPromptData(data)) {
216 toastr.info('Importing as system prompt...', 'System prompt detected');217 toastr.info(t`Importing as system prompt...`, t`System prompt detected`);
217 return await getPresetManager('sysprompt').savePreset(data.name, data);218 return await getPresetManager('sysprompt').savePreset(data.name, data);
218 }219 }
219220
220 // 4. Text Completion settings221 // 4. Text Completion settings
221 if (this.isPossiblyTextCompletionData(data)) {222 if (this.isPossiblyTextCompletionData(data)) {
222 toastr.info('Importing as settings preset...', 'Text Completion settings detected');223 toastr.info(t`Importing as settings preset...`, t`Text Completion settings detected`);
223 return await getPresetManager('textgenerationwebui').savePreset(fileName, data);224 return await getPresetManager('textgenerationwebui').savePreset(fileName, data);
224 }225 }
225226
@@ -231,7 +232,7 @@ class PresetManager {
231 }232 }
232233
233 if (validSections.length === 0) {234 if (validSections.length === 0) {
234 toastr.error('No valid sections found in imported data');235 toastr.error(t`No valid sections found in imported data`);
235 return;236 return;
236 }237 }
237238
@@ -242,8 +243,8 @@ class PresetManager {
242243
243 const html = $(await renderTemplateAsync('masterImport', { sections: sectionNames }));244 const html = $(await renderTemplateAsync('masterImport', { sections: sectionNames }));
244 const popup = new Popup(html, POPUP_TYPE.CONFIRM, '', {245 const popup = new Popup(html, POPUP_TYPE.CONFIRM, '', {
245 okButton: 'Import',246 okButton: t`Import`,
246 cancelButton: 'Cancel',247 cancelButton: t`Cancel`,
247 });248 });
248249
249 const result = await popup.show();250 const result = await popup.show();
@@ -257,7 +258,7 @@ class PresetManager {
257 const confirmedSections = html.find('input:checked').map((_, el) => el instanceof HTMLInputElement && el.value).get();258 const confirmedSections = html.find('input:checked').map((_, el) => el instanceof HTMLInputElement && el.value).get();
258259
259 if (confirmedSections.length === 0) {260 if (confirmedSections.length === 0) {
260 toastr.info('No sections selected for import');261 toastr.info(t`No sections selected for import`);
261 return;262 return;
262 }263 }
263264
@@ -270,7 +271,7 @@ class PresetManager {
270 }271 }
271 }272 }
272273
273 toastr.success(`Imported ${importedSections.length} settings: ${importedSections.join(', ')}`);274 toastr.success(t`Imported ${importedSections.length} settings: ${importedSections.join(', ')}`);
274 }275 }
275276
276 /**277 /**
@@ -285,8 +286,8 @@ class PresetManager {
285 const html = $(await renderTemplateAsync('masterExport', { sections: sectionNames }));286 const html = $(await renderTemplateAsync('masterExport', { sections: sectionNames }));
286287
287 const popup = new Popup(html, POPUP_TYPE.CONFIRM, '', {288 const popup = new Popup(html, POPUP_TYPE.CONFIRM, '', {
288 okButton: 'Export',289 okButton: t`Export`,
289 cancelButton: 'Cancel',290 cancelButton: t`Cancel`,
290 });291 });
291292
292 const result = await popup.show();293 const result = await popup.show();
@@ -300,7 +301,7 @@ class PresetManager {
300 const data = {};301 const data = {};
301302
302 if (confirmedSections.length === 0) {303 if (confirmedSections.length === 0) {
303 toastr.info('No sections selected for export');304 toastr.info(t`No sections selected for export`);
304 return;305 return;
305 }306 }
306307
@@ -366,21 +367,21 @@ class PresetManager {
366 console.log(selected);367 console.log(selected);
367368
368 if (selected.val() == 'gui') {369 if (selected.val() == 'gui') {
369 toastr.info('Cannot update GUI preset');370 toastr.info(t`Cannot update GUI preset`);
370 return;371 return;
371 }372 }
372373
373 const name = selected.text();374 const name = selected.text();
374 await this.savePreset(name);375 await this.savePreset(name);
375376
376 const successToast = !this.isAdvancedFormatting() ? 'Preset updated' : 'Template updated';377 const successToast = !this.isAdvancedFormatting() ? t`Preset updated` : t`Template updated`;
377 toastr.success(successToast);378 toastr.success(successToast);
378 }379 }
379380
380 async savePresetAs() {381 async savePresetAs() {
381 const inputValue = this.getSelectedPresetName();382 const inputValue = this.getSelectedPresetName();
382 const popupText = !this.isAdvancedFormatting() ? '<h4>Hint: Use a character/group name to bind preset to a specific chat.</h4>' : '';383 const popupText = !this.isAdvancedFormatting() ? '<h4>' + t`Hint: Use a character/group name to bind preset to a specific chat.` + '</h4>' : '';
383 const headerText = !this.isAdvancedFormatting() ? 'Preset name:' : 'Template name:';384 const headerText = !this.isAdvancedFormatting() ? t`Preset name:` : t`Template name:`;
384 const name = await Popup.show.input(headerText, popupText, inputValue);385 const name = await Popup.show.input(headerText, popupText, inputValue);
385 if (!name) {386 if (!name) {
386 console.log('Preset name not provided');387 console.log('Preset name not provided');
@@ -389,7 +390,7 @@ class PresetManager {
389390
390 await this.savePreset(name);391 await this.savePreset(name);
391392
392 const successToast = !this.isAdvancedFormatting() ? 'Preset saved' : 'Template saved';393 const successToast = !this.isAdvancedFormatting() ? t`Preset saved` : t`Template saved`;
393 toastr.success(successToast);394 toastr.success(successToast);
394 }395 }
395396
@@ -411,7 +412,7 @@ class PresetManager {
411 });412 });
412413
413 if (!response.ok) {414 if (!response.ok) {
414 toastr.error('Check the server connection and reload the page to prevent data loss.', 'Preset could not be saved');415 toastr.error(t`Check the server connection and reload the page to prevent data loss.`, t`Preset could not be saved`);
415 console.error('Preset could not be saved', response);416 console.error('Preset could not be saved', response);
416 throw new Error('Preset could not be saved');417 throw new Error('Preset could not be saved');
417 }418 }
@@ -421,6 +422,19 @@ class PresetManager {
421422
422 this.updateList(name, preset);423 this.updateList(name, preset);
423 }424 }
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
425 getPresetList() {439 getPresetList() {
426 let presets = [];440 let presets = [];
@@ -585,13 +599,14 @@ class PresetManager {
585 return settings;599 return settings;
586 }600 }
587601
588 async deleteCurrentPreset() {602 // pass no arguments to delete current preset
603 async deletePreset(name) {
589 const { preset_names, presets } = this.getPresetList();604 const { preset_names, presets } = this.getPresetList();
590 const value = this.getSelectedPreset();605 const value = name ? this.isKeyedApi() ? this.findPreset(name) : name : this.getSelectedPreset();
591 const nameToDelete = this.getSelectedPresetName();606 const nameToDelete = name || this.getSelectedPresetName();
592607
593 if (value == 'gui') {608 if (value == 'gui') {
594 toastr.info('Cannot delete GUI preset');609 toastr.info(t`Cannot delete GUI preset`);
595 return;610 return;
596 }611 }
597612
@@ -604,8 +619,11 @@ class PresetManager {
604 } else {619 } else {
605 delete preset_names[nameToDelete];620 delete preset_names[nameToDelete];
606 }621 }
607622
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) {
609 const nextPresetName = Object.keys(preset_names)[0];627 const nextPresetName = Object.keys(preset_names)[0];
610 const newValue = preset_names[nextPresetName];628 const newValue = preset_names[nextPresetName];
611 $(this.select).find(`option[value="${newValue}"]`).attr('selected', 'true');629 $(this.select).find(`option[value="${newValue}"]`).attr('selected', 'true');
@@ -629,7 +647,7 @@ class PresetManager {
629 });647 });
630648
631 if (!response.ok) {649 if (!response.ok) {
632 const errorToast = !this.isAdvancedFormatting() ? 'Failed to restore default preset' : 'Failed to restore default template';650 const errorToast = !this.isAdvancedFormatting() ? t`Failed to restore default preset` : t`Failed to restore default template`;
633 toastr.error(errorToast);651 toastr.error(errorToast);
634 return;652 return;
635 }653 }
@@ -773,6 +791,29 @@ export async function initPresetManager() {
773791
774 await presetManager.savePresetAs();792 await presetManager.savePresetAs();
775 });793 });
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
777 $(document).on('click', '[data-preset-manager-export]', async function () {818 $(document).on('click', '[data-preset-manager-export]', async function () {
778 const apiId = $(this).data('preset-manager-export');819 const apiId = $(this).data('preset-manager-export');
@@ -816,7 +857,7 @@ export async function initPresetManager() {
816 data['name'] = name;857 data['name'] = name;
817858
818 await presetManager.savePreset(name, data);859 await presetManager.savePreset(name, data);
819 const successToast = !presetManager.isAdvancedFormatting() ? 'Preset imported' : 'Template imported';860 const successToast = !presetManager.isAdvancedFormatting() ? t`Preset imported` : t`Template imported`;
820 toastr.success(successToast);861 toastr.success(successToast);
821 e.target.value = null;862 e.target.value = null;
822 });863 });
@@ -830,19 +871,19 @@ export async function initPresetManager() {
830 return;871 return;
831 }872 }
832873
833 const headerText = !presetManager.isAdvancedFormatting() ? 'Delete this preset?' : 'Delete this template?';874 const headerText = !presetManager.isAdvancedFormatting() ? t`Delete this preset?` : t`Delete this template?`;
834 const confirm = await Popup.show.confirm(headerText, 'This action is irreversible and your current settings will be overwritten.');875 const confirm = await Popup.show.confirm(headerText, t`This action is irreversible and your current settings will be overwritten.`);
835 if (!confirm) {876 if (!confirm) {
836 return;877 return;
837 }878 }
838879
839 const result = await presetManager.deleteCurrentPreset();880 const result = await presetManager.deletePreset();
840881
841 if (result) {882 if (result) {
842 const successToast = !presetManager.isAdvancedFormatting() ? 'Preset deleted' : 'Template deleted';883 const successToast = !presetManager.isAdvancedFormatting() ? t`Preset deleted` : t`Template deleted`;
843 toastr.success(successToast);884 toastr.success(successToast);
844 } else {885 } else {
845 const warningToast = !presetManager.isAdvancedFormatting() ? 'Preset was not deleted from server' : 'Template was not deleted from server';886 const warningToast = !presetManager.isAdvancedFormatting() ? t`Preset was not deleted from server` : t`Template was not deleted from server`;
846 toastr.warning(warningToast);887 toastr.warning(warningToast);
847 }888 }
848889
@@ -862,7 +903,7 @@ export async function initPresetManager() {
862 const data = await presetManager.getDefaultPreset(name);903 const data = await presetManager.getDefaultPreset(name);
863904
864 if (name == 'gui') {905 if (name == 'gui') {
865 toastr.info('Cannot restore GUI preset');906 toastr.info(t`Cannot restore GUI preset`);
866 return;907 return;
867 }908 }
868909
@@ -872,37 +913,37 @@ export async function initPresetManager() {
872913
873 if (data.isDefault) {914 if (data.isDefault) {
874 if (Object.keys(data.preset).length === 0) {915 if (Object.keys(data.preset).length === 0) {
875 const errorToast = !presetManager.isAdvancedFormatting() ? 'Default preset cannot be restored' : 'Default template cannot be restored';916 const errorToast = !presetManager.isAdvancedFormatting() ? t`Default preset cannot be restored` : t`Default template cannot be restored`;
876 toastr.error(errorToast);917 toastr.error(errorToast);
877 return;918 return;
878 }919 }
879920
880 const confirmText = !presetManager.isAdvancedFormatting()921 const confirmText = !presetManager.isAdvancedFormatting()
881 ? 'Resetting a <b>default preset</b> will restore the default settings.'922 ? t`Resetting a <b>default preset</b> will restore the default settings.`
882 : 'Resetting a <b>default template</b> will restore the default settings.';923 : t`Resetting a <b>default template</b> will restore the default settings.`;
883 const confirm = await Popup.show.confirm('Are you sure?', confirmText);924 const confirm = await Popup.show.confirm(t`Are you sure?`, confirmText);
884 if (!confirm) {925 if (!confirm) {
885 return;926 return;
886 }927 }
887928
888 await presetManager.deleteCurrentPreset();929 await presetManager.deletePreset();
889 await presetManager.savePreset(name, data.preset);930 await presetManager.savePreset(name, data.preset);
890 const option = presetManager.findPreset(name);931 const option = presetManager.findPreset(name);
891 presetManager.selectPreset(option);932 presetManager.selectPreset(option);
892 const successToast = !presetManager.isAdvancedFormatting() ? 'Default preset restored' : 'Default template restored';933 const successToast = !presetManager.isAdvancedFormatting() ? t`Default preset restored` : t`Default template restored`;
893 toastr.success(successToast);934 toastr.success(successToast);
894 } else {935 } else {
895 const confirmText = !presetManager.isAdvancedFormatting()936 const confirmText = !presetManager.isAdvancedFormatting()
896 ? 'Resetting a <b>custom preset</b> will restore to the last saved state.'937 ? t`Resetting a <b>custom preset</b> will restore to the last saved state.`
897 : 'Resetting a <b>custom template</b> will restore to the last saved state.';938 : t`Resetting a <b>custom template</b> will restore to the last saved state.`;
898 const confirm = await Popup.show.confirm('Are you sure?', confirmText);939 const confirm = await Popup.show.confirm(t`Are you sure?`, confirmText);
899 if (!confirm) {940 if (!confirm) {
900 return;941 return;
901 }942 }
902943
903 const option = presetManager.findPreset(name);944 const option = presetManager.findPreset(name);
904 presetManager.selectPreset(option);945 presetManager.selectPreset(option);
905 const successToast = !presetManager.isAdvancedFormatting() ? 'Preset restored' : 'Template restored';946 const successToast = !presetManager.isAdvancedFormatting() ? t`Preset restored` : t`Template restored`;
906 toastr.success(successToast);947 toastr.success(successToast);
907 }948 }
908 });949 });