Merge pull request #2955 from Yokayo/staging Add rename buttons for advanced formatting presets
Signed| @@ -3178,9 +3178,10 @@ | |||
| 3178 | </h4> | 3178 | </h4> |
| 3179 | <div class="flex-container" title="Select your current Context Template" data-i18n="[title]Select your current Context Template"> | 3179 | <div class="flex-container" title="Select your current Context Template" data-i18n="[title]Select your current Context Template"> |
| 3180 | <select id="context_presets" data-preset-manager-for="context" class="flex1 text_pole"></select> | 3180 | <select id="context_presets" data-preset-manager-for="context" class="flex1 text_pole"></select> |
| 3181 | <div class="flex-container justifyCenter"> | 3181 | <div class="flex-container justifyCenter gap3px"> |
| 3182 | <input type="file" hidden data-preset-manager-file="context" accept=".json, .settings"> | 3182 | <input type="file" hidden data-preset-manager-file="context" accept=".json, .settings"> |
| 3183 | <i data-preset-manager-update="context" class="menu_button fa-solid fa-save" title="Update current template" data-i18n="[title]Update current template"></i> | 3183 | <i data-preset-manager-update="context" class="menu_button fa-solid fa-save" title="Update current template" data-i18n="[title]Update current template"></i> |
| 3184 | <i data-preset-manager-rename="context" class="menu_button fa-pencil fa-solid" title="Rename current template" data-i18n="[title]Rename current template"></i> | ||
| 3184 | <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> | 3185 | <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> |
| 3185 | <i data-preset-manager-import="context" class="displayNone menu_button fa-solid fa-file-import" title="Import template" data-i18n="[title]Import template"></i> | 3186 | <i data-preset-manager-import="context" class="displayNone menu_button fa-solid fa-file-import" title="Import template" data-i18n="[title]Import template"></i> |
| 3186 | <i data-preset-manager-export="context" class="displayNone menu_button fa-solid fa-file-export" title="Export template" data-i18n="[title]Export template"></i> | 3187 | <i data-preset-manager-export="context" class="displayNone menu_button fa-solid fa-file-export" title="Export template" data-i18n="[title]Export template"></i> |
| @@ -3289,9 +3290,10 @@ | |||
| 3289 | 3290 | ||
| 3290 | <div class="flex-container" title="Select your current Instruct Template" data-i18n="[title]Select your current Instruct Template"> | 3291 | <div class="flex-container" title="Select your current Instruct Template" data-i18n="[title]Select your current Instruct Template"> |
| 3291 | <select id="instruct_presets" data-preset-manager-for="instruct" class="flex1 text_pole"></select> | 3292 | <select id="instruct_presets" data-preset-manager-for="instruct" class="flex1 text_pole"></select> |
| 3292 | <div class="flex-container margin0 justifyCenter"> | 3293 | <div class="flex-container margin0 justifyCenter gap3px"> |
| 3293 | <input type="file" hidden data-preset-manager-file="instruct" accept=".json, .settings"> | 3294 | <input type="file" hidden data-preset-manager-file="instruct" accept=".json, .settings"> |
| 3294 | <i data-preset-manager-update="instruct" class="menu_button fa-solid fa-save" title="Update current template" data-i18n="[title]Update current template"></i> | 3295 | <i data-preset-manager-update="instruct" class="menu_button fa-solid fa-save" title="Update current template" data-i18n="[title]Update current template"></i> |
| 3296 | <i data-preset-manager-rename="instruct" class="menu_button fa-pencil fa-solid" title="Rename current template" data-i18n="[title]Rename current template"></i> | ||
| 3295 | <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> | 3297 | <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> |
| 3296 | <i data-preset-manager-import="instruct" class="displayNone menu_button fa-solid fa-file-import" title="Import template" data-i18n="[title]Import template"></i> | 3298 | <i data-preset-manager-import="instruct" class="displayNone menu_button fa-solid fa-file-import" title="Import template" data-i18n="[title]Import template"></i> |
| 3297 | <i data-preset-manager-export="instruct" class="displayNone menu_button fa-solid fa-file-export" title="Export template" data-i18n="[title]Export template"></i> | 3299 | <i data-preset-manager-export="instruct" class="displayNone menu_button fa-solid fa-file-export" title="Export template" data-i18n="[title]Export template"></i> |
| @@ -3469,9 +3471,10 @@ | |||
| 3469 | 3471 | ||
| 3470 | <div class="flex-container" title="Select your current System Prompt" data-i18n="[title]Select your current System Prompt"> | 3472 | <div class="flex-container" title="Select your current System Prompt" data-i18n="[title]Select your current System Prompt"> |
| 3471 | <select id="sysprompt_select" data-preset-manager-for="sysprompt" class="flex1 text_pole"></select> | 3473 | <select id="sysprompt_select" data-preset-manager-for="sysprompt" class="flex1 text_pole"></select> |
| 3472 | <div class="flex-container margin0 justifyCenter"> | 3474 | <div class="flex-container margin0 justifyCenter gap3px"> |
| 3473 | <input type="file" hidden data-preset-manager-file="sysprompt" accept=".json, .settings"> | 3475 | <input type="file" hidden data-preset-manager-file="sysprompt" accept=".json, .settings"> |
| 3474 | <i data-preset-manager-update="sysprompt" class="menu_button fa-solid fa-save" title="Update current prompt" data-i18n="[title]Update current prompt"></i> | 3476 | <i data-preset-manager-update="sysprompt" class="menu_button fa-solid fa-save" title="Update current prompt" data-i18n="[title]Update current prompt"></i> |
| 3477 | <i data-preset-manager-rename="sysprompt" class="menu_button fa-pencil fa-solid" title="Rename current prompt" data-i18n="[title]Rename current prompt"></i> | ||
| 3475 | <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> | 3478 | <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> |
| 3476 | <i data-preset-manager-import="sysprompt" class="displayNone menu_button fa-solid fa-file-import" title="Import template" data-i18n="[title]Import template"></i> | 3479 | <i data-preset-manager-import="sysprompt" class="displayNone menu_button fa-solid fa-file-import" title="Import template" data-i18n="[title]Import template"></i> |
| 3477 | <i data-preset-manager-export="sysprompt" class="displayNone menu_button fa-solid fa-file-export" title="Export template" data-i18n="[title]Export template"></i> | 3480 | <i data-preset-manager-export="sysprompt" class="displayNone menu_button fa-solid fa-file-export" title="Export template" data-i18n="[title]Export template"></i> |
| @@ -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,71 @@ | |||
| 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-режима", | ||
| 1957 | "and connect to an": "и подключитесь к", | ||
| 1958 | "You can add more": "Можете добавить больше", | ||
| 1959 | "from other websites": "с других сайтов.", | ||
| 1960 | "Go to the": "Загляните в", | ||
| 1961 | "to install additional features.": ", чтобы установить разные дополнительные ресурсы.", | ||
| 1962 | "or_welcome": "; также доступен" | ||
| 1897 | } | 1963 | } |
| @@ -6755,7 +6755,7 @@ export async function saveSettings(type) { | |||
| 6755 | eventSource.emit(event_types.SETTINGS_UPDATED); | 6755 | eventSource.emit(event_types.SETTINGS_UPDATED); |
| 6756 | }, | 6756 | }, |
| 6757 | error: function (jqXHR, exception) { | 6757 | error: function (jqXHR, exception) { |
| 6758 | toastr.error(t`Check the server connection and reload the page to prevent data loss.t`, t`Settings could not be saved`); | 6758 | toastr.error(t`Check the server connection and reload the page to prevent data loss.`, t`Settings could not be saved`); |
| 6759 | console.log(exception); | 6759 | console.log(exception); |
| 6760 | console.log(jqXHR); | 6760 | console.log(jqXHR); |
| 6761 | }, | 6761 | }, |
| @@ -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'; |
| 36 | import { download, parseJsonFile, waitUntilCondition } from './utils.js'; | 36 | import { download, parseJsonFile, waitUntilCondition } from './utils.js'; |
| 37 | import { t } from './i18n.js'; | ||
| 37 | 38 | ||
| 38 | const presetManagers = {}; | 39 | const presetManagers = {}; |
| 39 | 40 | ||
| @@ -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 | } |
| 200 | 201 | ||
| 201 | // Check for legacy file imports | 202 | // Check for legacy file imports |
| 202 | // 1. Instruct Template | 203 | // 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 | } |
| 207 | 208 | ||
| 208 | // 2. Context Template | 209 | // 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 | } |
| 213 | 214 | ||
| 214 | // 3. System Prompt | 215 | // 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 | } |
| 219 | 220 | ||
| 220 | // 4. Text Completion settings | 221 | // 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 | } |
| 225 | 226 | ||
| @@ -231,7 +232,7 @@ class PresetManager { | |||
| 231 | } | 232 | } |
| 232 | 233 | ||
| 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 | } |
| 237 | 238 | ||
| @@ -242,8 +243,8 @@ class PresetManager { | |||
| 242 | 243 | ||
| 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 | }); |
| 248 | 249 | ||
| 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(); |
| 258 | 259 | ||
| 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 | } |
| 263 | 264 | ||
| @@ -270,7 +271,7 @@ class PresetManager { | |||
| 270 | } | 271 | } |
| 271 | } | 272 | } |
| 272 | 273 | ||
| 273 | toastr.success(`Imported ${importedSections.length} settings: ${importedSections.join(', ')}`); | 274 | toastr.success(t`Imported ${importedSections.length} settings: ${importedSections.join(', ')}`); |
| 274 | } | 275 | } |
| 275 | 276 | ||
| 276 | /** | 277 | /** |
| @@ -285,8 +286,8 @@ class PresetManager { | |||
| 285 | const html = $(await renderTemplateAsync('masterExport', { sections: sectionNames })); | 286 | const html = $(await renderTemplateAsync('masterExport', { sections: sectionNames })); |
| 286 | 287 | ||
| 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 | }); |
| 291 | 292 | ||
| 292 | const result = await popup.show(); | 293 | const result = await popup.show(); |
| @@ -300,7 +301,7 @@ class PresetManager { | |||
| 300 | const data = {}; | 301 | const data = {}; |
| 301 | 302 | ||
| 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 | } |
| 306 | 307 | ||
| @@ -366,21 +367,21 @@ class PresetManager { | |||
| 366 | console.log(selected); | 367 | console.log(selected); |
| 367 | 368 | ||
| 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 | } |
| 372 | 373 | ||
| 373 | const name = selected.text(); | 374 | const name = selected.text(); |
| 374 | await this.savePreset(name); | 375 | await this.savePreset(name); |
| 375 | 376 | ||
| 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 | } |
| 379 | 380 | ||
| 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 { | |||
| 389 | 390 | ||
| 390 | await this.savePreset(name); | 391 | await this.savePreset(name); |
| 391 | 392 | ||
| 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 | } |
| 395 | 396 | ||
| @@ -411,7 +412,7 @@ class PresetManager { | |||
| 411 | }); | 412 | }); |
| 412 | 413 | ||
| 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 | } |
| @@ -422,6 +423,19 @@ class PresetManager { | |||
| 422 | this.updateList(name, preset); | 423 | this.updateList(name, preset); |
| 423 | } | 424 | } |
| 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 | } | ||
| 438 | |||
| 425 | getPresetList() { | 439 | getPresetList() { |
| 426 | let presets = []; | 440 | let presets = []; |
| 427 | let preset_names = {}; | 441 | let preset_names = {}; |
| @@ -585,13 +599,14 @@ class PresetManager { | |||
| 585 | return settings; | 599 | return settings; |
| 586 | } | 600 | } |
| 587 | 601 | ||
| 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(); |
| 592 | 607 | ||
| 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 | } |
| 597 | 612 | ||
| @@ -605,7 +620,10 @@ class PresetManager { | |||
| 605 | delete preset_names[nameToDelete]; | 620 | delete preset_names[nameToDelete]; |
| 606 | } | 621 | } |
| 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) { | ||
| 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 | }); |
| 630 | 648 | ||
| 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 | } |
| @@ -721,7 +739,8 @@ async function waitForConnection() { | |||
| 721 | export async function initPresetManager() { | 739 | export async function initPresetManager() { |
| 722 | eventSource.on(event_types.CHAT_CHANGED, autoSelectPreset); | 740 | eventSource.on(event_types.CHAT_CHANGED, autoSelectPreset); |
| 723 | registerPresetManagers(); | 741 | registerPresetManagers(); |
| 724 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'preset', | 742 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ |
| 743 | name: 'preset', | ||
| 725 | callback: presetCommandCallback, | 744 | callback: presetCommandCallback, |
| 726 | returns: 'current preset', | 745 | returns: 'current preset', |
| 727 | unnamedArgumentList: [ | 746 | unnamedArgumentList: [ |
| @@ -774,6 +793,29 @@ export async function initPresetManager() { | |||
| 774 | await presetManager.savePresetAs(); | 793 | await presetManager.savePresetAs(); |
| 775 | }); | 794 | }); |
| 776 | 795 | ||
| 796 | $(document).on('click', '[data-preset-manager-rename]', async function () { | ||
| 797 | const apiId = $(this).data('preset-manager-rename'); | ||
| 798 | const presetManager = getPresetManager(apiId); | ||
| 799 | |||
| 800 | if (!presetManager) { | ||
| 801 | console.warn(`Preset Manager not found for API: ${apiId}`); | ||
| 802 | return; | ||
| 803 | } | ||
| 804 | |||
| 805 | const popupHeader = !presetManager.isAdvancedFormatting() ? t`Rename preset` : t`Rename template`; | ||
| 806 | const oldName = presetManager.getSelectedPresetName(); | ||
| 807 | const newName = await Popup.show.input(popupHeader, t`Enter a new name:`, oldName); | ||
| 808 | if (!newName || oldName === newName) { | ||
| 809 | console.debug(!presetManager.isAdvancedFormatting() ? 'Preset rename cancelled' : 'Template rename cancelled'); | ||
| 810 | return; | ||
| 811 | } | ||
| 812 | |||
| 813 | await presetManager.renamePreset(newName); | ||
| 814 | |||
| 815 | const successToast = !presetManager.isAdvancedFormatting() ? t`Preset renamed` : t`Template renamed`; | ||
| 816 | toastr.success(successToast); | ||
| 817 | }); | ||
| 818 | |||
| 777 | $(document).on('click', '[data-preset-manager-export]', async function () { | 819 | $(document).on('click', '[data-preset-manager-export]', async function () { |
| 778 | const apiId = $(this).data('preset-manager-export'); | 820 | const apiId = $(this).data('preset-manager-export'); |
| 779 | const presetManager = getPresetManager(apiId); | 821 | const presetManager = getPresetManager(apiId); |
| @@ -816,7 +858,7 @@ export async function initPresetManager() { | |||
| 816 | data['name'] = name; | 858 | data['name'] = name; |
| 817 | 859 | ||
| 818 | await presetManager.savePreset(name, data); | 860 | await presetManager.savePreset(name, data); |
| 819 | const successToast = !presetManager.isAdvancedFormatting() ? 'Preset imported' : 'Template imported'; | 861 | const successToast = !presetManager.isAdvancedFormatting() ? t`Preset imported` : t`Template imported`; |
| 820 | toastr.success(successToast); | 862 | toastr.success(successToast); |
| 821 | e.target.value = null; | 863 | e.target.value = null; |
| 822 | }); | 864 | }); |
| @@ -830,19 +872,19 @@ export async function initPresetManager() { | |||
| 830 | return; | 872 | return; |
| 831 | } | 873 | } |
| 832 | 874 | ||
| 833 | const headerText = !presetManager.isAdvancedFormatting() ? 'Delete this preset?' : 'Delete this template?'; | 875 | 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.'); | 876 | const confirm = await Popup.show.confirm(headerText, t`This action is irreversible and your current settings will be overwritten.`); |
| 835 | if (!confirm) { | 877 | if (!confirm) { |
| 836 | return; | 878 | return; |
| 837 | } | 879 | } |
| 838 | 880 | ||
| 839 | const result = await presetManager.deleteCurrentPreset(); | 881 | const result = await presetManager.deletePreset(); |
| 840 | 882 | ||
| 841 | if (result) { | 883 | if (result) { |
| 842 | const successToast = !presetManager.isAdvancedFormatting() ? 'Preset deleted' : 'Template deleted'; | 884 | const successToast = !presetManager.isAdvancedFormatting() ? t`Preset deleted` : t`Template deleted`; |
| 843 | toastr.success(successToast); | 885 | toastr.success(successToast); |
| 844 | } else { | 886 | } else { |
| 845 | const warningToast = !presetManager.isAdvancedFormatting() ? 'Preset was not deleted from server' : 'Template was not deleted from server'; | 887 | const warningToast = !presetManager.isAdvancedFormatting() ? t`Preset was not deleted from server` : t`Template was not deleted from server`; |
| 846 | toastr.warning(warningToast); | 888 | toastr.warning(warningToast); |
| 847 | } | 889 | } |
| 848 | 890 | ||
| @@ -862,7 +904,7 @@ export async function initPresetManager() { | |||
| 862 | const data = await presetManager.getDefaultPreset(name); | 904 | const data = await presetManager.getDefaultPreset(name); |
| 863 | 905 | ||
| 864 | if (name == 'gui') { | 906 | if (name == 'gui') { |
| 865 | toastr.info('Cannot restore GUI preset'); | 907 | toastr.info(t`Cannot restore GUI preset`); |
| 866 | return; | 908 | return; |
| 867 | } | 909 | } |
| 868 | 910 | ||
| @@ -872,37 +914,37 @@ export async function initPresetManager() { | |||
| 872 | 914 | ||
| 873 | if (data.isDefault) { | 915 | if (data.isDefault) { |
| 874 | if (Object.keys(data.preset).length === 0) { | 916 | if (Object.keys(data.preset).length === 0) { |
| 875 | const errorToast = !presetManager.isAdvancedFormatting() ? 'Default preset cannot be restored' : 'Default template cannot be restored'; | 917 | const errorToast = !presetManager.isAdvancedFormatting() ? t`Default preset cannot be restored` : t`Default template cannot be restored`; |
| 876 | toastr.error(errorToast); | 918 | toastr.error(errorToast); |
| 877 | return; | 919 | return; |
| 878 | } | 920 | } |
| 879 | 921 | ||
| 880 | const confirmText = !presetManager.isAdvancedFormatting() | 922 | const confirmText = !presetManager.isAdvancedFormatting() |
| 881 | ? 'Resetting a <b>default preset</b> will restore the default settings.' | 923 | ? t`Resetting a <b>default preset</b> will restore the default settings.` |
| 882 | : 'Resetting a <b>default template</b> will restore the default settings.'; | 924 | : t`Resetting a <b>default template</b> will restore the default settings.`; |
| 883 | const confirm = await Popup.show.confirm('Are you sure?', confirmText); | 925 | const confirm = await Popup.show.confirm(t`Are you sure?`, confirmText); |
| 884 | if (!confirm) { | 926 | if (!confirm) { |
| 885 | return; | 927 | return; |
| 886 | } | 928 | } |
| 887 | 929 | ||
| 888 | await presetManager.deleteCurrentPreset(); | 930 | await presetManager.deletePreset(); |
| 889 | await presetManager.savePreset(name, data.preset); | 931 | await presetManager.savePreset(name, data.preset); |
| 890 | const option = presetManager.findPreset(name); | 932 | const option = presetManager.findPreset(name); |
| 891 | presetManager.selectPreset(option); | 933 | presetManager.selectPreset(option); |
| 892 | const successToast = !presetManager.isAdvancedFormatting() ? 'Default preset restored' : 'Default template restored'; | 934 | const successToast = !presetManager.isAdvancedFormatting() ? t`Default preset restored` : t`Default template restored`; |
| 893 | toastr.success(successToast); | 935 | toastr.success(successToast); |
| 894 | } else { | 936 | } else { |
| 895 | const confirmText = !presetManager.isAdvancedFormatting() | 937 | const confirmText = !presetManager.isAdvancedFormatting() |
| 896 | ? 'Resetting a <b>custom preset</b> will restore to the last saved state.' | 938 | ? 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.'; | 939 | : 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); | 940 | const confirm = await Popup.show.confirm(t`Are you sure?`, confirmText); |
| 899 | if (!confirm) { | 941 | if (!confirm) { |
| 900 | return; | 942 | return; |
| 901 | } | 943 | } |
| 902 | 944 | ||
| 903 | const option = presetManager.findPreset(name); | 945 | const option = presetManager.findPreset(name); |
| 904 | presetManager.selectPreset(option); | 946 | presetManager.selectPreset(option); |
| 905 | const successToast = !presetManager.isAdvancedFormatting() ? 'Preset restored' : 'Template restored'; | 947 | const successToast = !presetManager.isAdvancedFormatting() ? t`Preset restored` : t`Template restored`; |
| 906 | toastr.success(successToast); | 948 | toastr.success(successToast); |
| 907 | } | 949 | } |
| 908 | }); | 950 | }); |
| @@ -10,7 +10,7 @@ | |||
| 10 | <span data-i18n="Click _space">Click </span> | 10 | <span data-i18n="Click _space">Click </span> |
| 11 | <button class="menu_button menu_button_icon drawer-opener inline-flex" data-target="sys-settings-button"> | 11 | <button class="menu_button menu_button_icon drawer-opener inline-flex" data-target="sys-settings-button"> |
| 12 | <i class="fa-solid fa-plug"></i> | 12 | <i class="fa-solid fa-plug"></i> |
| 13 | <span data-i18n="[title]API Connections">API Connections</span> | 13 | <span data-i18n="API Connections">API Connections</span> |
| 14 | </button> | 14 | </button> |
| 15 | <span data-i18n="and connect to an">and connect to an</span> | 15 | <span data-i18n="and connect to an">and connect to an</span> |
| 16 | <a href="https://docs.sillytavern.app/usage/api-connections/" target="_blank"> | 16 | <a href="https://docs.sillytavern.app/usage/api-connections/" target="_blank"> |
| @@ -21,7 +21,7 @@ | |||
| 21 | <span data-i18n="Click _space">Click </span> | 21 | <span data-i18n="Click _space">Click </span> |
| 22 | <button class="menu_button menu_button_icon drawer-opener inline-flex" data-target="rightNavHolder"> | 22 | <button class="menu_button menu_button_icon drawer-opener inline-flex" data-target="rightNavHolder"> |
| 23 | <i class="fa-solid fa-address-card"></i> | 23 | <i class="fa-solid fa-address-card"></i> |
| 24 | <span data-i18n="[title]Character Management">Character Management</span> | 24 | <span data-i18n="Character Management">Character Management</span> |
| 25 | </button> | 25 | </button> |
| 26 | <span data-i18n="and pick a character."> and pick a character.</span> | 26 | <span data-i18n="and pick a character."> and pick a character.</span> |
| 27 | </li> | 27 | </li> |
| @@ -33,7 +33,7 @@ | |||
| 33 | <i class="fa-solid fa-image-portrait"></i> | 33 | <i class="fa-solid fa-image-portrait"></i> |
| 34 | <span data-i18n="Sample characters">Sample characters</span> | 34 | <span data-i18n="Sample characters">Sample characters</span> |
| 35 | </button> | 35 | </button> |
| 36 | <span data-i18n="or">or</span> | 36 | <span data-i18n="or_welcome">or</span> |
| 37 | <button class="external_import_button menu_button menu_button_icon inline-flex"> | 37 | <button class="external_import_button menu_button menu_button_icon inline-flex"> |
| 38 | <i class="fa-solid fa-cloud-arrow-down"></i> | 38 | <i class="fa-solid fa-cloud-arrow-down"></i> |
| 39 | <span data-i18n="Import Characters">Import characters</span> | 39 | <span data-i18n="Import Characters">Import characters</span> |
| @@ -48,7 +48,7 @@ | |||
| 48 | 48 | ||
| 49 | <button class="menu_button menu_button_icon drawer-opener inline-flex" data-target="extensions-settings-button"> | 49 | <button class="menu_button menu_button_icon drawer-opener inline-flex" data-target="extensions-settings-button"> |
| 50 | <i class="fa-solid fa-cubes"></i> | 50 | <i class="fa-solid fa-cubes"></i> |
| 51 | <span data-i18n="[title]Extensions">Extensions</span> | 51 | <span data-i18n="Extensions">Extensions</span> |
| 52 | </button> | 52 | </button> |
| 53 | 53 | ||
| 54 | <span data-i18n="to install additional features.">to install additional features.</span> | 54 | <span data-i18n="to install additional features.">to install additional features.</span> |