Progress on move entry * Fixed header alignment * Building HTML with browser api instead of string. * jqueryElement.data(key, value) usages converted to jqueryElement.attr(data-key, value) * Logs simplified * Removed success toastry message
| @@ -1,4 +1,4 @@ | ||
| 1 | 1 | <div id="WIEntryHeaderTitlesPC" class="flex-container wide100p spaceBetween justifyCenter textAlignCenter" style="padding:0 47.5em0em;"> |
| 2 | 2 | <small class="flex1" data-i18n="Title/Memo">Title/Memo</small> |
| 3 | 3 | <small style="width: calc(3.5em + 10px)" data-i18n="Strategy">Strategy</small> |
| 4 | 4 | <small style="width: calc(3.5em + 20px)" data-i18n="Position">Position</small> |
| @@ -2208,7 +2208,7 @@ function verifyWorldInfoSearchSortRule() { | ||
| 2208 | 2208 | * Use `originalWIDataKeyMap` to find the correct value to be set. |
| 2209 | 2209 | * |
| 2210 | 2210 | * @param {object} data - The data object containing the original data entries. |
| 2211 | 2211 | * @param {stringnumber} uid - The unique identifier of the data entry. |
| 2212 | 2212 | * @param {string} key - The key of the value to be set. |
| 2213 | 2213 | * @param {any} value - The value to be set. |
| 2214 | 2214 | */ |
| @@ -3141,21 +3141,38 @@ export async function getWorldEntry(name, data, entry) { | ||
| 3141 | 3141 | |
| 3142 | 3142 | // move button |
| 3143 | 3143 | const moveButton = template.find('.move_entry_button'); |
| 3144 | 3144 | moveButton.dataattr('data-uid', entry.uid); |
| 3145 | 3145 | moveButton.dataattr('data-current-world', name); |
| 3146 | 3146 | moveButton.on('click', async function (e) { |
| 3147 | 3147 | e.stopPropagation(); |
| 3148 | 3148 | const sourceUid = $(this).data('uid'); |
| 3149 | 3149 | const sourceWorld = $(this).data('current-world'); |
| 3150 | - // Loading world info is bad, do we have cache variable? | |
| 3150 | + const sourceWorldInfo = await loadWorldInfo(sourceWorld); | |
| 3151 | - const sourceName = (await loadWorldInfo(sourceWorld)).entries[sourceUid].comment; | |
| 3151 | + if (!sourceWorldInfo) { | |
| 3152 | + return; | |
| 3153 | + } | |
| 3154 | + const sourceName = sourceWorldInfo.entries[sourceUid]?.comment; | |
| 3155 | + if (sourceName === undefined) { | |
| 3156 | + return; | |
| 3157 | + } | |
| 3158 | + | |
| 3159 | + const select = document.createElement('select'); | |
| 3160 | + select.id = 'move_entry_target_select'; | |
| 3161 | + select.classList.add('text_pole', 'wide100p', 'margin-top'); | |
| 3162 | + | |
| 3163 | + const defaultOption = document.createElement('option'); | |
| 3164 | + defaultOption.value = ''; | |
| 3165 | + defaultOption.textContent = `-- ${t`Select Target Lorebook`} --`; | |
| 3166 | + select.appendChild(defaultOption); | |
| 3152 | 3167 | |
| 3153 | - let optionsHtml = `<option value="">-- ${t`Select Target Lorebook`} --</option>`; | |
| 3154 | 3168 | let selectableWorldCount = 0; |
| 3155 | 3169 | world_names.forEach(worldName => { |
| 3156 | 3170 | if (worldName !== sourceWorld) { // Exclude the current world |
| 3157 | - optionsHtml += `<option value="${world_names.indexOf(worldName)}">${worldName}</option>`; | |
| 3171 | + const option = document.createElement('option'); | |
| 3158 | - selectableWorldCount += 1; | |
| 3172 | + option.value = world_names.indexOf(worldName).toString(); | |
| 3173 | + option.textContent = worldName; | |
| 3174 | + select.appendChild(option); | |
| 3175 | + selectableWorldCount++; | |
| 3159 | 3176 | } |
| 3160 | 3177 | }); |
| 3161 | 3178 | |
| @@ -3164,27 +3181,24 @@ export async function getWorldEntry(name, data, entry) { | ||
| 3164 | 3181 | return; |
| 3165 | 3182 | } |
| 3166 | 3183 | |
| 3167 | - const content = ` | |
| 3184 | + // Create wrapper div | |
| 3168 | - <div>${t`Move ${sourceName} to:`}</div> | |
| 3185 | + const wrapper = document.createElement('div'); | |
| 3169 | - <select id="move_entry_target_select" class="text_pole wide100p margin-top"> | |
| 3186 | + wrapper.textContent = t`Move ${sourceName} to:`; | |
| 3170 | - ${optionsHtml} | |
| 3171 | - </select> | |
| 3172 | - `; | |
| 3173 | 3187 | |
| 3174 | - const popupPromise = callGenericPopup(content, POPUP_TYPE.CONFIRM, '', { | |
| 3188 | + // Create container and append elements | |
| 3175 | - okButton: t`Move`, | |
| 3189 | + const container = document.createElement('div'); | |
| 3176 | - cancelButton: t`Cancel`, | |
| 3190 | + container.appendChild(wrapper); | |
| 3177 | 3191 | }container.appendChild(select); |
| 3178 | 3192 | |
| 3179 | 3193 | let selectedWorldIndex = -1; |
| 3180 | 3194 | $('#move_entry_target_select')select.onaddEventListener('change', function () { |
| 3181 | - /** @type {string} */ | |
| 3195 | + selectedWorldIndex = this.value === '' ? -1 : Number(this.value); | |
| 3182 | - // @ts-ignore | |
| 3183 | - const value = $(this).val(); | |
| 3184 | - selectedWorldIndex = value === '' ? -1 : Number(value); | |
| 3185 | 3196 | }); |
| 3186 | 3197 | |
| 3187 | 3198 | const popupConfirm = await popupPromise;callGenericPopup(container, POPUP_TYPE.CONFIRM, '', { |
| 3199 | + okButton: t`Move`, | |
| 3200 | + cancelButton: t`Cancel`, | |
| 3201 | + }); | |
| 3188 | 3202 | if (!popupConfirm) { |
| 3189 | 3203 | return; |
| 3190 | 3204 | } |
| @@ -5337,19 +5351,11 @@ jQuery(() => { | ||
| 5337 | 5351 | * |
| 5338 | 5352 | * @param {string} sourceName - The name of the source lorebook file. |
| 5339 | 5353 | * @param {string} targetName - The name of the target lorebook file. |
| 5340 | 5354 | * @param {number|string} uid - The UID of the entry to move from the source lorebook. |
| 5341 | 5355 | * @returns {Promise<boolean>} True if the move was successful, false otherwise. |
| 5342 | 5356 | */ |
| 5343 | 5357 | export async function moveWorldInfoEntry(sourceName, targetName, uid) { |
| 5344 | - console.log(`[WI] Attempting to move entry UID ${uid} from '${sourceName}' to '${targetName}'`); | |
| 5345 | - | |
| 5346 | - if (!sourceName || !targetName || uid === undefined || uid === null) { | |
| 5347 | - console.error('[WI Move] Missing required arguments.'); | |
| 5348 | - return false; | |
| 5349 | - } | |
| 5350 | - | |
| 5351 | 5358 | if (sourceName === targetName) { |
| 5352 | - toastr.warning(t`Source and target lorebooks cannot be the same.`); | |
| 5353 | 5359 | return false; |
| 5354 | 5360 | } |
| 5355 | 5361 | |
| @@ -5407,20 +5413,19 @@ export async function moveWorldInfoEntry(sourceName, targetName, uid) { | ||
| 5407 | 5413 | targetData.entries[newUid] = entryToMove; |
| 5408 | 5414 | |
| 5409 | 5415 | delete sourceData.entries[entryUidString]; |
| 5410 | 5416 | // Remove from originalData if it exists, using the original UID |
| 5411 | 5417 | deleteWIOriginalDataValue(sourceData, entryUidString); |
| 5418 | + // TODO: setWIOriginalDataValue | |
| 5412 | 5419 | console.debug(`[WI Move] Removed entry UID ${entryUidString} from source '${sourceName}'.`); |
| 5413 | 5420 | |
| 5414 | 5421 | |
| 5415 | - // Save immediately to reduce chances of inconsistency if the browser is closed | |
| 5422 | + await saveWorldInfo(targetName, targetData); | |
| 5416 | - // Note: This is not truly atomic. If one save fails, state could be inconsistent. | |
| 5417 | - await saveWorldInfo(targetName, targetData, true); | |
| 5418 | 5423 | console.debug(`[WI Move] Saved target lorebook '${targetName}'.`); |
| 5419 | 5424 | await saveWorldInfo(sourceName, sourceData, true); |
| 5420 | 5425 | console.debug(`[WI Move] Saved source lorebook '${sourceName}'.`); |
| 5421 | 5426 | |
| 5422 | 5427 | |
| 5423 | 5428 | toastrconsole.successlog(t`[WI Move] ${entryToMove.comment} moved successfully! to '${targetName}'.`); |
| 5424 | 5429 | |
| 5425 | 5430 | // Check if the currently viewed book in the editor is the source or target and reload it |
| 5426 | 5431 | const currentEditorBookIndex = Number($('#world_editor_select').val()); |