mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-09-20 18:51:26 -03:00
feat(settings): split overloaded Library tab into a new Organization tab
Move download path templates, priority tags, and auto-organize exclusions out of the Library settings section into a dedicated Organization section, so Library keeps location-focused settings (roots, extra paths, example images, metadata) and Organization holds file-arrangement rules. Translated settings.nav.organization for all locales.
This commit is contained in:
@@ -66,6 +66,11 @@ Locales: `en`, `zh-CN`, `zh-TW`, `ja`, `ko`, `fr`, `de`, `es`, `ru`, `he` (RTL).
|
|||||||
> section" — and re-translated in all 9 locales. The `on disk` phrase now survives only in
|
> section" — and re-translated in all 9 locales. The `on disk` phrase now survives only in
|
||||||
> the ComfyUI variant (`descriptionComfyUI`).
|
> the ComfyUI variant (`descriptionComfyUI`).
|
||||||
|
|
||||||
|
> **Status (2026-09, settings Organization tab):** the settings modal split its overloaded
|
||||||
|
> Library tab, adding the single `settings.nav.organization` key (renderings in §2,
|
||||||
|
> "Settings Organization tab"). All 9 locales are translated, so the "no remaining
|
||||||
|
> placeholders" claim holds again.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Hard rules (do not violate)
|
## 1. Hard rules (do not violate)
|
||||||
@@ -371,6 +376,27 @@ clause (and its `—`) when the copy is edited. The `{name}` / `{count}` / `{mes
|
|||||||
`sidebar.createFolderResult.*`, `sidebar.deleteFolderResult.*` and `sidebar.renameFolderResult.*`
|
`sidebar.createFolderResult.*`, `sidebar.deleteFolderResult.*` and `sidebar.renameFolderResult.*`
|
||||||
are verbatim §1-R2 placeholders; `successWithFiles` is the only key carrying `{count}`.
|
are verbatim §1-R2 placeholders; `successWithFiles` is the only key carrying `{count}`.
|
||||||
|
|
||||||
|
### Settings Organization tab
|
||||||
|
|
||||||
|
The settings modal's fourth nav tab groups everything about how files are arranged on
|
||||||
|
disk: download path templates, priority tags, and auto-organize exclusions. The label is
|
||||||
|
the **noun for arranging files**, matching each locale's existing
|
||||||
|
`settings.sections.autoOrganize` rendering minus the "auto":
|
||||||
|
|
||||||
|
| Locale | `settings.nav.organization` |
|
||||||
|
|---|---|
|
||||||
|
| fr | Organisation |
|
||||||
|
| zh-CN | 整理 |
|
||||||
|
| zh-TW | 整理 |
|
||||||
|
| ja | 整理 |
|
||||||
|
| ko | 정리 |
|
||||||
|
| de | Organisation |
|
||||||
|
| es | Organización |
|
||||||
|
| ru | Организация |
|
||||||
|
| he | ארגון |
|
||||||
|
|
||||||
|
zh-CN/zh-TW use 整理 ("tidying/arranging"), not 组织/組織 (an organization as a group).
|
||||||
|
|
||||||
### Chip reordering (model tags / trigger words)
|
### Chip reordering (model tags / trigger words)
|
||||||
|
|
||||||
Model tags and trigger-word chips share a single reorder affordance (drag the chip, or its
|
Model tags and trigger-word chips share a single reorder affordance (drag the chip, or its
|
||||||
|
|||||||
@@ -383,6 +383,7 @@
|
|||||||
"general": "Allgemein",
|
"general": "Allgemein",
|
||||||
"interface": "Oberfläche",
|
"interface": "Oberfläche",
|
||||||
"library": "Bibliothek",
|
"library": "Bibliothek",
|
||||||
|
"organization": "Organisation",
|
||||||
"modelPaths": "Modellpfade"
|
"modelPaths": "Modellpfade"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
|
|||||||
@@ -383,6 +383,7 @@
|
|||||||
"general": "General",
|
"general": "General",
|
||||||
"interface": "Interface",
|
"interface": "Interface",
|
||||||
"library": "Library",
|
"library": "Library",
|
||||||
|
"organization": "Organization",
|
||||||
"modelPaths": "Model Paths"
|
"modelPaths": "Model Paths"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
|
|||||||
@@ -383,6 +383,7 @@
|
|||||||
"general": "General",
|
"general": "General",
|
||||||
"interface": "Interfaz",
|
"interface": "Interfaz",
|
||||||
"library": "Biblioteca",
|
"library": "Biblioteca",
|
||||||
|
"organization": "Organización",
|
||||||
"modelPaths": "Rutas de modelos"
|
"modelPaths": "Rutas de modelos"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
|
|||||||
@@ -383,6 +383,7 @@
|
|||||||
"general": "Général",
|
"general": "Général",
|
||||||
"interface": "Interface",
|
"interface": "Interface",
|
||||||
"library": "Bibliothèque",
|
"library": "Bibliothèque",
|
||||||
|
"organization": "Organisation",
|
||||||
"modelPaths": "Chemins de modèles"
|
"modelPaths": "Chemins de modèles"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
|
|||||||
@@ -383,6 +383,7 @@
|
|||||||
"general": "כללי",
|
"general": "כללי",
|
||||||
"interface": "ממשק",
|
"interface": "ממשק",
|
||||||
"library": "ספרייה",
|
"library": "ספרייה",
|
||||||
|
"organization": "ארגון",
|
||||||
"modelPaths": "נתיבי מודלים"
|
"modelPaths": "נתיבי מודלים"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
|
|||||||
@@ -383,6 +383,7 @@
|
|||||||
"general": "一般",
|
"general": "一般",
|
||||||
"interface": "インターフェース",
|
"interface": "インターフェース",
|
||||||
"library": "ライブラリ",
|
"library": "ライブラリ",
|
||||||
|
"organization": "整理",
|
||||||
"modelPaths": "モデルパス"
|
"modelPaths": "モデルパス"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
|
|||||||
@@ -383,6 +383,7 @@
|
|||||||
"general": "일반",
|
"general": "일반",
|
||||||
"interface": "인터페이스",
|
"interface": "인터페이스",
|
||||||
"library": "라이브러리",
|
"library": "라이브러리",
|
||||||
|
"organization": "정리",
|
||||||
"modelPaths": "모델 경로"
|
"modelPaths": "모델 경로"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
|
|||||||
@@ -383,6 +383,7 @@
|
|||||||
"general": "Общее",
|
"general": "Общее",
|
||||||
"interface": "Интерфейс",
|
"interface": "Интерфейс",
|
||||||
"library": "Библиотека",
|
"library": "Библиотека",
|
||||||
|
"organization": "Организация",
|
||||||
"modelPaths": "Пути к моделям"
|
"modelPaths": "Пути к моделям"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
|
|||||||
@@ -383,6 +383,7 @@
|
|||||||
"general": "通用",
|
"general": "通用",
|
||||||
"interface": "界面",
|
"interface": "界面",
|
||||||
"library": "库",
|
"library": "库",
|
||||||
|
"organization": "整理",
|
||||||
"modelPaths": "模型路径"
|
"modelPaths": "模型路径"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
|
|||||||
@@ -383,6 +383,7 @@
|
|||||||
"general": "通用",
|
"general": "通用",
|
||||||
"interface": "介面",
|
"interface": "介面",
|
||||||
"library": "模型庫",
|
"library": "模型庫",
|
||||||
|
"organization": "整理",
|
||||||
"modelPaths": "模型路徑"
|
"modelPaths": "模型路徑"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
|
|||||||
@@ -1,15 +1,4 @@
|
|||||||
{% import 'components/modals/settings/_macros.html' as sm with context %}
|
{% import 'components/modals/settings/_macros.html' as sm with context %}
|
||||||
{% set template_preset_options = [
|
|
||||||
('', 'settings.downloadPathTemplates.templateOptions.flatStructure'),
|
|
||||||
('{base_model}', 'settings.downloadPathTemplates.templateOptions.byBaseModel'),
|
|
||||||
('{author}', 'settings.downloadPathTemplates.templateOptions.byAuthor'),
|
|
||||||
('{first_tag}', 'settings.downloadPathTemplates.templateOptions.byFirstTag'),
|
|
||||||
('{base_model}/{first_tag}', 'settings.downloadPathTemplates.templateOptions.baseModelFirstTag'),
|
|
||||||
('{base_model}/{author}', 'settings.downloadPathTemplates.templateOptions.baseModelAuthor'),
|
|
||||||
('{author}/{first_tag}', 'settings.downloadPathTemplates.templateOptions.authorFirstTag'),
|
|
||||||
('{base_model}/{author}/{first_tag}', 'settings.downloadPathTemplates.templateOptions.baseModelAuthorFirstTag'),
|
|
||||||
('custom', 'settings.downloadPathTemplates.templateOptions.customTemplate'),
|
|
||||||
] %}
|
|
||||||
<!-- Section 3: Library -->
|
<!-- Section 3: Library -->
|
||||||
<div id="section-library" class="settings-section" data-section="library">
|
<div id="section-library" class="settings-section" data-section="library">
|
||||||
<!-- Folder Settings -->
|
<!-- Folder Settings -->
|
||||||
@@ -187,192 +176,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Download Path Templates -->
|
|
||||||
<div class="settings-subsection">
|
|
||||||
<div class="settings-subsection-header">
|
|
||||||
<h4>
|
|
||||||
{{ t('settings.downloadPathTemplates.title') }}
|
|
||||||
<i class="fas fa-info-circle info-icon" data-tooltip="{{ t('settings.downloadPathTemplates.help') }}"></i>
|
|
||||||
</h4>
|
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<div class="input-help">
|
|
||||||
<div class="placeholder-info">
|
|
||||||
<strong>{{ t('settings.downloadPathTemplates.availablePlaceholders') }}</strong>
|
|
||||||
<span class="placeholder-tag">{base_model}</span>
|
|
||||||
<span class="placeholder-tag">{author}</span>
|
|
||||||
<span class="placeholder-tag">{first_tag}</span>
|
|
||||||
<span class="placeholder-tag">{model_name}</span>
|
|
||||||
<span class="placeholder-tag">{version_name}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<div class="setting-row">
|
|
||||||
<div class="setting-info">
|
|
||||||
<label for="loraTemplatePreset">{{ t('settings.downloadPathTemplates.modelTypes.lora') }}</label>
|
|
||||||
</div>
|
|
||||||
<div class="setting-control select-control">
|
|
||||||
<select id="loraTemplatePreset" onchange="settingsManager.updateTemplatePreset('lora', this.value)">
|
|
||||||
{% for value, option_label in template_preset_options %}
|
|
||||||
<option value="{{ value }}">{{ t(option_label) }}</option>
|
|
||||||
{% endfor %}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="template-custom-row" id="loraCustomRow" style="display: none;">
|
|
||||||
<input type="text" id="loraCustomTemplate" class="template-custom-input" placeholder="{{ t('settings.downloadPathTemplates.customTemplatePlaceholder') }}" />
|
|
||||||
<div class="template-validation" id="loraValidation"></div>
|
|
||||||
</div>
|
|
||||||
<div class="template-preview" id="loraPreview"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<div class="setting-row">
|
|
||||||
<div class="setting-info">
|
|
||||||
<label for="checkpointTemplatePreset">{{ t('settings.downloadPathTemplates.modelTypes.checkpoint') }}</label>
|
|
||||||
</div>
|
|
||||||
<div class="setting-control select-control">
|
|
||||||
<select id="checkpointTemplatePreset" onchange="settingsManager.updateTemplatePreset('checkpoint', this.value)">
|
|
||||||
{% for value, option_label in template_preset_options %}
|
|
||||||
<option value="{{ value }}">{{ t(option_label) }}</option>
|
|
||||||
{% endfor %}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="template-custom-row" id="checkpointCustomRow" style="display: none;">
|
|
||||||
<input type="text" id="checkpointCustomTemplate" class="template-custom-input" placeholder="{{ t('settings.downloadPathTemplates.customTemplatePlaceholder') }}" />
|
|
||||||
<div class="template-validation" id="checkpointValidation"></div>
|
|
||||||
</div>
|
|
||||||
<div class="template-preview" id="checkpointPreview"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<div class="setting-row">
|
|
||||||
<div class="setting-info">
|
|
||||||
<label for="embeddingTemplatePreset">{{ t('settings.downloadPathTemplates.modelTypes.embedding') }}</label>
|
|
||||||
</div>
|
|
||||||
<div class="setting-control select-control">
|
|
||||||
<select id="embeddingTemplatePreset" onchange="settingsManager.updateTemplatePreset('embedding', this.value)">
|
|
||||||
{% for value, option_label in template_preset_options %}
|
|
||||||
<option value="{{ value }}">{{ t(option_label) }}</option>
|
|
||||||
{% endfor %}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="template-custom-row" id="embeddingCustomRow" style="display: none;">
|
|
||||||
<input type="text" id="embeddingCustomTemplate" class="template-custom-input" placeholder="{{ t('settings.downloadPathTemplates.customTemplatePlaceholder') }}" />
|
|
||||||
<div class="template-validation" id="embeddingValidation"></div>
|
|
||||||
</div>
|
|
||||||
<div class="template-preview" id="embeddingPreview"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<div class="setting-row">
|
|
||||||
<div class="setting-info">
|
|
||||||
<label>
|
|
||||||
{{ t('settings.downloadPathTemplates.baseModelPathMappings') }}
|
|
||||||
<i class="fas fa-info-circle info-icon" data-tooltip="{{ t('settings.downloadPathTemplates.baseModelPathMappingsHelp') }}"></i>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="setting-control">
|
|
||||||
<button type="button" class="add-mapping-btn" onclick="settingsManager.addMappingRow()">
|
|
||||||
<i class="fas fa-plus"></i>
|
|
||||||
<span>{{ t('settings.downloadPathTemplates.addMapping') }}</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="mappings-container">
|
|
||||||
<div id="baseModelMappingsContainer">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{ sm.setting_toggle('skipPreviouslyDownloadedModelVersions', 'skip_previously_downloaded_model_versions', 'settings.skipPreviouslyDownloadedModelVersions.label', 'settings.skipPreviouslyDownloadedModelVersions.help') }}
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<div class="setting-row">
|
|
||||||
<div class="setting-info">
|
|
||||||
<label for="downloadSkipBaseModelsToggle">
|
|
||||||
{{ t('settings.downloadSkipBaseModels.label') }}
|
|
||||||
<i class="fas fa-info-circle info-icon" data-tooltip="{{ t('settings.downloadSkipBaseModels.help') }}"></i>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="setting-control">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
id="downloadSkipBaseModelsToggle"
|
|
||||||
class="secondary-btn base-model-skip-toggle"
|
|
||||||
aria-expanded="false"
|
|
||||||
>
|
|
||||||
<span id="downloadSkipBaseModelsSummary">{{ t('settings.downloadSkipBaseModels.summary.none') }}</span>
|
|
||||||
<span class="base-model-skip-toggle-label">{{ t('settings.downloadSkipBaseModels.actions.edit') }}</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="downloadSkipBaseModelsPanel" class="base-model-skip-panel" hidden>
|
|
||||||
<div class="base-model-skip-toolbar">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
id="downloadSkipBaseModelsSearch"
|
|
||||||
class="base-model-skip-search"
|
|
||||||
placeholder="{{ t('settings.downloadSkipBaseModels.searchPlaceholder') }}"
|
|
||||||
/>
|
|
||||||
<button type="button" class="text-btn base-model-skip-clear" id="downloadSkipBaseModelsClear">
|
|
||||||
{{ t('settings.downloadSkipBaseModels.actions.clear') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div id="downloadSkipBaseModelsContainer" class="base-model-skip-list"></div>
|
|
||||||
<div id="downloadSkipBaseModelsEmpty" class="base-model-skip-empty" hidden>
|
|
||||||
{{ t('settings.downloadSkipBaseModels.empty') }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="settings-input-error-message" id="downloadSkipBaseModelsError"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Priority Tags -->
|
|
||||||
<div class="setting-item priority-tags-item">
|
|
||||||
<div class="setting-row priority-tags-header-row">
|
|
||||||
<div class="setting-info priority-tags-header">
|
|
||||||
<label>
|
|
||||||
{{ t('settings.priorityTags.title') }}
|
|
||||||
<i class="fas fa-info-circle info-icon" data-tooltip="{{ t('settings.priorityTags.description') }}"></i>
|
|
||||||
</label>
|
|
||||||
<a class="settings-action-link priority-tags-help-link" href="https://github.com/willmiao/ComfyUI-Lora-Manager/wiki/Priority-Tags-Configuration-Guide" target="_blank" rel="noopener" aria-label="{{ t('settings.priorityTags.helpLinkLabel') }}" title="{{ t('settings.priorityTags.helpLinkLabel') }}">
|
|
||||||
<i class="fas fa-question-circle" aria-hidden="true"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="priority-tags-tabs">
|
|
||||||
<input type="radio" id="priority-tags-tab-lora" name="priority-tags-tab" class="priority-tags-tab-input" checked>
|
|
||||||
<input type="radio" id="priority-tags-tab-checkpoint" name="priority-tags-tab" class="priority-tags-tab-input">
|
|
||||||
<input type="radio" id="priority-tags-tab-embedding" name="priority-tags-tab" class="priority-tags-tab-input">
|
|
||||||
|
|
||||||
<div class="priority-tags-tablist">
|
|
||||||
<label class="priority-tags-tab-label" for="priority-tags-tab-lora" id="priority-tags-tab-lora-label">{{ t('settings.priorityTags.modelTypes.lora') }}</label>
|
|
||||||
<label class="priority-tags-tab-label" for="priority-tags-tab-checkpoint" id="priority-tags-tab-checkpoint-label">{{ t('settings.priorityTags.modelTypes.checkpoint') }}</label>
|
|
||||||
<label class="priority-tags-tab-label" for="priority-tags-tab-embedding" id="priority-tags-tab-embedding-label">{{ t('settings.priorityTags.modelTypes.embedding') }}</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="priority-tags-panels">
|
|
||||||
<div class="priority-tags-panel" id="priority-tags-panel-lora">
|
|
||||||
<textarea id="loraPriorityTagsInput" class="priority-tags-input" placeholder="{{ t('settings.priorityTags.placeholder') }}"></textarea>
|
|
||||||
<div class="settings-input-error-message" id="loraPriorityTagsError"></div>
|
|
||||||
</div>
|
|
||||||
<div class="priority-tags-panel" id="priority-tags-panel-checkpoint">
|
|
||||||
<textarea id="checkpointPriorityTagsInput" class="priority-tags-input" placeholder="{{ t('settings.priorityTags.placeholder') }}"></textarea>
|
|
||||||
<div class="settings-input-error-message" id="checkpointPriorityTagsError"></div>
|
|
||||||
</div>
|
|
||||||
<div class="priority-tags-panel" id="priority-tags-panel-embedding">
|
|
||||||
<textarea id="embeddingPriorityTagsInput" class="priority-tags-input" placeholder="{{ t('settings.priorityTags.placeholder') }}"></textarea>
|
|
||||||
<div class="settings-input-error-message" id="embeddingPriorityTagsError"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Version Scope -->
|
<!-- Version Scope -->
|
||||||
<div class="settings-subsection">
|
<div class="settings-subsection">
|
||||||
{{ sm.subsection_header('settings.sections.versionScope') }}
|
{{ sm.subsection_header('settings.sections.versionScope') }}
|
||||||
@@ -463,25 +266,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Auto-organize -->
|
|
||||||
<div class="settings-subsection">
|
|
||||||
{{ sm.subsection_header('settings.sections.autoOrganize') }}
|
|
||||||
|
|
||||||
<!-- Auto-organize Exclusions -->
|
|
||||||
<div class="setting-item auto-organize-exclusions-item">
|
|
||||||
<div class="setting-row">
|
|
||||||
<div class="setting-info">
|
|
||||||
<label for="autoOrganizeExclusions">
|
|
||||||
{{ t('settings.autoOrganizeExclusions.label') }}
|
|
||||||
<i class="fas fa-info-circle info-icon" data-tooltip="{{ t('settings.autoOrganizeExclusions.help') }}"></i>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<textarea id="autoOrganizeExclusions" class="priority-tags-input auto-organize-exclusions-input" placeholder="{{ t('settings.autoOrganizeExclusions.placeholder') }}"></textarea>
|
|
||||||
<div class="settings-input-error-message" id="autoOrganizeExclusionsError"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Metadata -->
|
<!-- Metadata -->
|
||||||
<div class="settings-subsection">
|
<div class="settings-subsection">
|
||||||
{{ sm.subsection_header('settings.sections.metadata') }}
|
{{ sm.subsection_header('settings.sections.metadata') }}
|
||||||
|
|||||||
@@ -0,0 +1,219 @@
|
|||||||
|
{% import 'components/modals/settings/_macros.html' as sm with context %}
|
||||||
|
{% set template_preset_options = [
|
||||||
|
('', 'settings.downloadPathTemplates.templateOptions.flatStructure'),
|
||||||
|
('{base_model}', 'settings.downloadPathTemplates.templateOptions.byBaseModel'),
|
||||||
|
('{author}', 'settings.downloadPathTemplates.templateOptions.byAuthor'),
|
||||||
|
('{first_tag}', 'settings.downloadPathTemplates.templateOptions.byFirstTag'),
|
||||||
|
('{base_model}/{first_tag}', 'settings.downloadPathTemplates.templateOptions.baseModelFirstTag'),
|
||||||
|
('{base_model}/{author}', 'settings.downloadPathTemplates.templateOptions.baseModelAuthor'),
|
||||||
|
('{author}/{first_tag}', 'settings.downloadPathTemplates.templateOptions.authorFirstTag'),
|
||||||
|
('{base_model}/{author}/{first_tag}', 'settings.downloadPathTemplates.templateOptions.baseModelAuthorFirstTag'),
|
||||||
|
('custom', 'settings.downloadPathTemplates.templateOptions.customTemplate'),
|
||||||
|
] %}
|
||||||
|
<!-- Section 4: Organization -->
|
||||||
|
<div id="section-organization" class="settings-section" data-section="organization">
|
||||||
|
<!-- Download Path Templates -->
|
||||||
|
<div class="settings-subsection">
|
||||||
|
<div class="settings-subsection-header">
|
||||||
|
<h4>
|
||||||
|
{{ t('settings.downloadPathTemplates.title') }}
|
||||||
|
<i class="fas fa-info-circle info-icon" data-tooltip="{{ t('settings.downloadPathTemplates.help') }}"></i>
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="input-help">
|
||||||
|
<div class="placeholder-info">
|
||||||
|
<strong>{{ t('settings.downloadPathTemplates.availablePlaceholders') }}</strong>
|
||||||
|
<span class="placeholder-tag">{base_model}</span>
|
||||||
|
<span class="placeholder-tag">{author}</span>
|
||||||
|
<span class="placeholder-tag">{first_tag}</span>
|
||||||
|
<span class="placeholder-tag">{model_name}</span>
|
||||||
|
<span class="placeholder-tag">{version_name}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-row">
|
||||||
|
<div class="setting-info">
|
||||||
|
<label for="loraTemplatePreset">{{ t('settings.downloadPathTemplates.modelTypes.lora') }}</label>
|
||||||
|
</div>
|
||||||
|
<div class="setting-control select-control">
|
||||||
|
<select id="loraTemplatePreset" onchange="settingsManager.updateTemplatePreset('lora', this.value)">
|
||||||
|
{% for value, option_label in template_preset_options %}
|
||||||
|
<option value="{{ value }}">{{ t(option_label) }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="template-custom-row" id="loraCustomRow" style="display: none;">
|
||||||
|
<input type="text" id="loraCustomTemplate" class="template-custom-input" placeholder="{{ t('settings.downloadPathTemplates.customTemplatePlaceholder') }}" />
|
||||||
|
<div class="template-validation" id="loraValidation"></div>
|
||||||
|
</div>
|
||||||
|
<div class="template-preview" id="loraPreview"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-row">
|
||||||
|
<div class="setting-info">
|
||||||
|
<label for="checkpointTemplatePreset">{{ t('settings.downloadPathTemplates.modelTypes.checkpoint') }}</label>
|
||||||
|
</div>
|
||||||
|
<div class="setting-control select-control">
|
||||||
|
<select id="checkpointTemplatePreset" onchange="settingsManager.updateTemplatePreset('checkpoint', this.value)">
|
||||||
|
{% for value, option_label in template_preset_options %}
|
||||||
|
<option value="{{ value }}">{{ t(option_label) }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="template-custom-row" id="checkpointCustomRow" style="display: none;">
|
||||||
|
<input type="text" id="checkpointCustomTemplate" class="template-custom-input" placeholder="{{ t('settings.downloadPathTemplates.customTemplatePlaceholder') }}" />
|
||||||
|
<div class="template-validation" id="checkpointValidation"></div>
|
||||||
|
</div>
|
||||||
|
<div class="template-preview" id="checkpointPreview"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-row">
|
||||||
|
<div class="setting-info">
|
||||||
|
<label for="embeddingTemplatePreset">{{ t('settings.downloadPathTemplates.modelTypes.embedding') }}</label>
|
||||||
|
</div>
|
||||||
|
<div class="setting-control select-control">
|
||||||
|
<select id="embeddingTemplatePreset" onchange="settingsManager.updateTemplatePreset('embedding', this.value)">
|
||||||
|
{% for value, option_label in template_preset_options %}
|
||||||
|
<option value="{{ value }}">{{ t(option_label) }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="template-custom-row" id="embeddingCustomRow" style="display: none;">
|
||||||
|
<input type="text" id="embeddingCustomTemplate" class="template-custom-input" placeholder="{{ t('settings.downloadPathTemplates.customTemplatePlaceholder') }}" />
|
||||||
|
<div class="template-validation" id="embeddingValidation"></div>
|
||||||
|
</div>
|
||||||
|
<div class="template-preview" id="embeddingPreview"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-row">
|
||||||
|
<div class="setting-info">
|
||||||
|
<label>
|
||||||
|
{{ t('settings.downloadPathTemplates.baseModelPathMappings') }}
|
||||||
|
<i class="fas fa-info-circle info-icon" data-tooltip="{{ t('settings.downloadPathTemplates.baseModelPathMappingsHelp') }}"></i>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="setting-control">
|
||||||
|
<button type="button" class="add-mapping-btn" onclick="settingsManager.addMappingRow()">
|
||||||
|
<i class="fas fa-plus"></i>
|
||||||
|
<span>{{ t('settings.downloadPathTemplates.addMapping') }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mappings-container">
|
||||||
|
<div id="baseModelMappingsContainer">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ sm.setting_toggle('skipPreviouslyDownloadedModelVersions', 'skip_previously_downloaded_model_versions', 'settings.skipPreviouslyDownloadedModelVersions.label', 'settings.skipPreviouslyDownloadedModelVersions.help') }}
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-row">
|
||||||
|
<div class="setting-info">
|
||||||
|
<label for="downloadSkipBaseModelsToggle">
|
||||||
|
{{ t('settings.downloadSkipBaseModels.label') }}
|
||||||
|
<i class="fas fa-info-circle info-icon" data-tooltip="{{ t('settings.downloadSkipBaseModels.help') }}"></i>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="setting-control">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
id="downloadSkipBaseModelsToggle"
|
||||||
|
class="secondary-btn base-model-skip-toggle"
|
||||||
|
aria-expanded="false"
|
||||||
|
>
|
||||||
|
<span id="downloadSkipBaseModelsSummary">{{ t('settings.downloadSkipBaseModels.summary.none') }}</span>
|
||||||
|
<span class="base-model-skip-toggle-label">{{ t('settings.downloadSkipBaseModels.actions.edit') }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="downloadSkipBaseModelsPanel" class="base-model-skip-panel" hidden>
|
||||||
|
<div class="base-model-skip-toolbar">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="downloadSkipBaseModelsSearch"
|
||||||
|
class="base-model-skip-search"
|
||||||
|
placeholder="{{ t('settings.downloadSkipBaseModels.searchPlaceholder') }}"
|
||||||
|
/>
|
||||||
|
<button type="button" class="text-btn base-model-skip-clear" id="downloadSkipBaseModelsClear">
|
||||||
|
{{ t('settings.downloadSkipBaseModels.actions.clear') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="downloadSkipBaseModelsContainer" class="base-model-skip-list"></div>
|
||||||
|
<div id="downloadSkipBaseModelsEmpty" class="base-model-skip-empty" hidden>
|
||||||
|
{{ t('settings.downloadSkipBaseModels.empty') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="settings-input-error-message" id="downloadSkipBaseModelsError"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Priority Tags -->
|
||||||
|
<div class="setting-item priority-tags-item">
|
||||||
|
<div class="setting-row priority-tags-header-row">
|
||||||
|
<div class="setting-info priority-tags-header">
|
||||||
|
<label>
|
||||||
|
{{ t('settings.priorityTags.title') }}
|
||||||
|
<i class="fas fa-info-circle info-icon" data-tooltip="{{ t('settings.priorityTags.description') }}"></i>
|
||||||
|
</label>
|
||||||
|
<a class="settings-action-link priority-tags-help-link" href="https://github.com/willmiao/ComfyUI-Lora-Manager/wiki/Priority-Tags-Configuration-Guide" target="_blank" rel="noopener" aria-label="{{ t('settings.priorityTags.helpLinkLabel') }}" title="{{ t('settings.priorityTags.helpLinkLabel') }}">
|
||||||
|
<i class="fas fa-question-circle" aria-hidden="true"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="priority-tags-tabs">
|
||||||
|
<input type="radio" id="priority-tags-tab-lora" name="priority-tags-tab" class="priority-tags-tab-input" checked>
|
||||||
|
<input type="radio" id="priority-tags-tab-checkpoint" name="priority-tags-tab" class="priority-tags-tab-input">
|
||||||
|
<input type="radio" id="priority-tags-tab-embedding" name="priority-tags-tab" class="priority-tags-tab-input">
|
||||||
|
|
||||||
|
<div class="priority-tags-tablist">
|
||||||
|
<label class="priority-tags-tab-label" for="priority-tags-tab-lora" id="priority-tags-tab-lora-label">{{ t('settings.priorityTags.modelTypes.lora') }}</label>
|
||||||
|
<label class="priority-tags-tab-label" for="priority-tags-tab-checkpoint" id="priority-tags-tab-checkpoint-label">{{ t('settings.priorityTags.modelTypes.checkpoint') }}</label>
|
||||||
|
<label class="priority-tags-tab-label" for="priority-tags-tab-embedding" id="priority-tags-tab-embedding-label">{{ t('settings.priorityTags.modelTypes.embedding') }}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="priority-tags-panels">
|
||||||
|
<div class="priority-tags-panel" id="priority-tags-panel-lora">
|
||||||
|
<textarea id="loraPriorityTagsInput" class="priority-tags-input" placeholder="{{ t('settings.priorityTags.placeholder') }}"></textarea>
|
||||||
|
<div class="settings-input-error-message" id="loraPriorityTagsError"></div>
|
||||||
|
</div>
|
||||||
|
<div class="priority-tags-panel" id="priority-tags-panel-checkpoint">
|
||||||
|
<textarea id="checkpointPriorityTagsInput" class="priority-tags-input" placeholder="{{ t('settings.priorityTags.placeholder') }}"></textarea>
|
||||||
|
<div class="settings-input-error-message" id="checkpointPriorityTagsError"></div>
|
||||||
|
</div>
|
||||||
|
<div class="priority-tags-panel" id="priority-tags-panel-embedding">
|
||||||
|
<textarea id="embeddingPriorityTagsInput" class="priority-tags-input" placeholder="{{ t('settings.priorityTags.placeholder') }}"></textarea>
|
||||||
|
<div class="settings-input-error-message" id="embeddingPriorityTagsError"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Auto-organize -->
|
||||||
|
<div class="settings-subsection">
|
||||||
|
{{ sm.subsection_header('settings.sections.autoOrganize') }}
|
||||||
|
|
||||||
|
<!-- Auto-organize Exclusions -->
|
||||||
|
<div class="setting-item auto-organize-exclusions-item">
|
||||||
|
<div class="setting-row">
|
||||||
|
<div class="setting-info">
|
||||||
|
<label for="autoOrganizeExclusions">
|
||||||
|
{{ t('settings.autoOrganizeExclusions.label') }}
|
||||||
|
<i class="fas fa-info-circle info-icon" data-tooltip="{{ t('settings.autoOrganizeExclusions.help') }}"></i>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<textarea id="autoOrganizeExclusions" class="priority-tags-input auto-organize-exclusions-input" placeholder="{{ t('settings.autoOrganizeExclusions.placeholder') }}"></textarea>
|
||||||
|
<div class="settings-input-error-message" id="autoOrganizeExclusionsError"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -36,6 +36,7 @@
|
|||||||
<button type="button" class="settings-nav-item active" data-section="general">{{ t('settings.nav.general') }}</button>
|
<button type="button" class="settings-nav-item active" data-section="general">{{ t('settings.nav.general') }}</button>
|
||||||
<button type="button" class="settings-nav-item" data-section="interface">{{ t('settings.nav.interface') }}</button>
|
<button type="button" class="settings-nav-item" data-section="interface">{{ t('settings.nav.interface') }}</button>
|
||||||
<button type="button" class="settings-nav-item" data-section="library">{{ t('settings.nav.library') }}</button>
|
<button type="button" class="settings-nav-item" data-section="library">{{ t('settings.nav.library') }}</button>
|
||||||
|
<button type="button" class="settings-nav-item" data-section="organization">{{ t('settings.nav.organization') }}</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
@@ -46,6 +47,7 @@
|
|||||||
{% include 'components/modals/settings/general.html' %}
|
{% include 'components/modals/settings/general.html' %}
|
||||||
{% include 'components/modals/settings/interface.html' %}
|
{% include 'components/modals/settings/interface.html' %}
|
||||||
{% include 'components/modals/settings/library.html' %}
|
{% include 'components/modals/settings/library.html' %}
|
||||||
|
{% include 'components/modals/settings/organization.html' %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user