Spaces:
Running
on
L40S
Running
on
L40S
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}`); | |
} | |
} | |
} | |