|
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}`); |
|
} |
|
} |
|
} |
|
|