From b51580fe6a031241f6f63fcd36a43d0b36fe8f33 Mon Sep 17 00:00:00 2001 From: "ilian.iliev" Date: Tue, 11 Apr 2023 11:50:54 +0300 Subject: [PATCH] Export and import state actions implemented --- javascript/state.core.js | 43 ++++++++++++++++++++++++++++++++------- javascript/state.store.js | 35 ++++++++++++++++++++++++++----- javascript/state.utils.js | 25 +++++++++++++++++++++++ style.css | 12 ++++++++++- 4 files changed, 102 insertions(+), 13 deletions(-) diff --git a/javascript/state.core.js b/javascript/state.core.js index 24f8984..246184c 100644 --- a/javascript/state.core.js +++ b/javascript/state.core.js @@ -105,13 +105,7 @@ state.core = (function () { function loadUI() { let resetBtn = document.createElement("button"); resetBtn.innerHTML = "*️⃣"; - resetBtn.addEventListener('click', function () { - let confirmed = confirm('Reset all state values?'); - if (confirmed) { - store.clearAll(); - alert('All state values deleted!'); - } - }); + resetBtn.addEventListener('click', actions.resetAll); let quickSettings = gradioApp().getElementById("quicksettings"); resetBtn.className = quickSettings.querySelector('button').className; quickSettings.appendChild(resetBtn); @@ -268,8 +262,43 @@ state.core = (function () { 'marginTop': '20px', 'marginBottom': '10px' }); + buttonsContainer.appendChild(state.utils.html.create('hr')); + buttonsContainer.appendChild(state.utils.html.create('div', { innerHTML: 'Actions' }, { marginBottom: '10px' })); + buttonsContainer.appendChild(state.utils.html.createButton('Reset All', actions.resetAll)); + buttonsContainer.appendChild(state.utils.html.createButton('Export State', actions.exportState)); + buttonsContainer.appendChild(state.utils.html.createButton('Import State', actions.importState)); + buttonsContainer.appendChild(state.utils.html.create('input', { + id: 'state-import-file', type: 'file', accept: 'application/json' + })); page.appendChild(buttonsContainer); } + let actions = { + resetAll: function () { + let confirmed = confirm('Reset all state values?'); + if (confirmed) { + store.clearAll(); + alert('All state values deleted!'); + } + }, + exportState: function () { + state.utils.saveFile('sd-webui-state', store.getAll()); + }, + importState: function () { + const fileInput = gradioApp().getElementById('state-import-file'); + if (! fileInput.files || ! fileInput.files[0]) { + alert('Please select a JSON file!'); + return; + } + const file = fileInput.files[0]; + const reader = new FileReader(); + reader.onload = function (event) { + store.load(JSON.parse(event.target.result)); + window.location.reload(); + }; + reader.readAsText(file); + } + }; + return { init }; }()); diff --git a/javascript/state.store.js b/javascript/state.store.js index eb1a58b..f7a16c3 100644 --- a/javascript/state.store.js +++ b/javascript/state.store.js @@ -5,19 +5,23 @@ state.Store = function Store (prefix) { this.prefix = state.constants.LS_PREFIX + (prefix ? prefix + '-' : ''); } -state.Store.prototype.set = function(key, value) { - localStorage.setItem(this.prefix + key, value); +state.Store.prototype.set = function (key, value) { + if (key.startsWith(this.prefix)) { + localStorage.setItem(key, value); + } else { + localStorage.setItem(this.prefix + key, value); + } }; -state.Store.prototype.get = function(key) { +state.Store.prototype.get = function (key) { return localStorage.getItem(this.prefix + key); }; -state.Store.prototype.remove = function(key) { +state.Store.prototype.remove = function (key) { localStorage.removeItem(this.prefix + key); }; -state.Store.prototype.clear = function() { +state.Store.prototype.clear = function () { localStorage.clear(); }; @@ -29,3 +33,24 @@ state.Store.prototype.clearAll = function () { } } }; + +state.Store.prototype.getAll = function () { + let result = {}; + let keys = Object.keys(localStorage); + for (let i = 0; i < keys.length; i++) { + if (keys[i].startsWith(state.constants.LS_PREFIX)) { + result[keys[i]] = localStorage[keys[i]]; + } + } + return result; +}; + +state.Store.prototype.load = function (json) { + this.clearAll(); + let keys = Object.keys(json); + for (let i = 0; i < keys.length; i++) { + if (keys[i].startsWith(state.constants.LS_PREFIX)) { + this.set(keys[i], json[keys[i]]); + } + } +}; diff --git a/javascript/state.utils.js b/javascript/state.utils.js index 752ad4f..21d69f7 100644 --- a/javascript/state.utils.js +++ b/javascript/state.utils.js @@ -143,6 +143,17 @@ state.utils = { } } }, + saveFile: function saveJSON(fileName ,data) { + const json = JSON.stringify(data, null, 4); + const blob = new Blob([json], {type: 'application/json'}); + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.download = fileName + '.json'; + document.body.appendChild(link); + link.click(); + link.parentNode.removeChild(link); + }, debounce: function debounce(func, delay) { let lastCallTime = 0; return function() { @@ -176,6 +187,20 @@ state.utils.html = { } }); }, + create: function create(type, props, style) { + const element = document.createElement(type); + if (props) { + for (let key in props) { + if (props.hasOwnProperty(key)) { + element[key] = props[key]; + } + } + } + if (style) { + this.setStyle(element, style); + } + return element; + }, createButton: function createButton(text, onclick) { const btn = document.createElement('button'); btn.innerHTML = text; diff --git a/style.css b/style.css index 86c49f2..9eaccc5 100644 --- a/style.css +++ b/style.css @@ -1,4 +1,5 @@ -#settings_state_buttons button { +#settings_state_buttons button, +#settings_state_buttons input[type="file"] { color: white; background: rgb(249, 115, 22); border-radius: 8px; @@ -7,4 +8,13 @@ font-size: 16px; margin-left: 5px; margin-right: 5px; +} + +#settings_state_buttons input[type="file"] { + padding: 3px 5px; +} + +#settings_state hr { + margin-top: 32px; + margin-bottom: 32px; } \ No newline at end of file