diff --git a/aiserver.py b/aiserver.py index 58217e7f..cdb197d5 100644 --- a/aiserver.py +++ b/aiserver.py @@ -6407,8 +6407,28 @@ def UI_2_change_wi_text(data): @socketio.on('move_wi') def UI_2_move_wi(data): print(data) - koboldai_vars.worldinfo_v2.reorder(int(data['dragged_id']), int(data['drop_id'])) - + if data['folder'] is None: + koboldai_vars.worldinfo_v2.reorder(int(data['dragged_id']), int(data['drop_id'])) + else: + koboldai_vars.worldinfo_v2.set_folder(int(data['dragged_id']), data['folder'], before_uid=int(data['drop_id'])) + +#==================================================================# +# Event triggered when user moves world info +#==================================================================# +@socketio.on('wi_set_folder') +def UI_2_wi_set_folder(data): + print(data) + koboldai_vars.worldinfo_v2.set_folder(int(data['dragged_id']), data['folder']) + +#==================================================================# +# Event triggered when user renames world info folder +#==================================================================# +@socketio.on('Rename_World_Info_Folder') +def UI_2_Rename_World_Info_Folder(data): + print("Rename_World_Info_Folder") + print(data) + koboldai_vars.worldinfo_v2.rename_folder(data['old_folder'], data['new_folder']) + #==================================================================# # Event triggered to rely a message diff --git a/koboldai_settings.py b/koboldai_settings.py index cc59c2df..e2079a6a 100644 --- a/koboldai_settings.py +++ b/koboldai_settings.py @@ -911,8 +911,8 @@ class KoboldWorldInfo(object): def get_folders(self, ui_version=2): if ui_version == 1: - return {i: {'collapsed': True, 'name': x} for i, x in enumerate(set([x['folder'] for x in self.world_info]))} - return list(set([x['folder'] for x in self.world_info])) + return {i: {'collapsed': True, 'name': x} for i, x in enumerate(set([self.world_info[x]['folder'] for x in self.world_info]))} + return list(set([self.world_info[x]['folder'] for x in self.world_info])) def get_folder_items(self, folder): items = [item.to_dict() for item in self.world_info if item['folder'] == folder] @@ -929,20 +929,28 @@ class KoboldWorldInfo(object): self.world_info[uid]['sort'] = before_sort_number def set_folder(self, uid, folder, before_uid=None): - max_sort = max([x['sort'] for x in self.world_info if x['folder'] == folder]) + max_sort = max([self.world_info[x]['sort'] for x in self.world_info if self.world_info[x]['folder'] == folder]+[-1]) old_folder = self.world_info[uid]['folder'] self.world_info[uid]['folder'] = folder - self.world_info[uid]['sort'] = max_sort + self.world_info[uid]['sort'] = max_sort+1 if before_uid is not None: - self.reorder(folder, uid, before_uid) + self.reorder(uid, before_uid) self.resort(folder) self.resort(old_folder) + def rename_folder(self, old_folder, new_folder): + while new_folder in self.get_folders(): + new_folder = "{}-1".format(new_folder) + for x in self.world_info: + if self.world_info[x]['folder'] == old_folder: + self.world_info[x]['folder'] = new_folder + + def resort(self, folder): - for i in range(max([x['sort'] for x in self.world_info if x['folder'] == folder])+1): - if i > len([x['sort'] for x in self.world_info if x['folder'] == folder]): + for i in range(max([self.world_info[x]['sort'] for x in self.world_info if self.world_info[x]['folder'] == folder])+1): + if i > len([self.world_info[x]['sort'] for x in self.world_info if self.world_info[x]['folder'] == folder]): break - elif i not in [x['sort'] for x in self.world_info if x['folder'] == folder]: + elif i not in [self.world_info[x]['sort'] for x in self.world_info if self.world_info[x]['folder'] == folder]: for item in world_info: if item['folder'] == folder and item['sort'] > i: item['sort'] = item['sort']-1 diff --git a/static/koboldai.css b/static/koboldai.css index 659cce47..236fa548 100644 --- a/static/koboldai.css +++ b/static/koboldai.css @@ -404,7 +404,8 @@ td.server_vars { .world_info_card { width: 100%; border: 2px outset var(--wi_card_border_color); - background-color: var(--wi_card_bg_color) + background-color: var(--wi_card_bg_color); + margin-bottom: 10px; } .world_info_tag_area { @@ -423,6 +424,14 @@ td.server_vars { cursor: pointer; } +.oi[folder] { + margin-right: 5px; +} + +.oi[data-glyph="folder"] { + margin-right: 5px; +} + /* ---------------------------- OVERALL PAGE CONFIG ------------------------------*/ body { @@ -938,4 +947,5 @@ button.disabled { .drag-over { border-top: dashed 3px red; -} \ No newline at end of file +} + diff --git a/static/koboldai.js b/static/koboldai.js index 4eeb7a1b..b4fca905 100644 --- a/static/koboldai.js +++ b/static/koboldai.js @@ -1009,12 +1009,60 @@ function world_info(data) { folder_item.id = "world_info_folder_"+folder; folder_item.classList.add("WI_Folder"); title = document.createElement("h2"); - title.textContent = folder; + title.addEventListener('dragenter', dragEnter) + title.addEventListener('dragover', dragOver); + title.addEventListener('dragleave', dragLeave); + title.addEventListener('drop', drop); + collapse_icon = document.createElement("span"); + collapse_icon.id = "world_info_folder_collapse_"+folder; + collapse_icon.classList.add("oi"); + collapse_icon.setAttribute("data-glyph", "chevron-bottom"); + collapse_icon.setAttribute("folder", folder); + collapse_icon.onclick = function () { + hide_wi_folder(this.getAttribute("folder")); + document.getElementById('world_info_folder_expand_'+this.getAttribute("folder")).classList.remove('hidden'); + this.classList.add("hidden"); + }; + title.append(collapse_icon); + expand_icon = document.createElement("span"); + expand_icon.id = "world_info_folder_expand_"+folder; + expand_icon.classList.add("oi"); + expand_icon.setAttribute("data-glyph", "chevron-right"); + expand_icon.setAttribute("folder", folder); + expand_icon.onclick = function () { + unhide_wi_folder(this.getAttribute("folder")); + document.getElementById('world_info_folder_collapse_'+this.getAttribute("folder")).classList.remove('hidden'); + this.classList.add("hidden"); + }; + expand_icon.classList.add("hidden"); + title.append(expand_icon); + icon = document.createElement("span"); + icon.classList.add("oi"); + icon.setAttribute("data-glyph", "folder"); + title.append(icon); + title_text = document.createElement("span"); + title_text.setAttribute("contenteditable", true); + title_text.setAttribute("original_text", folder); + title_text.textContent = folder; + title_text.onblur = function () { + if (this.textContent != this.getAttribute("original_text")) { + //Need to check if the new folder name is already in use + folder_name = this.textContent; + while (folder_name in Array(document.getElementById("story_menu_wi").children).filter(folder => folder.id.replace("world_info_folder_", ""))) { + folder_name = folder_name + " 1"; + } + this.parentElement.parentElement.id = "world_info_folder_" + folder_name; + socket.emit("Rename_World_Info_Folder", {"old_folder": this.getAttribute("original_text"), "new_folder": folder_name}); + this.setAttribute("original_text", folder_name); + } + } + title.append(title_text); folder_item.append(title); world_info_area.append(folder_item); } else { folder_item = document.getElementById("world_info_folder_"+folder); } + world_info_card.setAttribute("folder", folder); @@ -1224,6 +1272,95 @@ function upload_file(file_box) { } //--------------------------------------------General UI Functions------------------------------------ +function create_world_info_folder() { + var world_info_area = document.getElementById("story_menu_wi"); + + var i=0; + while (document.getElementById("world_info_folder_New "+i) != null) { + console.log("New "+i); + console.log(document.getElementById("world_info_folder_New "+i)); + i+=1; + } + folder = "New "+i; + //create new folder + var folder_item = document.createElement("span"); + folder_item.id = "world_info_folder_"+folder; + folder_item.classList.add("WI_Folder"); + title = document.createElement("h2"); + title.addEventListener('dragenter', dragEnter) + title.addEventListener('dragover', dragOver); + title.addEventListener('dragleave', dragLeave); + title.addEventListener('drop', drop); + collapse_icon = document.createElement("span"); + collapse_icon.id = "world_info_folder_collapse_"+folder; + collapse_icon.classList.add("oi"); + collapse_icon.setAttribute("data-glyph", "chevron-bottom"); + collapse_icon.setAttribute("folder", folder); + collapse_icon.onclick = function () { + hide_wi_folder(this.getAttribute("folder")); + document.getElementById('world_info_folder_expand_'+this.getAttribute("folder")).classList.remove('hidden'); + this.classList.add("hidden"); + }; + title.append(collapse_icon); + expand_icon = document.createElement("span"); + expand_icon.id = "world_info_folder_expand_"+folder; + expand_icon.classList.add("oi"); + expand_icon.setAttribute("data-glyph", "chevron-right"); + expand_icon.setAttribute("folder", folder); + expand_icon.onclick = function () { + unhide_wi_folder(this.getAttribute("folder")); + document.getElementById('world_info_folder_collapse_'+this.getAttribute("folder")).classList.remove('hidden'); + this.classList.add("hidden"); + }; + expand_icon.classList.add("hidden"); + title.append(expand_icon); + icon = document.createElement("span"); + icon.classList.add("oi"); + icon.setAttribute("data-glyph", "folder"); + title.append(icon); + title_text = document.createElement("span"); + title_text.setAttribute("contenteditable", true); + title_text.setAttribute("original_text", folder); + title_text.textContent = folder; + title_text.onblur = function () { + if (this.textContent != this.getAttribute("original_text")) { + //Need to check if the new folder name is already in use + folder_name = this.textContent; + while (folder_name in document.getElementById("story_menu_wi").children.filter(animal => folder.id.replace("world_info_folder_", ""))) { + folder_name = folder_name + " 1"; + } + this.parentElement.parentElement.id = "world_info_folder_" + folder_name; + socket.emit("Rename_World_Info_Folder", {"old_folder": this.getAttribute("original_text"), "new_folder": folder_name}); + this.setAttribute("original_text", folder_name); + } + } + title.append(title_text); + folder_item.append(title); + world_info_area.append(folder_item); +} + +function hide_wi_folder(folder) { + if (document.getElementById("world_info_folder_"+folder)) { + folder_item = document.getElementById("world_info_folder_"+folder); + for (card of folder_item.children) { + if (card.tagName != "H2") { + card.classList.add("hidden"); + } + } + } +} + +function unhide_wi_folder(folder) { + if (document.getElementById("world_info_folder_"+folder)) { + folder_item = document.getElementById("world_info_folder_"+folder); + for (card of folder_item.children) { + if (card.tagName != "H2") { + card.classList.remove("hidden"); + } + } + } +} + function create_wi_card(wiid) { world_info_card = document.createElement("div"); world_info_card.setAttribute("draggable", true); @@ -1280,9 +1417,12 @@ function dragStart(e) { } function find_wi_container(e) { + while (true) { if (e.parentElement == document) { return e; + } else if (e.tagName == 'H2') { + return e.parentElement; } else if (typeof e.id == 'undefined') { e = e.parentElement; } else if (e.id.replace(/[^a-z_]/gi, '') == 'world_info_') { @@ -1318,18 +1458,29 @@ function drop(e) { // get the draggable element const id = e.dataTransfer.getData('text/plain'); const draggable = document.getElementById(id); - - // add it before the drop target - element = find_wi_container(e.target); - element.parentElement.insertBefore(draggable, element); - - // display the draggable element - draggable.classList.remove('hidden'); - - //send the new order to the backend dragged_id = draggable.id.split("_").slice(-1)[0]; drop_id = element.id.split("_").slice(-1)[0]; - socket.emit("move_wi", {'dragged_id': dragged_id, 'drop_id': drop_id}); + + // get the drop element + element = find_wi_container(e.target); + + //check if we're droping on a folder, and then append it to the folder + if (element.children[0].tagName == "H2") { + element.append(draggable); + socket.emit("wi_set_folder", {'dragged_id': dragged_id, 'folder': drop_id}); + } else { + //insert the draggable element before the drop element + element.parentElement.insertBefore(draggable, element); + + // display the draggable element + draggable.classList.remove('hidden'); + + if (element.getAttribute("folder") == draggable.getAttribute("folder")) { + socket.emit("move_wi", {'dragged_id': dragged_id, 'drop_id': drop_id, 'folder': null}); + } else { + socket.emit("move_wi", {'dragged_id': dragged_id, 'drop_id': drop_id, 'folder': element.getAttribute("folder")}); + } + } } function dragend(e) { @@ -1340,67 +1491,69 @@ function dragend(e) { function assign_world_info_to_action(wiid=null, action_item=null) { //console.log(world_info_data); - if (wiid != null) { - var worldinfo_to_check = {}; - worldinfo_to_check[wiid] = world_info_data[wiid] - } else { - var worldinfo_to_check = world_info_data; - } - if (action_item != null) { - var actions = [action_item] - } else { - var actions = document.getElementById("Selected Text").children; - } - for (action of actions) { - //First check to see if we have a key in the text - var words = Array.prototype.slice.call( action.children ); - words_text = []; - for (word of words) { - words_text.push(word.textContent); + if (world_info_data != {}) { + if (wiid != null) { + var worldinfo_to_check = {}; + worldinfo_to_check[wiid] = world_info_data[wiid] + } else { + var worldinfo_to_check = world_info_data; } - for (const [key, worldinfo] of Object.entries(worldinfo_to_check)) { - //remove any world info tags - for (tag of action.getElementsByClassName("tag_wiid_"+wiid)) { - tag.classList.remove("tag_wiid_"+wiid); - tag.removeAttribute("title"); + if (action_item != null) { + var actions = [action_item] + } else { + var actions = document.getElementById("Selected Text").children; + } + for (action of actions) { + //First check to see if we have a key in the text + var words = Array.prototype.slice.call( action.children ); + words_text = []; + for (word of words) { + words_text.push(word.textContent); } - - if (('key' in worldinfo) & ('keysecondary' in worldinfo) & ('content' in worldinfo)) { - for (keyword of worldinfo['key']) { - if ((action.textContent.replace(/[^0-9a-z \'\"]/gi, '')).includes(keyword)) { - //Ok we have a key match, but we need to check for secondary keys if applicable - if (worldinfo['keysecondary'].length > 0) { - if ('keysecondary' in worldinfo) { - for (second_key of worldinfo['keysecondary']) { - if (action.textContent.replace(/[^0-9a-z \'\"]/gi, '').includes(second_key)) { - //OK we have the phrase in our action. Let's see if we can identify the word(s) that are triggering - for (var i = 0; i < words.length; i++) { - key_words = keyword.split(" ").length; - var to_check = words_text.slice(i, i+key_words).join("").replace(/[^0-9a-z \'\"]/gi, '').trim(); - if (keyword == to_check) { - for (var j = i; j < key_words+i; j++) { - words[j].title = worldinfo['content']; - words[j].classList.add("tag_wiid_"+wiid); + for (const [key, worldinfo] of Object.entries(worldinfo_to_check)) { + //remove any world info tags + for (tag of action.getElementsByClassName("tag_wiid_"+wiid)) { + tag.classList.remove("tag_wiid_"+wiid); + tag.removeAttribute("title"); + } + + if (('key' in worldinfo) & ('keysecondary' in worldinfo) & ('content' in worldinfo)) { + for (keyword of worldinfo['key']) { + if ((action.textContent.replace(/[^0-9a-z \'\"]/gi, '')).includes(keyword)) { + //Ok we have a key match, but we need to check for secondary keys if applicable + if (worldinfo['keysecondary'].length > 0) { + if ('keysecondary' in worldinfo) { + for (second_key of worldinfo['keysecondary']) { + if (action.textContent.replace(/[^0-9a-z \'\"]/gi, '').includes(second_key)) { + //OK we have the phrase in our action. Let's see if we can identify the word(s) that are triggering + for (var i = 0; i < words.length; i++) { + key_words = keyword.split(" ").length; + var to_check = words_text.slice(i, i+key_words).join("").replace(/[^0-9a-z \'\"]/gi, '').trim(); + if (keyword == to_check) { + for (var j = i; j < key_words+i; j++) { + words[j].title = worldinfo['content']; + words[j].classList.add("tag_wiid_"+wiid); + } } } } } } - } - } else { - //OK we have the phrase in our action. Let's see if we can identify the word(s) that are triggering - for (var i = 0; i < words.length; i++) { - key_words = keyword.split(" ").length; - var to_check = words_text.slice(i, i+key_words).join("").replace(/[^0-9a-z \'\"]/gi, '').trim(); - if (keyword == to_check) { - for (var j = i; j < key_words+i; j++) { - words[j].title = worldinfo['content']; - words[j].classList.add("tag_wiid_"+wiid); + } else { + //OK we have the phrase in our action. Let's see if we can identify the word(s) that are triggering + for (var i = 0; i < words.length; i++) { + key_words = keyword.split(" ").length; + var to_check = words_text.slice(i, i+key_words).join("").replace(/[^0-9a-z \'\"]/gi, '').trim(); + if (keyword == to_check) { + for (var j = i; j < key_words+i; j++) { + words[j].title = worldinfo['content']; + words[j].classList.add("tag_wiid_"+wiid); + } } } } + } - } } } diff --git a/templates/story flyout.html b/templates/story flyout.html index 7a1800a3..86cd0a8b 100644 --- a/templates/story flyout.html +++ b/templates/story flyout.html @@ -29,7 +29,7 @@
Memory:
- +