Merge pull request #2663 from d-ber/bulkTagImport Add bulk tag import
Signed| @@ -99,6 +99,6 @@ | ||
| 99 | 99 | } |
| 100 | 100 | |
| 101 | 101 | #bulk_tag_shadow_popup #bulk_tag_popup #dialogue_popup_controls .menu_button { |
| 102 | 102 | width: 100pxunset; |
| 103 | 103 | padding: 0.25em; |
| 104 | 104 | } |
| @@ -10740,7 +10740,7 @@ jQuery(async function () { | ||
| 10740 | 10740 | } |
| 10741 | 10741 | } break; |
| 10742 | 10742 | case 'import_tags': { |
| 10743 | 10743 | await importTags(characters[this_chid], { forceShowimportSetting: truetag_import_setting.ASK }); |
| 10744 | 10744 | } break; |
| 10745 | 10745 | /*case 'delete_button': |
| 10746 | 10746 | popup_type = "del_ch"; |
| @@ -18,7 +18,7 @@ import { | ||
| 18 | 18 | import { favsToHotswap } from './RossAscends-mods.js'; |
| 19 | 19 | import { hideLoader, showLoader } from './loader.js'; |
| 20 | 20 | import { convertCharacterToPersona } from './personas.js'; |
| 21 | 21 | import { createTagInput, getTagKeyForEntity, getTagsList, printTagList, tag_map, compareTagsForSort, removeTagFromMap, importTags, tag_import_setting } from './tags.js'; |
| 22 | 22 | |
| 23 | 23 | /** |
| 24 | 24 | * Static object representing the actions of the |
| @@ -197,10 +197,10 @@ class BulkTagPopupHandler { | ||
| 197 | 197 | #getHtml = () => { |
| 198 | 198 | const characterData = JSON.stringify({ characterIds: this.characterIds }); |
| 199 | 199 | return `<div id="bulk_tag_shadow_popup"> |
| 200 | 200 | <div id="bulk_tag_popup" class="wider_dialogue_popup"> |
| 201 | 201 | <div id="bulk_tag_popup_holder"> |
| 202 | 202 | <h3 class="marginBot5">Modify tags of ${this.characterIds.length} characters</h3> |
| 203 | 203 | <small class="bulk_tags_desc m-b-1">Add or remove the mutual tags of all selected characters. Import all or existing tags for all selected characters.</small> |
| 204 | 204 | <div id="bulk_tags_avatars_block" class="avatars_inline avatars_inline_small tags tags_inline"></div> |
| 205 | 205 | <br> |
| 206 | 206 | <div id="bulk_tags_div" class="marginBot5" data-characters='${characterData}'> |
| @@ -219,6 +219,12 @@ class BulkTagPopupHandler { | ||
| 219 | 219 | <i class="fa-solid fa-trash-can margin-right-10px"></i> |
| 220 | 220 | Mutual |
| 221 | 221 | </div> |
| 222 | + <div id="bulk_tag_popup_import_all_tags" class="menu_button" title="Import all tags from selected characters" data-i18n="[title]Import all tags from selected characters"> | |
| 223 | + Import All | |
| 224 | + </div> | |
| 225 | + <div id="bulk_tag_popup_import_existing_tags" class="menu_button" title="Import existing tags from selected characters" data-i18n="[title]Import existing tags from selected characters"> | |
| 226 | + Import Existing | |
| 227 | + </div> | |
| 222 | 228 | <div id="bulk_tag_popup_cancel" class="menu_button" data-i18n="Cancel">Close</div> |
| 223 | 229 | </div> |
| 224 | 230 | </div> |
| @@ -254,6 +260,30 @@ class BulkTagPopupHandler { | ||
| 254 | 260 | document.querySelector('#bulk_tag_popup_reset').addEventListener('click', this.resetTags.bind(this)); |
| 255 | 261 | document.querySelector('#bulk_tag_popup_remove_mutual').addEventListener('click', this.removeMutual.bind(this)); |
| 256 | 262 | document.querySelector('#bulk_tag_popup_cancel').addEventListener('click', this.hide.bind(this)); |
| 263 | + document.querySelector('#bulk_tag_popup_import_all_tags').addEventListener('click', this.importAllTags.bind(this)); | |
| 264 | + document.querySelector('#bulk_tag_popup_import_existing_tags').addEventListener('click', this.importExistingTags.bind(this)); | |
| 265 | + } | |
| 266 | + | |
| 267 | + /** | |
| 268 | + * Import existing tags for all selected characters | |
| 269 | + */ | |
| 270 | + async importExistingTags() { | |
| 271 | + for (const characterId of this.characterIds) { | |
| 272 | + await importTags(characters[characterId], { importSetting: tag_import_setting.ONLY_EXISTING }); | |
| 273 | + } | |
| 274 | + | |
| 275 | + $('#bulkTagList').empty(); | |
| 276 | + } | |
| 277 | + | |
| 278 | + /** | |
| 279 | + * Import all tags for all selected characters | |
| 280 | + */ | |
| 281 | + async importAllTags() { | |
| 282 | + for (const characterId of this.characterIds) { | |
| 283 | + await importTags(characters[characterId], { importSetting: tag_import_setting.ALL }); | |
| 284 | + } | |
| 285 | + | |
| 286 | + $('#bulkTagList').empty(); | |
| 257 | 287 | } |
| 258 | 288 | |
| 259 | 289 | /** |
| @@ -570,7 +600,7 @@ class BulkEditOverlay { | ||
| 570 | 600 | this.container.removeEventListener('mouseup', cancelHold); |
| 571 | 601 | this.container.removeEventListener('touchend', cancelHold); |
| 572 | 602 | }, |
| 573 | 603 | BulkEditOverlay.longPressDelay); |
| 574 | 604 | }; |
| 575 | 605 | |
| 576 | 606 | handleLongPressEnd = (event) => { |
| @@ -708,12 +708,12 @@ const ANTI_TROLL_MAX_TAGS = 15; | ||
| 708 | 708 | * |
| 709 | 709 | * @param {Character} character - The character |
| 710 | 710 | * @param {object} [options] - Options |
| 711 | 711 | * @param {booleantag_import_setting} [options.forceShowimportSetting=falsenull] - Whether to forceForce showinga thetag import dialogsetting |
| 712 | 712 | * @returns {Promise<boolean>} Boolean indicating whether any tag was imported |
| 713 | 713 | */ |
| 714 | 714 | async function importTags(character, { forceShowimportSetting = falsenull } = {}) { |
| 715 | 715 | // Gather the tags to import based on the selected setting |
| 716 | 716 | const tagNamesToImport = await handleTagImport(character, { forceShowimportSetting }); |
| 717 | 717 | if (!tagNamesToImport?.length) { |
| 718 | 718 | console.debug('No tags to import'); |
| 719 | 719 | return; |
| @@ -732,10 +732,10 @@ async function importTags(character, { forceShow = false } = {}) { | ||
| 732 | 732 | * |
| 733 | 733 | * @param {Character} character - The character |
| 734 | 734 | * @param {object} [options] - Options |
| 735 | 735 | * @param {booleantag_import_setting} [options.forceShowimportSetting=falsenull] - Whether to forceForce showinga thetag import dialogsetting |
| 736 | 736 | * @returns {Promise<string[]>} Array of strings representing the tags to import |
| 737 | 737 | */ |
| 738 | 738 | async function handleTagImport(character, { forceShowimportSetting = falsenull } = {}) { |
| 739 | 739 | /** @type {string[]} */ |
| 740 | 740 | const importTags = character.tags.map(t => t.trim()).filter(t => t) |
| 741 | 741 | .filter(t => !IMPORT_EXLCUDED_TAGS.includes(t)) |
| @@ -745,9 +745,9 @@ async function handleTagImport(character, { forceShow = false } = {}) { | ||
| 745 | 745 | .map(newTag); |
| 746 | 746 | const folderTags = getOpenBogusFolders(); |
| 747 | 747 | |
| 748 | 748 | // Choose the setting for this dialog. IfFirst fromcheck settingsoverride, verifythen thesaved setting really exists,or otherwisefinally takeuse "ASK". |
| 749 | 749 | const setting = forceShowimportSetting ? tag_import_setting.ASKimportSetting : |
| 750 | 750 | : Object.values(tag_import_setting).find(setting => setting === power_user.tag_import_setting) ?? tag_import_setting.ASK; |
| 751 | 751 | |
| 752 | 752 | switch (setting) { |
| 753 | 753 | case tag_import_setting.ALL: |