Add button to bulk import existing tags
| @@ -200,7 +200,7 @@ class BulkTagPopupHandler { | |||
| 200 | <div id="bulk_tag_popup"> | 200 | <div id="bulk_tag_popup"> |
| 201 | <div id="bulk_tag_popup_holder"> | 201 | <div id="bulk_tag_popup_holder"> |
| 202 | <h3 class="marginBot5">Modify tags of ${this.characterIds.length} characters</h3> | 202 | <h3 class="marginBot5">Modify tags of ${this.characterIds.length} characters</h3> |
| 203 | <small class="bulk_tags_desc m-b-1">Add or remove the mutual tags of all selected characters.</small> | 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 | <div id="bulk_tags_avatars_block" class="avatars_inline avatars_inline_small tags tags_inline"></div> | 204 | <div id="bulk_tags_avatars_block" class="avatars_inline avatars_inline_small tags tags_inline"></div> |
| 205 | <br> | 205 | <br> |
| 206 | <div id="bulk_tags_div" class="marginBot5" data-characters='${characterData}'> | 206 | <div id="bulk_tags_div" class="marginBot5" data-characters='${characterData}'> |
| @@ -222,6 +222,9 @@ class BulkTagPopupHandler { | |||
| 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"> | 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 | 223 | Import All |
| 224 | </div> | 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> | ||
| 225 | <div id="bulk_tag_popup_cancel" class="menu_button" data-i18n="Cancel">Close</div> | 228 | <div id="bulk_tag_popup_cancel" class="menu_button" data-i18n="Cancel">Close</div> |
| 226 | </div> | 229 | </div> |
| 227 | </div> | 230 | </div> |
| @@ -258,6 +261,18 @@ class BulkTagPopupHandler { | |||
| 258 | document.querySelector('#bulk_tag_popup_remove_mutual').addEventListener('click', this.removeMutual.bind(this)); | 261 | document.querySelector('#bulk_tag_popup_remove_mutual').addEventListener('click', this.removeMutual.bind(this)); |
| 259 | document.querySelector('#bulk_tag_popup_cancel').addEventListener('click', this.hide.bind(this)); | 262 | document.querySelector('#bulk_tag_popup_cancel').addEventListener('click', this.hide.bind(this)); |
| 260 | document.querySelector('#bulk_tag_popup_import_all_tags').addEventListener('click', this.importAllTags.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], { importExisting: true }); | ||
| 273 | } | ||
| 274 | |||
| 275 | $('#bulkTagList').empty(); | ||
| 261 | } | 276 | } |
| 262 | 277 | ||
| 263 | /** | 278 | /** |
| @@ -709,12 +709,13 @@ const ANTI_TROLL_MAX_TAGS = 15; | |||
| 709 | * @param {Character} character - The character | 709 | * @param {Character} character - The character |
| 710 | * @param {object} [options] - Options | 710 | * @param {object} [options] - Options |
| 711 | * @param {boolean} [options.importAll=false] - Whether to import all tags without dialog | 711 | * @param {boolean} [options.importAll=false] - Whether to import all tags without dialog |
| 712 | * @param {boolean} [options.importExisting=false] - Whether to import existing tags without dialog | ||
| 712 | * @param {boolean} [options.forceShow=false] - Whether to force showing the import dialog | 713 | * @param {boolean} [options.forceShow=false] - Whether to force showing the import dialog |
| 713 | * @returns {Promise<boolean>} Boolean indicating whether any tag was imported | 714 | * @returns {Promise<boolean>} Boolean indicating whether any tag was imported |
| 714 | */ | 715 | */ |
| 715 | async function importTags(character, { importAll = false, forceShow = false } = {}) { | 716 | async function importTags(character, { importAll = false, importExisting = false, forceShow = false } = {}) { |
| 716 | // Gather the tags to import based on the selected setting | 717 | // Gather the tags to import based on the selected setting |
| 717 | const tagNamesToImport = await handleTagImport(character, { importAll, forceShow }); | 718 | const tagNamesToImport = await handleTagImport(character, { importAll, importExisting, forceShow }); |
| 718 | if (!tagNamesToImport?.length) { | 719 | if (!tagNamesToImport?.length) { |
| 719 | console.debug('No tags to import'); | 720 | console.debug('No tags to import'); |
| 720 | return; | 721 | return; |
| @@ -734,10 +735,11 @@ async function importTags(character, { importAll = false, forceShow = false } = | |||
| 734 | * @param {Character} character - The character | 735 | * @param {Character} character - The character |
| 735 | * @param {object} [options] - Options | 736 | * @param {object} [options] - Options |
| 736 | * @param {boolean} [options.importAll=false] - Whether to import all tags without dialog | 737 | * @param {boolean} [options.importAll=false] - Whether to import all tags without dialog |
| 738 | * @param {boolean} [options.importExisting=false] - Whether to import existing tags without dialog | ||
| 737 | * @param {boolean} [options.forceShow=false] - Whether to force showing the import dialog | 739 | * @param {boolean} [options.forceShow=false] - Whether to force showing the import dialog |
| 738 | * @returns {Promise<string[]>} Array of strings representing the tags to import | 740 | * @returns {Promise<string[]>} Array of strings representing the tags to import |
| 739 | */ | 741 | */ |
| 740 | async function handleTagImport(character, { importAll = false, forceShow = false } = {}) { | 742 | async function handleTagImport(character, { importAll = false, importExisting = false, forceShow = false } = {}) { |
| 741 | /** @type {string[]} */ | 743 | /** @type {string[]} */ |
| 742 | const importTags = character.tags.map(t => t.trim()).filter(t => t) | 744 | const importTags = character.tags.map(t => t.trim()).filter(t => t) |
| 743 | .filter(t => !IMPORT_EXLCUDED_TAGS.includes(t)) | 745 | .filter(t => !IMPORT_EXLCUDED_TAGS.includes(t)) |
| @@ -750,7 +752,8 @@ async function handleTagImport(character, { importAll = false, forceShow = false | |||
| 750 | // Choose the setting for this dialog. If from settings, verify the setting really exists, otherwise take "ASK". | 752 | // Choose the setting for this dialog. If from settings, verify the setting really exists, otherwise take "ASK". |
| 751 | const setting = forceShow ? tag_import_setting.ASK | 753 | const setting = forceShow ? tag_import_setting.ASK |
| 752 | : importAll ? tag_import_setting.ALL | 754 | : importAll ? tag_import_setting.ALL |
| 753 | : Object.values(tag_import_setting).find(setting => setting === power_user.tag_import_setting) ?? tag_import_setting.ASK; | 755 | : importExisting ? tag_import_setting.ONLY_EXISTING |
| 756 | : Object.values(tag_import_setting).find(setting => setting === power_user.tag_import_setting) ?? tag_import_setting.ASK; | ||
| 754 | 757 | ||
| 755 | switch (setting) { | 758 | switch (setting) { |
| 756 | case tag_import_setting.ALL: | 759 | case tag_import_setting.ALL: |