Spaces:
Running
on
Zero
Running
on
Zero
| import { app } from "../../scripts/app.js"; | |
| import { api } from "../../scripts/api.js" | |
| import { ComfyDialog, $el } from "../../scripts/ui.js"; | |
| import { manager_instance, rebootAPI, show_message } from "./common.js"; | |
| async function restore_snapshot(target) { | |
| if(SnapshotManager.instance) { | |
| try { | |
| const response = await api.fetchApi(`/snapshot/restore?target=${target}`, { cache: "no-store" }); | |
| if(response.status == 403) { | |
| show_message('This action is not allowed with this security level configuration.'); | |
| return false; | |
| } | |
| if(response.status == 400) { | |
| show_message(`Restore snapshot failed: ${target.title} / ${exception}`); | |
| } | |
| app.ui.dialog.close(); | |
| return true; | |
| } | |
| catch(exception) { | |
| show_message(`Restore snapshot failed: ${target.title} / ${exception}`); | |
| return false; | |
| } | |
| finally { | |
| await SnapshotManager.instance.invalidateControl(); | |
| SnapshotManager.instance.updateMessage("<BR>To apply the snapshot, please <button id='cm-reboot-button2' class='cm-small-button'>RESTART</button> ComfyUI. And refresh browser.", 'cm-reboot-button2'); | |
| } | |
| } | |
| } | |
| async function remove_snapshot(target) { | |
| if(SnapshotManager.instance) { | |
| try { | |
| const response = await api.fetchApi(`/snapshot/remove?target=${target}`, { cache: "no-store" }); | |
| if(response.status == 403) { | |
| show_message('This action is not allowed with this security level configuration.'); | |
| return false; | |
| } | |
| if(response.status == 400) { | |
| show_message(`Remove snapshot failed: ${target.title} / ${exception}`); | |
| } | |
| app.ui.dialog.close(); | |
| return true; | |
| } | |
| catch(exception) { | |
| show_message(`Restore snapshot failed: ${target.title} / ${exception}`); | |
| return false; | |
| } | |
| finally { | |
| await SnapshotManager.instance.invalidateControl(); | |
| } | |
| } | |
| } | |
| async function save_current_snapshot() { | |
| try { | |
| const response = await api.fetchApi('/snapshot/save', { cache: "no-store" }); | |
| app.ui.dialog.close(); | |
| return true; | |
| } | |
| catch(exception) { | |
| show_message(`Backup snapshot failed: ${exception}`); | |
| return false; | |
| } | |
| finally { | |
| await SnapshotManager.instance.invalidateControl(); | |
| SnapshotManager.instance.updateMessage("<BR>Current snapshot saved."); | |
| } | |
| } | |
| async function getSnapshotList() { | |
| const response = await api.fetchApi(`/snapshot/getlist`); | |
| const data = await response.json(); | |
| return data; | |
| } | |
| export class SnapshotManager extends ComfyDialog { | |
| static instance = null; | |
| restore_buttons = []; | |
| message_box = null; | |
| data = null; | |
| clear() { | |
| this.restore_buttons = []; | |
| this.message_box = null; | |
| this.data = null; | |
| } | |
| constructor(app, manager_dialog) { | |
| super(); | |
| this.manager_dialog = manager_dialog; | |
| this.search_keyword = ''; | |
| this.element = $el("div.comfy-modal", { parent: document.body }, []); | |
| } | |
| async remove_item() { | |
| caller.disableButtons(); | |
| await caller.invalidateControl(); | |
| } | |
| createControls() { | |
| return [ | |
| $el("button.cm-small-button", { | |
| type: "button", | |
| textContent: "Close", | |
| onclick: () => { this.close(); } | |
| }) | |
| ]; | |
| } | |
| startRestore(target) { | |
| const self = SnapshotManager.instance; | |
| self.updateMessage(`<BR><font color="green">Restore snapshot '${target.name}'</font>`); | |
| for(let i in self.restore_buttons) { | |
| self.restore_buttons[i].disabled = true; | |
| self.restore_buttons[i].style.backgroundColor = 'gray'; | |
| } | |
| } | |
| async invalidateControl() { | |
| this.clear(); | |
| this.data = (await getSnapshotList()).items; | |
| while (this.element.children.length) { | |
| this.element.removeChild(this.element.children[0]); | |
| } | |
| await this.createGrid(); | |
| await this.createBottomControls(); | |
| } | |
| updateMessage(msg, btn_id) { | |
| this.message_box.innerHTML = msg; | |
| if(btn_id) { | |
| const rebootButton = document.getElementById(btn_id); | |
| const self = this; | |
| rebootButton.onclick = function() { | |
| if(rebootAPI()) { | |
| self.close(); | |
| self.manager_dialog.close(); | |
| } | |
| }; | |
| } | |
| } | |
| async createGrid(models_json) { | |
| var grid = document.createElement('table'); | |
| grid.setAttribute('id', 'snapshot-list-grid'); | |
| var thead = document.createElement('thead'); | |
| var tbody = document.createElement('tbody'); | |
| var headerRow = document.createElement('tr'); | |
| thead.style.position = "sticky"; | |
| thead.style.top = "0px"; | |
| thead.style.borderCollapse = "collapse"; | |
| thead.style.tableLayout = "fixed"; | |
| var header1 = document.createElement('th'); | |
| header1.innerHTML = ' ID '; | |
| header1.style.width = "20px"; | |
| var header2 = document.createElement('th'); | |
| header2.innerHTML = 'Datetime'; | |
| header2.style.width = "100%"; | |
| var header_button = document.createElement('th'); | |
| header_button.innerHTML = 'Action'; | |
| header_button.style.width = "100px"; | |
| thead.appendChild(headerRow); | |
| headerRow.appendChild(header1); | |
| headerRow.appendChild(header2); | |
| headerRow.appendChild(header_button); | |
| headerRow.style.backgroundColor = "Black"; | |
| headerRow.style.color = "White"; | |
| headerRow.style.textAlign = "center"; | |
| headerRow.style.width = "100%"; | |
| headerRow.style.padding = "0"; | |
| grid.appendChild(thead); | |
| grid.appendChild(tbody); | |
| this.grid_rows = {}; | |
| if(this.data) | |
| for (var i = 0; i < this.data.length; i++) { | |
| const data = this.data[i]; | |
| var dataRow = document.createElement('tr'); | |
| var data1 = document.createElement('td'); | |
| data1.style.textAlign = "center"; | |
| data1.innerHTML = i+1; | |
| var data2 = document.createElement('td'); | |
| data2.innerHTML = ` ${data}`; | |
| var data_button = document.createElement('td'); | |
| data_button.style.textAlign = "center"; | |
| var restoreBtn = document.createElement('button'); | |
| restoreBtn.innerHTML = 'Restore'; | |
| restoreBtn.style.width = "100px"; | |
| restoreBtn.style.backgroundColor = 'blue'; | |
| restoreBtn.addEventListener('click', function() { | |
| restore_snapshot(data); | |
| }); | |
| var removeBtn = document.createElement('button'); | |
| removeBtn.innerHTML = 'Remove'; | |
| removeBtn.style.width = "100px"; | |
| removeBtn.style.backgroundColor = 'red'; | |
| removeBtn.addEventListener('click', function() { | |
| remove_snapshot(data); | |
| }); | |
| data_button.appendChild(restoreBtn); | |
| data_button.appendChild(removeBtn); | |
| dataRow.style.backgroundColor = "var(--bg-color)"; | |
| dataRow.style.color = "var(--fg-color)"; | |
| dataRow.style.textAlign = "left"; | |
| dataRow.appendChild(data1); | |
| dataRow.appendChild(data2); | |
| dataRow.appendChild(data_button); | |
| tbody.appendChild(dataRow); | |
| this.grid_rows[i] = {data:data, control:dataRow}; | |
| } | |
| let self = this; | |
| const panel = document.createElement('div'); | |
| panel.style.width = "100%"; | |
| panel.appendChild(grid); | |
| function handleResize() { | |
| const parentHeight = self.element.clientHeight; | |
| const gridHeight = parentHeight - 200; | |
| grid.style.height = gridHeight + "px"; | |
| } | |
| window.addEventListener("resize", handleResize); | |
| grid.style.position = "relative"; | |
| grid.style.display = "inline-block"; | |
| grid.style.width = "100%"; | |
| grid.style.height = "100%"; | |
| grid.style.overflowY = "scroll"; | |
| this.element.style.height = "85%"; | |
| this.element.style.width = "80%"; | |
| this.element.appendChild(panel); | |
| handleResize(); | |
| } | |
| async createBottomControls() { | |
| var close_button = document.createElement("button"); | |
| close_button.className = "cm-small-button"; | |
| close_button.innerHTML = "Close"; | |
| close_button.onclick = () => { this.close(); } | |
| close_button.style.display = "inline-block"; | |
| var save_button = document.createElement("button"); | |
| save_button.className = "cm-small-button"; | |
| save_button.innerHTML = "Save snapshot"; | |
| save_button.onclick = () => { save_current_snapshot(); } | |
| save_button.style.display = "inline-block"; | |
| save_button.style.horizontalAlign = "right"; | |
| save_button.style.width = "170px"; | |
| this.message_box = $el('div', {id:'custom-download-message'}, [$el('br'), '']); | |
| this.message_box.style.height = '60px'; | |
| this.message_box.style.verticalAlign = 'middle'; | |
| this.element.appendChild(this.message_box); | |
| this.element.appendChild(close_button); | |
| this.element.appendChild(save_button); | |
| } | |
| async show() { | |
| try { | |
| this.invalidateControl(); | |
| this.element.style.display = "block"; | |
| this.element.style.zIndex = 10001; | |
| } | |
| catch(exception) { | |
| app.ui.dialog.show(`Failed to get external model list. / ${exception}`); | |
| } | |
| } | |
| } | |