From f8e9f346313518c450e201e818de7293e3072846 Mon Sep 17 00:00:00 2001 From: ebolam Date: Mon, 29 Aug 2022 15:17:00 -0400 Subject: [PATCH] Import/Export world info folders --- aiserver.py | 15 ++++++++++++--- koboldai_settings.py | 35 ++++++++++++++++++++--------------- static/koboldai.css | 30 ++++++++++++++++++++++++++++++ static/koboldai.js | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 18 deletions(-) diff --git a/aiserver.py b/aiserver.py index 3fae32c6..53a7024a 100644 --- a/aiserver.py +++ b/aiserver.py @@ -7322,12 +7322,21 @@ def UI_2_export_world_info_folder(): else: data = koboldai_vars.worldinfo_v2.to_json() folder = koboldai_vars.story_name - return Response( - data, + json.dumps(data, indent="\t"), mimetype="application/json", headers={"Content-disposition": - "attachment; filename={}_world_info.json".format(folder)}) + "attachment; filename={}_world_info.json".format(folder)} + ) + +#==================================================================# +# Event triggered when user exports world info folder +#==================================================================# +@socketio.on('upload_world_info_folder') +def UI_2_upload_world_info_folder(data): + json_data = json.loads(data['data']) + koboldai_vars.worldinfo_v2.load_json(json_data, folder=data['folder']) + #==================================================================# # Event triggered when user edits phrase biases diff --git a/koboldai_settings.py b/koboldai_settings.py index 8a087f54..43073bff 100644 --- a/koboldai_settings.py +++ b/koboldai_settings.py @@ -1367,21 +1367,26 @@ class KoboldWorldInfo(object): "entries": {x: self.world_info[x] for x in self.world_info if self.world_info[x]['folder'] == folder} } - def load_json(self, data): - self.world_info = {int(x): data['entries'][x] for x in data['entries']} - self.world_info_folder = data['folders'] - #Make sure we have all the appropriate variables: - for item in self.world_info: - for column in ["uid","title","key","keysecondary","folder","constant","content","comment","token_length","selective","used_in_game"]: - if column not in item: - item[column] = None - try: - self.sync_world_info_to_old_format() - except: - print(self.world_info) - print(data) - raise - self.send_to_ui() + def load_json(self, data, folder=None): + if folder is None: + self.world_info = {int(x): data['entries'][x] for x in data['entries']} + self.world_info_folder = data['folders'] + #Make sure we have all the appropriate variables: + for item in self.world_info: + for column in ["uid","title","key","keysecondary","folder","constant","content","comment","token_length","selective","used_in_game"]: + if column not in item: + item[column] = None + try: + self.sync_world_info_to_old_format() + except: + print(self.world_info) + print(data) + raise + self.send_to_ui() + else: + for uid, item in data['entries'].items(): + self.add_item(item['title'], item['key'], item['keysecondary'], folder, item['constant'], item['manual_text'], item['comment'], + use_wpp=item['use_wpp'], wpp=item['wpp']) def sync_world_info_to_old_format(self): #Since the old UI uses world info entries for folders, we need to make some up diff --git a/static/koboldai.css b/static/koboldai.css index b790b20b..7bc9b378 100644 --- a/static/koboldai.css +++ b/static/koboldai.css @@ -829,6 +829,36 @@ td.server_vars { text-align: center; } +.WI_Folder_Header { + margin-left: 10px; + display: grid; + grid-template-areas: "folder expand title upload_box upload download"; + grid-template-columns: 15px 30px auto 0px 25px 25px; +} + +.WI_Folder_Header .folder { + grid-area: folder; +} + +.WI_Folder_Header .expand { + grid-area: expand; +} + +.WI_Folder_Header .title { + grid-area: title; +} + +.WI_Folder_Header .upload_box { + grid-area: upload_box; + display: none; +} + +.WI_Folder_Header .download { + grid-area: download; +} + + + #world_info_folder_root.WI_Folder { margin-left: 10px; } diff --git a/static/koboldai.js b/static/koboldai.js index b644c7d5..a8825a62 100644 --- a/static/koboldai.js +++ b/static/koboldai.js @@ -1479,6 +1479,7 @@ function world_info_folder(data) { title.addEventListener('dragover', dragOver); title.addEventListener('dragleave', dragLeave); title.addEventListener('drop', drop); + title.classList.add("WI_Folder_Header"); collapse_icon = document.createElement("span"); collapse_icon.id = "world_info_folder_collapse_"+folder_name; collapse_icon.classList.add("wi_folder_collapser"); @@ -1490,6 +1491,7 @@ function world_info_folder(data) { document.getElementById('world_info_folder_expand_'+this.getAttribute("folder")).classList.remove('hidden'); this.classList.add("hidden"); }; + collapse_icon.classList.add("expand") title.append(collapse_icon); expand_icon = document.createElement("span"); expand_icon.id = "world_info_folder_expand_"+folder_name; @@ -1502,12 +1504,14 @@ function world_info_folder(data) { document.getElementById('world_info_folder_collapse_'+this.getAttribute("folder")).classList.remove('hidden'); this.classList.add("hidden"); }; + expand_icon.classList.add("expand") expand_icon.classList.add("hidden"); title.append(expand_icon); icon = document.createElement("span"); icon.classList.add("material-icons-outlined"); icon.setAttribute("folder", folder_name); icon.textContent = "folder"; + icon.classList.add("folder"); title.append(icon); title_text = document.createElement("span"); title_text.classList.add("wi_title"); @@ -1520,16 +1524,52 @@ function world_info_folder(data) { socket.emit("Rename_World_Info_Folder", {"old_folder": this.getAttribute("original_text"), "new_folder": this.textContent}); } } + title_text.classList.add("title"); title.append(title_text); //create download button download = document.createElement("span"); download.classList.add("material-icons-outlined"); + download.classList.add("cursor"); download.setAttribute("folder", folder_name); download.textContent = "file_download"; download.onclick = function () { document.getElementById('download_iframe').src = 'export_world_info_folder?folder='+this.getAttribute("folder"); }; + download.classList.add("download"); title.append(download); + + //upload element + upload_element = document.createElement("input"); + upload_element.id = "wi_upload_element_"+folder_name; + upload_element.type = "file"; + upload_element.setAttribute("folder", folder_name); + upload_element.classList.add("upload_box"); + upload_element.onchange = function () { + var fileList = this.files; + for (file of fileList) { + reader = new FileReader(); + reader.folder = this.getAttribute("folder"); + reader.onload = function (event) { + socket.emit("upload_world_info_folder", {'folder': event.target.folder, 'filename': file.name, "data": event.target.result}); + }; + reader.readAsArrayBuffer(file); + + } + }; + title.append(upload_element); + + //create upload button + upload = document.createElement("span"); + upload.classList.add("material-icons-outlined"); + upload.classList.add("cursor"); + upload.setAttribute("folder", folder_name); + upload.textContent = "file_upload"; + upload.onclick = function () { + document.getElementById('wi_upload_element_'+this.getAttribute("folder")).click(); + //document.getElementById('download_iframe').src = 'export_world_info_folder?folder='+this.getAttribute("folder"); + }; + upload.classList.add("upload"); + title.append(upload); folder.append(title); //create add button