diff --git a/public/index.html b/public/index.html index 13295a005..f65ebb534 100644 --- a/public/index.html +++ b/public/index.html @@ -5088,7 +5088,8 @@ - + +
diff --git a/public/scripts/world-info.js b/public/scripts/world-info.js index 275fdd277..bfbdde330 100644 --- a/public/scripts/world-info.js +++ b/public/scripts/world-info.js @@ -522,7 +522,7 @@ function registerWorldInfoSlashCommands() { return ''; } - const entry = createWorldInfoEntry(file, data, true); + const entry = createWorldInfoEntry(file, data); if (key) { entry.key.push(key); @@ -795,20 +795,20 @@ function displayWorldEntries(name, data, navigation = navigation_option.none) { callback: function (/** @type {object[]} */ page) { $('#world_popup_entries_list').empty(); const keywordHeaders = ` -
+
Title/Memo - + Status - + Position - + Depth - + Order @@ -859,7 +859,8 @@ function displayWorldEntries(name, data, navigation = navigation_option.none) { } $('#world_popup_new').off('click').on('click', () => { - createWorldInfoEntry(name, data); + const entry = createWorldInfoEntry(name, data); + if (entry) updateEditor(entry.uid); }); $('#world_popup_name_button').off('click').on('click', async () => { @@ -1571,6 +1572,18 @@ function getWorldEntry(name, data, entry) { }); preventRecursionInput.prop('checked', entry.preventRecursion).trigger('input'); + // duplicate button + const duplicateButton = template.find('.duplicate_entry_button'); + duplicateButton.data('uid', entry.uid); + duplicateButton.on('click', function () { + const uid = $(this).data('uid'); + const entry = duplicateWorldInfoEntry(data, uid); + if (entry) { + saveWorldInfo(name, data); + updateEditor(entry.uid); + } + }); + // delete button const deleteButton = template.find('.delete_entry_button'); deleteButton.data('uid', entry.uid); @@ -1755,7 +1768,33 @@ function createEntryInputAutocomplete(input, callback) { }); } -async function deleteWorldInfoEntry(data, uid) { +/** + * Duplicated a WI entry by copying all of its properties and assigning a new uid + * @param {*} data - The data of the book + * @param {number} uid - The uid of the entry to copy in this book + * @returns {*} The new WI duplicated entry + */ +function duplicateWorldInfoEntry(data, uid) { + if (!data || !('entries' in data) || !data.entries[uid]) { + return; + } + + // Exclude uid and gather the rest of the properties + const { uid: _, ...originalData } = data.entries[uid]; + + // Create new entry and copy over data + const entry = createWorldInfoEntry(data.name, data); + Object.assign(entry, originalData); + + return entry; +} + +/** + * Deletes a WI entry, with a user confirmation dialog + * @param {*[]} data - The data of the book + * @param {number} uid - The uid of the entry to copy in this book + */ +function deleteWorldInfoEntry(data, uid) { if (!data || !('entries' in data)) { return; } @@ -1792,7 +1831,7 @@ const newEntryTemplate = { role: 0, }; -function createWorldInfoEntry(name, data, fromSlashCommand = false) { +function createWorldInfoEntry(name, data) { const newUid = getFreeWorldEntryUid(data); if (!Number.isInteger(newUid)) { @@ -1803,10 +1842,6 @@ function createWorldInfoEntry(name, data, fromSlashCommand = false) { const newEntry = { uid: newUid, ...structuredClone(newEntryTemplate) }; data.entries[newUid] = newEntry; - if (!fromSlashCommand) { - updateEditor(newUid); - } - return newEntry; }