| 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, handle403Response, loadCss } from "./common.js"; | |
| import { buildGuiFrame } from "./comfyui-gui-builder.js"; | |
| loadCss("./snapshot.css"); | |
| async function restore_snapshot(target) { | |
| if(SnapshotManager.instance) { | |
| try { | |
| const response = await api.fetchApi('/snapshot/restore', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ target: target }), cache: "no-store" }); | |
| if(response.status == 403) { | |
| await handle403Response(response); | |
| 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='p-button p-component'>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', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ target: target }), cache: "no-store" }); | |
| if(response.status == 403) { | |
| await handle403Response(response); | |
| 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', { method: 'POST', 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; | |
| content = $el("div.snapshot-manager"); | |
| clear() { | |
| this.restore_buttons = []; | |
| this.message_box = null; | |
| this.data = null; | |
| } | |
| constructor(app, manager_dialog) { | |
| super(); | |
| // this.manager_dialog = manager_dialog; | |
| this.search_keyword = ''; | |
| const frame = buildGuiFrame( | |
| 'snapshot-manager-dialog', // dialog id | |
| 'Snapshot Manager', // title | |
| 'i.mdi.mdi-puzzle', // icon class | |
| this.content, // dialog content element | |
| this | |
| ); // send this so we can attach close functions | |
| this.element = frame; | |
| } | |
| async remove_item() { | |
| caller.disableButtons(); | |
| await caller.invalidateControl(); | |
| } | |
| createControls() { | |
| return [ | |
| $el("button.p-button.p-component", { | |
| 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.content.children.length) { | |
| this.content.removeChild(this.content.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 = async function() { | |
| if(await 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"; | |
| data_button.className = "data-btns"; | |
| var restoreBtn = document.createElement('button'); | |
| restoreBtn.className = "snapshot-restore-btn p-button p-component"; | |
| restoreBtn.innerHTML = 'Restore'; | |
| restoreBtn.style.width = "100px"; | |
| restoreBtn.addEventListener('click', function() { | |
| restore_snapshot(data); | |
| }); | |
| var removeBtn = document.createElement('button'); | |
| removeBtn.className = "snapshot-remove-btn p-button p-component"; | |
| removeBtn.innerHTML = 'Remove'; | |
| removeBtn.style.width = "100px"; | |
| 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.style.height = "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.content.appendChild(panel); | |
| handleResize(); | |
| } | |
| async createBottomControls() { | |
| var save_button = document.createElement("button"); | |
| save_button.className = "p-button p-component"; | |
| save_button.innerHTML = "Save snapshot"; | |
| save_button.onclick = () => { save_current_snapshot(); } | |
| 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'; | |
| const footer = $el("div.snapshot-footer"); | |
| const spacer = $el("div.cn-flex-auto"); | |
| footer.appendChild(spacer); | |
| footer.appendChild(save_button); | |
| this.content.appendChild(this.message_box); | |
| this.content.appendChild(footer); | |
| } | |
| async show() { | |
| try { | |
| this.invalidateControl(); | |
| this.element.style.display = "flex"; | |
| this.element.style.zIndex = 1099; | |
| } | |
| catch(exception) { | |
| app.ui.dialog.show(`Failed to get external model list. / ${exception}`); | |
| } | |
| } | |
| } | |
Xet Storage Details
- Size:
- 8.62 kB
- Xet hash:
- 4aceeeaef0fd70cd27c57cf78e4d8c72dcfb7834d274efc691211a21a8b6da65
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.