feat: stop feature
feat: model-manager - support background tasking
This commit is contained in:
@@ -55,6 +55,12 @@ const pageCss = `
|
||||
color: white;
|
||||
}
|
||||
|
||||
.cn-manager .cn-manager-stop {
|
||||
display: none;
|
||||
background-color: #500000;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.cn-manager .cn-manager-back {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -344,13 +350,14 @@ const pageHtml = `
|
||||
<div class="cn-manager-selection"></div>
|
||||
<div class="cn-manager-message"></div>
|
||||
<div class="cn-manager-footer">
|
||||
<button class="cn-manager-back">
|
||||
<svg class="arrow-icon" width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2 8H18M2 8L8 2M2 8L8 14" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
Back
|
||||
</button>
|
||||
<button class="cn-manager-back">
|
||||
<svg class="arrow-icon" width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2 8H18M2 8L8 2M2 8L8 14" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
Back
|
||||
</button>
|
||||
<button class="cn-manager-restart">Restart</button>
|
||||
<button class="cn-manager-stop">Stop</button>
|
||||
<div class="cn-flex-auto"></div>
|
||||
<button class="cn-manager-check-update">Check Update</button>
|
||||
<button class="cn-manager-check-missing">Check Missing</button>
|
||||
@@ -392,7 +399,7 @@ export class CustomNodesManager {
|
||||
|
||||
this.init();
|
||||
|
||||
api.addEventListener("cm-install-status", this.onInstallStatus);
|
||||
api.addEventListener("cm-queue-status", this.onQueueStatus);
|
||||
}
|
||||
|
||||
init() {
|
||||
@@ -762,6 +769,13 @@ export class CustomNodesManager {
|
||||
}
|
||||
},
|
||||
|
||||
".cn-manager-stop": {
|
||||
click: () => {
|
||||
api.fetchApi('/manager/queue/reset');
|
||||
infoToast('Cancel', 'Remaining tasks will stop after completing the current task.');
|
||||
}
|
||||
},
|
||||
|
||||
".cn-manager-check-update": {
|
||||
click: (e) => {
|
||||
e.target.classList.add("cn-btn-loading");
|
||||
@@ -1271,9 +1285,9 @@ export class CustomNodesManager {
|
||||
}
|
||||
|
||||
async installNodes(list, btn, title, selected_version) {
|
||||
let stats = await api.fetchApi('/customnode/queue/count');
|
||||
let stats = await api.fetchApi('/manager/queue/status');
|
||||
stats = await stats.json();
|
||||
if(stats.total_count > 0) {
|
||||
if(stats.in_progress) {
|
||||
customAlert(`[ComfyUI-Manager] There are already tasks in progress. Please try again after it is completed. (${stats.done_count}/${stats.total_count})`);
|
||||
return;
|
||||
}
|
||||
@@ -1304,11 +1318,13 @@ export class CustomNodesManager {
|
||||
let needRestart = false;
|
||||
let errorMsg = "";
|
||||
|
||||
await api.fetchApi('/customnode/queue/reset');
|
||||
this.install_context = btn;
|
||||
await api.fetchApi('/manager/queue/reset');
|
||||
|
||||
let target_items = [];
|
||||
|
||||
for (const hash of list) {
|
||||
const item = this.grid.getRowItemBy("hash", hash);
|
||||
target_items.push(item);
|
||||
|
||||
if (!item) {
|
||||
errorMsg = `Not found custom node: ${hash}`;
|
||||
@@ -1347,7 +1363,7 @@ export class CustomNodesManager {
|
||||
api_mode = 'reinstall';
|
||||
}
|
||||
|
||||
const res = await api.fetchApi(`/customnode/queue/${api_mode}`, {
|
||||
const res = await api.fetchApi(`/manager/queue/${api_mode}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
@@ -1367,18 +1383,32 @@ export class CustomNodesManager {
|
||||
}
|
||||
}
|
||||
|
||||
this.install_context = {btn: btn, targets: target_items};
|
||||
|
||||
for(let k in target_items) {
|
||||
let item = this.install_context.targets[k];
|
||||
this.grid.updateCell(item, "action");
|
||||
}
|
||||
|
||||
if(errorMsg) {
|
||||
this.showError(errorMsg);
|
||||
show_message("Installation Error:\n"+errorMsg);
|
||||
|
||||
// reset
|
||||
for (const hash of list) {
|
||||
const item = this.grid.getRowItemBy("hash", hash);
|
||||
self.grid.updateCell(item, "action");
|
||||
}
|
||||
}
|
||||
else {
|
||||
await api.fetchApi('/customnode/queue/start');
|
||||
await api.fetchApi('/manager/queue/start');
|
||||
this.showStop();
|
||||
}
|
||||
}
|
||||
|
||||
async onInstallStatus(event) {
|
||||
async onQueueStatus(event) {
|
||||
let self = CustomNodesManager.instance;
|
||||
if(event.detail.status == 'in_progress') {
|
||||
if(event.detail.status == 'in_progress' && event.detail.ui_target == 'nodepack_manager') {
|
||||
const hash = event.detail.target;
|
||||
|
||||
const item = self.grid.getRowItemBy("hash", hash);
|
||||
@@ -1386,14 +1416,20 @@ export class CustomNodesManager {
|
||||
item.restart = true;
|
||||
self.restartMap[item.hash] = true;
|
||||
self.grid.updateCell(item, "action");
|
||||
self.grid.setRowSelected(item, false);
|
||||
}
|
||||
else if(event.detail.status == 'done') {
|
||||
self.onInstallCompleted(event.detail);
|
||||
self.hideStop();
|
||||
self.onQueueCompleted(event.detail);
|
||||
}
|
||||
}
|
||||
|
||||
async onInstallCompleted(info) {
|
||||
let result = info.result;
|
||||
async onQueueCompleted(info) {
|
||||
let result = info.nodepack_result;
|
||||
|
||||
if(result.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let self = CustomNodesManager.instance;
|
||||
|
||||
@@ -1401,7 +1437,7 @@ export class CustomNodesManager {
|
||||
return;
|
||||
}
|
||||
|
||||
const { target, label, mode } = self.install_context;
|
||||
const { target, label, mode } = self.install_context.btn;
|
||||
target.classList.remove("cn-btn-loading");
|
||||
|
||||
let errorMsg = "";
|
||||
@@ -1409,13 +1445,15 @@ export class CustomNodesManager {
|
||||
for(let hash in result){
|
||||
let v = result[hash];
|
||||
|
||||
const item = self.grid.getRowItemBy("hash", hash);
|
||||
self.grid.setRowSelected(item, false);
|
||||
|
||||
if(v != 'success')
|
||||
errorMsg += v;
|
||||
}
|
||||
|
||||
for(let k in self.install_context.targets) {
|
||||
let item = self.install_context.targets[k];
|
||||
self.grid.updateCell(item, "action");
|
||||
}
|
||||
|
||||
if (errorMsg) {
|
||||
self.showError(errorMsg);
|
||||
show_message("Installation Error:\n"+errorMsg);
|
||||
@@ -1426,7 +1464,7 @@ export class CustomNodesManager {
|
||||
self.showRestart();
|
||||
self.showMessage(`To apply the installed/updated/disabled/enabled custom node, please restart ComfyUI. And refresh browser.`, "red");
|
||||
|
||||
infoToast(`[ComfyUI-Manager] All tasks in the queue have been completed.\n${info.done_count}/${info.total_count}`);
|
||||
infoToast(`[ComfyUI-Manager] All node pack tasks in the queue have been completed.\n${info.done_count}/${info.total_count}`);
|
||||
self.install_context = undefined;
|
||||
}
|
||||
|
||||
@@ -1808,9 +1846,9 @@ export class CustomNodesManager {
|
||||
}
|
||||
|
||||
setDisabled(disabled) {
|
||||
|
||||
const $close = this.element.querySelector(".cn-manager-close");
|
||||
const $restart = this.element.querySelector(".cn-manager-restart");
|
||||
const $stop = this.element.querySelector(".cn-manager-stop");
|
||||
|
||||
const list = [
|
||||
".cn-manager-header input",
|
||||
@@ -1822,7 +1860,7 @@ export class CustomNodesManager {
|
||||
})
|
||||
.flat()
|
||||
.filter(it => {
|
||||
return it !== $close && it !== $restart;
|
||||
return it !== $close && it !== $restart && it !== $stop;
|
||||
});
|
||||
|
||||
list.forEach($elem => {
|
||||
@@ -1843,6 +1881,14 @@ export class CustomNodesManager {
|
||||
this.element.querySelector(".cn-manager-restart").style.display = "block";
|
||||
}
|
||||
|
||||
showStop() {
|
||||
this.element.querySelector(".cn-manager-stop").style.display = "block";
|
||||
}
|
||||
|
||||
hideStop() {
|
||||
this.element.querySelector(".cn-manager-stop").style.display = "none";
|
||||
}
|
||||
|
||||
setFilter(filterValue) {
|
||||
let filter = "";
|
||||
const filterItem = this.getFilterItem(filterValue);
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { $el } from "../../scripts/ui.js";
|
||||
import {
|
||||
manager_instance, rebootAPI,
|
||||
fetchData, md5, icons
|
||||
fetchData, md5, icons, show_message, customAlert, infoToast
|
||||
} from "./common.js";
|
||||
import { api } from "../../scripts/api.js";
|
||||
|
||||
// https://cenfun.github.io/turbogrid/api.html
|
||||
import TG from "./turbogrid.esm.js";
|
||||
@@ -46,6 +48,18 @@ const pageCss = `
|
||||
background-color: var(--comfy-input-bg);
|
||||
}
|
||||
|
||||
.cmm-manager .cmm-manager-refresh {
|
||||
display: none;
|
||||
background-color: #000080;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.cmm-manager .cmm-manager-stop {
|
||||
display: none;
|
||||
background-color: #500000;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.cmm-manager-header {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -235,7 +249,14 @@ const pageHtml = `
|
||||
<div class="cmm-manager-selection"></div>
|
||||
<div class="cmm-manager-message"></div>
|
||||
<div class="cmm-manager-footer">
|
||||
<button class="cmm-manager-back">Back</button>
|
||||
<button class="cmm-manager-back">
|
||||
<svg class="arrow-icon" width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2 8H18M2 8L8 2M2 8L8 14" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
Back
|
||||
</button>
|
||||
<button class="cmm-manager-refresh">Refresh</button>
|
||||
<button class="cmm-manager-stop">Stop</button>
|
||||
<div class="cmm-flex-auto"></div>
|
||||
</div>
|
||||
`;
|
||||
@@ -254,6 +275,8 @@ export class ModelManager {
|
||||
this.keywords = '';
|
||||
|
||||
this.init();
|
||||
|
||||
api.addEventListener("cm-queue-status", this.onQueueStatus);
|
||||
}
|
||||
|
||||
init() {
|
||||
@@ -365,12 +388,25 @@ export class ModelManager {
|
||||
}
|
||||
},
|
||||
|
||||
".cmm-manager-refresh": {
|
||||
click: () => {
|
||||
app.refreshComboInNodes();
|
||||
}
|
||||
},
|
||||
|
||||
".cmm-manager-stop": {
|
||||
click: () => {
|
||||
api.fetchApi('/manager/queue/reset');
|
||||
infoToast('Cancel', 'Remaining tasks will stop after completing the current task.');
|
||||
}
|
||||
},
|
||||
|
||||
".cmm-manager-back": {
|
||||
click: (e) => {
|
||||
this.close()
|
||||
manager_instance.show();
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
Object.keys(eventsMap).forEach(selector => {
|
||||
const target = this.element.querySelector(selector);
|
||||
@@ -595,17 +631,28 @@ export class ModelManager {
|
||||
}
|
||||
|
||||
async installModels(list, btn) {
|
||||
|
||||
let stats = await api.fetchApi('/manager/queue/status');
|
||||
|
||||
stats = await stats.json();
|
||||
if(stats.in_progress) {
|
||||
customAlert(`[ComfyUI-Manager] There are already tasks in progress. Please try again after it is completed. (${stats.done_count}/${stats.total_count})`);
|
||||
return;
|
||||
}
|
||||
|
||||
btn.classList.add("cmm-btn-loading");
|
||||
this.showLoading();
|
||||
this.showError("");
|
||||
|
||||
let needRestart = false;
|
||||
let needRefresh = false;
|
||||
let errorMsg = "";
|
||||
|
||||
await api.fetchApi('/manager/queue/reset');
|
||||
|
||||
let target_items = [];
|
||||
|
||||
for (const item of list) {
|
||||
|
||||
this.grid.scrollRowIntoView(item);
|
||||
target_items.push(item);
|
||||
|
||||
if (!this.focusInstall(item)) {
|
||||
this.grid.onNextUpdated(() => {
|
||||
@@ -616,48 +663,104 @@ export class ModelManager {
|
||||
this.showStatus(`Install ${item.name} ...`);
|
||||
|
||||
const data = item.originalData;
|
||||
const res = await fetchData('/model/install', {
|
||||
data.ui_id = item.hash;
|
||||
|
||||
const res = await api.fetchApi(`/manager/queue/install_model`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
|
||||
if (res.error) {
|
||||
if (res.status != 200) {
|
||||
errorMsg = `Install failed: ${item.name} ${res.error.message}`;
|
||||
break;;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
needRestart = true;
|
||||
this.install_context = {btn: btn, targets: target_items};
|
||||
|
||||
this.grid.setRowSelected(item, false);
|
||||
if(errorMsg) {
|
||||
this.showError(errorMsg);
|
||||
show_message("Installation Error:\n"+errorMsg);
|
||||
|
||||
// reset
|
||||
for (const hash of list) {
|
||||
const item = this.grid.getRowItemBy("hash", hash);
|
||||
this.grid.updateCell(item, "installed");
|
||||
}
|
||||
}
|
||||
else {
|
||||
await api.fetchApi('/manager/queue/start');
|
||||
this.showStop();
|
||||
}
|
||||
}
|
||||
|
||||
async onQueueStatus(event) {
|
||||
let self = ModelManager.instance;
|
||||
|
||||
if(event.detail.status == 'in_progress' && event.detail.ui_target == 'model_manager') {
|
||||
const hash = event.detail.target;
|
||||
|
||||
const item = self.grid.getRowItemBy("hash", hash);
|
||||
|
||||
item.refresh = true;
|
||||
self.grid.setRowSelected(item, false);
|
||||
item.selectable = false;
|
||||
this.grid.updateCell(item, "installed");
|
||||
this.grid.updateCell(item, "tg-column-select");
|
||||
// self.grid.updateCell(item, "tg-column-select");
|
||||
self.grid.updateRow(item);
|
||||
}
|
||||
else if(event.detail.status == 'done') {
|
||||
self.hideStop();
|
||||
self.onQueueCompleted(event.detail);
|
||||
}
|
||||
}
|
||||
|
||||
this.showStatus(`Install ${item.name} successfully`);
|
||||
async onQueueCompleted(info) {
|
||||
let result = info.model_result;
|
||||
|
||||
if(result.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.hideLoading();
|
||||
let self = ModelManager.instance;
|
||||
|
||||
if(!self.install_context) {
|
||||
return;
|
||||
}
|
||||
|
||||
let btn = self.install_context.btn;
|
||||
|
||||
self.hideLoading();
|
||||
btn.classList.remove("cmm-btn-loading");
|
||||
|
||||
let errorMsg = "";
|
||||
|
||||
for(let hash in result){
|
||||
let v = result[hash];
|
||||
|
||||
if(v != 'success')
|
||||
errorMsg += v;
|
||||
}
|
||||
|
||||
for(let k in self.install_context.targets) {
|
||||
let item = self.install_context.targets[k];
|
||||
self.grid.updateCell(item, "installed");
|
||||
}
|
||||
|
||||
if (errorMsg) {
|
||||
this.showError(errorMsg);
|
||||
self.showError(errorMsg);
|
||||
show_message("Installation Error:\n"+errorMsg);
|
||||
} else {
|
||||
this.showStatus(`Install ${list.length} models successfully`);
|
||||
self.showStatus(`Install ${result.length} models successfully`);
|
||||
}
|
||||
|
||||
if (needRestart) {
|
||||
this.showMessage(`To apply the installed model, please click the 'Refresh' button on the main menu.`, "red")
|
||||
}
|
||||
self.showRefresh();
|
||||
self.showMessage(`To apply the installed model, please click the 'Refresh' button.`, "red")
|
||||
|
||||
infoToast('Tasks done', `[ComfyUI-Manager] All model downloading tasks in the queue have been completed.\n${info.done_count}/${info.total_count}`);
|
||||
self.install_context = undefined;
|
||||
}
|
||||
|
||||
getModelList(models) {
|
||||
|
||||
const typeMap = new Map();
|
||||
const baseMap = new Map();
|
||||
|
||||
@@ -826,7 +929,7 @@ export class ModelManager {
|
||||
}
|
||||
|
||||
showLoading() {
|
||||
this.setDisabled(true);
|
||||
// this.setDisabled(true);
|
||||
if (this.grid) {
|
||||
this.grid.showLoading();
|
||||
this.grid.showMask({
|
||||
@@ -836,7 +939,7 @@ export class ModelManager {
|
||||
}
|
||||
|
||||
hideLoading() {
|
||||
this.setDisabled(false);
|
||||
// this.setDisabled(false);
|
||||
if (this.grid) {
|
||||
this.grid.hideLoading();
|
||||
this.grid.hideMask();
|
||||
@@ -844,8 +947,9 @@ export class ModelManager {
|
||||
}
|
||||
|
||||
setDisabled(disabled) {
|
||||
|
||||
const $close = this.element.querySelector(".cmm-manager-close");
|
||||
const $refresh = this.element.querySelector(".cmm-manager-refresh");
|
||||
const $stop = this.element.querySelector(".cmm-manager-stop");
|
||||
|
||||
const list = [
|
||||
".cmm-manager-header input",
|
||||
@@ -857,7 +961,7 @@ export class ModelManager {
|
||||
})
|
||||
.flat()
|
||||
.filter(it => {
|
||||
return it !== $close;
|
||||
return it !== $close && it !== $refresh && it !== $stop;
|
||||
});
|
||||
|
||||
list.forEach($elem => {
|
||||
@@ -874,6 +978,18 @@ export class ModelManager {
|
||||
|
||||
}
|
||||
|
||||
showRefresh() {
|
||||
this.element.querySelector(".cmm-manager-refresh").style.display = "block";
|
||||
}
|
||||
|
||||
showStop() {
|
||||
this.element.querySelector(".cmm-manager-stop").style.display = "block";
|
||||
}
|
||||
|
||||
hideStop() {
|
||||
this.element.querySelector(".cmm-manager-stop").style.display = "none";
|
||||
}
|
||||
|
||||
setKeywords(keywords = "") {
|
||||
this.keywords = keywords;
|
||||
this.element.querySelector(".cmm-manager-keywords").value = keywords;
|
||||
|
||||
Reference in New Issue
Block a user