1
0
mirror of https://github.com/koloml/philomena-tagging-assistant.git synced 2026-05-09 07:12:19 +00:00

Merge remote-tracking branch 'origin/release/0.7.1' into feature/conditional-presets

# Conflicts:
#	src/content/components/extension/presets/PresetTableRow.ts
#	src/lib/extension/entities/TagEditorPreset.ts
#	src/lib/extension/transporting/exporters.ts
#	src/routes/features/presets/[id]/edit/+page.svelte
This commit is contained in:
2026-04-05 18:01:33 +04:00
7 changed files with 83 additions and 1 deletions

View File

@@ -18,3 +18,9 @@
<DetailsBlock title="Tags">
<TagsList tags={sortedTagsList}></TagsList>
</DetailsBlock>
{#if preset.settings.exclusive}
<DetailsBlock title="Exclusivity">
Only one tag in this preset should be active at a time. If you will click on other non-active tag, other tags will
be automatically removed from the editor.
</DetailsBlock>
{/if}

View File

@@ -9,6 +9,7 @@ export default class PresetTableRow extends BaseComponent {
#tagsList: HTMLElement[] = [];
#applyAllButton = document.createElement('button');
#removeAllButton = document.createElement('button');
#exclusiveWarning = document.createElement('div');
#alternateColorDummy = document.createElement('span');
constructor(container: HTMLElement, preset: TagEditorPreset) {
@@ -33,6 +34,7 @@ export default class PresetTableRow extends BaseComponent {
nameCell.textContent = this.#preset.settings.name;
const tagsCell = document.createElement('td');
tagsCell.style.width = '70%';
const tagsListContainer = document.createElement('div');
tagsListContainer.classList.add('tag-list');
@@ -53,6 +55,18 @@ export default class PresetTableRow extends BaseComponent {
this.#removeAllButton.append(createFontAwesomeIcon('circle-minus'));
this.#removeAllButton.title = 'Remove all tags from this preset from the editor';
if (this.#preset.settings.exclusive) {
this.#applyAllButton.disabled = true;
this.#applyAllButton.title = "You can't add all tags from this preset since it only allows one tag to be active";
this.#exclusiveWarning.classList.add('block', 'block--fixed', 'block--warning');
this.#exclusiveWarning.textContent = ' Multiple tags from this preset present in the editor! If you will click one of the tags here, other tags will be cleared automatically.'
this.#exclusiveWarning.prepend(createFontAwesomeIcon('triangle-exclamation'));
this.#exclusiveWarning.style.display = 'none';
tagsCell.append(this.#exclusiveWarning);
}
actionsContainer.append(
this.#applyAllButton,
this.#removeAllButton,
@@ -88,6 +102,30 @@ export default class PresetTableRow extends BaseComponent {
const tagName = targetElement.dataset.tagName;
const isMissing = targetElement.classList.contains(PresetTableRow.#tagMissingClassName);
if (!tagName) {
return;
}
// If a user clicks on the tag which was missing, then we have to remove all other active tags that are in this
// preset. But only when clicking on a tag which is missing, just so they will be able to remove any cases where
// multiple tags from exclusive present are active.
if (this.#preset.settings.exclusive && isMissing) {
const tagNamesToRemove = this.#tagsList
.filter(
tagElement => tagElement !== targetElement
&& !tagElement.classList.contains(PresetTableRow.#tagMissingClassName)
)
.map(tagElement => tagElement.dataset.tagName)
.filter(tagName => typeof tagName === 'string');
emit(this, EVENT_PRESET_TAG_CHANGE_APPLIED, {
addedTags: new Set([tagName]),
removedTags: new Set(tagNamesToRemove)
});
return;
}
emit(this, EVENT_PRESET_TAG_CHANGE_APPLIED, {
[isMissing ? 'addedTags' : 'removedTags']: new Set([tagName])
});
@@ -132,11 +170,29 @@ export default class PresetTableRow extends BaseComponent {
}
updateTags(tags: Set<string>) {
let presentTagsAmount = 0;
for (const tagElement of this.#tagsList) {
tagElement.classList.toggle(
const isTagMissing = tagElement.classList.toggle(
PresetTableRow.#tagMissingClassName,
!tags.has(tagElement.dataset.tagName || ''),
);
if (!isTagMissing) {
presentTagsAmount++;
}
}
if (this.#preset.settings.exclusive) {
const multipleTagsInExclusivePreset = presentTagsAmount > 1;
this.container.classList.toggle(PresetTableRow.#presetWarningClassName, multipleTagsInExclusivePreset);
if (multipleTagsInExclusivePreset) {
this.#exclusiveWarning.style.removeProperty('display');
} else {
this.#exclusiveWarning.style.display = 'none';
}
}
this.#maybeRefreshVisibilityFromTags(tags);
@@ -151,4 +207,5 @@ export default class PresetTableRow extends BaseComponent {
}
static #tagMissingClassName = 'is-missing';
static #presetWarningClassName = 'has-warning';
}

View File

@@ -3,6 +3,7 @@ import StorageEntity from "$lib/extension/base/StorageEntity";
interface TagEditorPresetSettings {
name: string;
tags: string[];
exclusive: boolean;
conditional: boolean;
requiredTags: string[];
}
@@ -12,6 +13,7 @@ export default class TagEditorPreset extends StorageEntity<TagEditorPresetSettin
super(id, {
name: settings.name || '',
tags: settings.tags || [],
exclusive: settings.exclusive ?? false
conditional: settings.conditional || false,
requiredTags: settings.requiredTags || [],
});

View File

@@ -42,6 +42,7 @@ const entitiesExporters: ExportersMap = {
id: entity.id,
name: entity.settings.name,
tags: entity.settings.tags,
exclusive: entity.settings.exclusive,
conditional: entity.settings.conditional,
requiredTags: entity.settings.requiredTags,
}

View File

@@ -24,6 +24,7 @@
let presetName = $state('');
let tagsList = $state<string[]>([]);
let isExclusive = $state(false);
let isConditional = $state<boolean>(false);
let requiredTags = $state<string[]>([]);
@@ -42,6 +43,7 @@
presetName = targetPreset.settings.name;
tagsList = [...targetPreset.settings.tags].sort((a, b) => a.localeCompare(b));
isExclusive = targetPreset.settings.exclusive;
isConditional = targetPreset.settings.conditional;
requiredTags = [...targetPreset.settings.requiredTags].sort((a, b) => a.localeCompare(b));
});
@@ -54,6 +56,7 @@
targetPreset.settings.name = presetName;
targetPreset.settings.tags = [...tagsList];
targetPreset.settings.exclusive = isExclusive;
targetPreset.settings.conditional = isConditional;
targetPreset.settings.requiredTags = [...requiredTags];
@@ -74,6 +77,11 @@
<FormControl label="Tags">
<TagsEditor bind:tags={tagsList}></TagsEditor>
</FormControl>
<FormControl>
<CheckboxField bind:checked={isExclusive}>
Keep only one tag from this preset active at a time.
</CheckboxField>
</FormControl>
<FormControl>
<CheckboxField bind:checked={isConditional}>
Show this preset only when specified tags are provided.

View File

@@ -4,6 +4,7 @@ $media-box-color: var(--media-box-color);
$padding-small: var(--padding-small);
$padding-normal: var(--padding-normal);
$padding-large: var(--padding-large);
$block-spacing: var(--block-spacing);
// These variables are defined dynamically based on the category of the tag
$resolved-tag-background: var(--tag-background);

View File

@@ -14,4 +14,11 @@
background: booru-vars.$resolved-tag-color;
}
}
.block.block--fixed.block--warning {
margin: {
top: booru-vars.$block-spacing;
bottom: 0;
}
}
}