mirror of
https://github.com/Comfy-Org/ComfyUI-Manager.git
synced 2026-07-03 13:19:20 +08:00
Model download support multiple selection
This commit is contained in:
parent
46963440df
commit
9d6cd0a58d
@ -256,7 +256,7 @@ const pageCss = `
|
|||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
100% {
|
100% {
|
||||||
left: -100px;
|
left: -105px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +281,7 @@ const pageCss = `
|
|||||||
transparent 10px,
|
transparent 10px,
|
||||||
transparent 15px
|
transparent 15px
|
||||||
);
|
);
|
||||||
animation: cn-btn-loading-bg 3s linear infinite;
|
animation: cn-btn-loading-bg 2s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cn-manager-light .cn-node-name a {
|
.cn-manager-light .cn-node-name a {
|
||||||
|
|||||||
@ -87,6 +87,13 @@ const pageCss = `
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cmm-manager-selection {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.cmm-manager-message {
|
.cmm-manager-message {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -167,7 +174,7 @@ const pageCss = `
|
|||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
100% {
|
100% {
|
||||||
left: -100px;
|
left: -105px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +199,7 @@ const pageCss = `
|
|||||||
transparent 10px,
|
transparent 10px,
|
||||||
transparent 15px
|
transparent 15px
|
||||||
);
|
);
|
||||||
animation: cmm-btn-loading-bg 3s linear infinite;
|
animation: cmm-btn-loading-bg 2s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cmm-manager-light .cmm-node-name a {
|
.cmm-manager-light .cmm-node-name a {
|
||||||
@ -225,6 +232,7 @@ const pageHtml = `
|
|||||||
<div class="cmm-flex-auto"></div>
|
<div class="cmm-flex-auto"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="cmm-manager-grid"></div>
|
<div class="cmm-manager-grid"></div>
|
||||||
|
<div class="cmm-manager-selection"></div>
|
||||||
<div class="cmm-manager-message"></div>
|
<div class="cmm-manager-message"></div>
|
||||||
<div class="cmm-manager-footer">
|
<div class="cmm-manager-footer">
|
||||||
<button class="cmm-manager-close">Close</button>
|
<button class="cmm-manager-close">Close</button>
|
||||||
@ -347,6 +355,16 @@ export class ModelManager {
|
|||||||
focus: (e) => e.target.select()
|
focus: (e) => e.target.select()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
".cmm-manager-selection": {
|
||||||
|
click: (e) => {
|
||||||
|
const target = e.target;
|
||||||
|
const mode = target.getAttribute("mode");
|
||||||
|
if (mode === "install") {
|
||||||
|
this.installModels(this.selectedModels, target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
".cmm-manager-close": {
|
".cmm-manager-close": {
|
||||||
click: (e) => this.close()
|
click: (e) => this.close()
|
||||||
},
|
},
|
||||||
@ -376,6 +394,10 @@ export class ModelManager {
|
|||||||
|
|
||||||
this.showStatus(`${grid.viewRows.length.toLocaleString()} external models`);
|
this.showStatus(`${grid.viewRows.length.toLocaleString()} external models`);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
grid.bind('onSelectChanged', (e, changes) => {
|
||||||
|
this.renderSelected();
|
||||||
});
|
});
|
||||||
|
|
||||||
grid.bind('onClick', (e, d) => {
|
grid.bind('onClick', (e, d) => {
|
||||||
@ -383,7 +405,7 @@ export class ModelManager {
|
|||||||
const target = d.e.target;
|
const target = d.e.target;
|
||||||
const mode = target.getAttribute("mode");
|
const mode = target.getAttribute("mode");
|
||||||
if (mode === "install") {
|
if (mode === "install") {
|
||||||
this.installModel(rowItem, target);
|
this.installModels([rowItem], target);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
@ -391,6 +413,10 @@ export class ModelManager {
|
|||||||
grid.setOption({
|
grid.setOption({
|
||||||
theme: 'dark',
|
theme: 'dark',
|
||||||
|
|
||||||
|
selectVisible: true,
|
||||||
|
selectMultiple: true,
|
||||||
|
selectAllVisible: true,
|
||||||
|
|
||||||
textSelectable: true,
|
textSelectable: true,
|
||||||
scrollbarRound: true,
|
scrollbarRound: true,
|
||||||
|
|
||||||
@ -505,14 +531,14 @@ export class ModelManager {
|
|||||||
width: 400,
|
width: 400,
|
||||||
maxWidth: 5000,
|
maxWidth: 5000,
|
||||||
classMap: 'cmm-node-desc'
|
classMap: 'cmm-node-desc'
|
||||||
}, {
|
|
||||||
id: 'filename',
|
|
||||||
name: 'Filename',
|
|
||||||
width: 200
|
|
||||||
}, {
|
}, {
|
||||||
id: "save_path",
|
id: "save_path",
|
||||||
name: 'Save Path',
|
name: 'Save Path',
|
||||||
width: 200
|
width: 200
|
||||||
|
}, {
|
||||||
|
id: 'filename',
|
||||||
|
name: 'Filename',
|
||||||
|
width: 200
|
||||||
}];
|
}];
|
||||||
|
|
||||||
this.grid.setData({
|
this.grid.setData({
|
||||||
@ -533,36 +559,88 @@ export class ModelManager {
|
|||||||
|
|
||||||
// ===========================================================================================
|
// ===========================================================================================
|
||||||
|
|
||||||
async installModel(item, btn) {
|
renderSelected() {
|
||||||
|
const selectedList = this.grid.getSelectedRows();
|
||||||
this.showLoading();
|
if (!selectedList.length) {
|
||||||
this.showError("");
|
this.showSelection("");
|
||||||
|
this.selectedModels = [];
|
||||||
this.showStatus(`Install ${item.name} ...`);
|
|
||||||
btn.classList.add("cmm-btn-loading");
|
|
||||||
|
|
||||||
const data = item.originalData;
|
|
||||||
const res = await fetchData('/model/install', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify(data)
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
if (res.error) {
|
|
||||||
const errorMsg = `Install failed: ${item.name} ${res.error.message}`;
|
|
||||||
this.showError(errorMsg);
|
|
||||||
this.hideLoading();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
item.refresh = true;
|
this.selectedModels = selectedList;
|
||||||
this.grid.updateCell(item, "installed");
|
this.showSelection(`<span>Selected <b>${selectedList.length}</b> models <button class="cmm-btn-install" mode="install">Install</button>`);
|
||||||
|
}
|
||||||
|
|
||||||
|
focusInstall(item) {
|
||||||
|
const cellNode = this.grid.getCellNode(item, "installed");
|
||||||
|
if (cellNode) {
|
||||||
|
const cellBtn = cellNode.querySelector(`button[mode="install"]`);
|
||||||
|
if (cellBtn) {
|
||||||
|
cellBtn.classList.add("cmm-btn-loading");
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async installModels(list, btn) {
|
||||||
|
|
||||||
|
btn.classList.add("cmm-btn-loading");
|
||||||
|
this.showLoading();
|
||||||
|
this.showError("");
|
||||||
|
|
||||||
|
let needRestart = false;
|
||||||
|
let errorMsg = "";
|
||||||
|
|
||||||
|
for (const item of list) {
|
||||||
|
|
||||||
|
this.grid.scrollRowIntoView(item);
|
||||||
|
|
||||||
|
if (!this.focusInstall(item)) {
|
||||||
|
this.grid.onNextUpdated(() => {
|
||||||
|
this.focusInstall(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.showStatus(`Install ${item.name} ...`);
|
||||||
|
|
||||||
|
const data = item.originalData;
|
||||||
|
const res = await fetchData('/model/install', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (res.error) {
|
||||||
|
errorMsg = `Install failed: ${item.name} ${res.error.message}`;
|
||||||
|
break;;
|
||||||
|
}
|
||||||
|
|
||||||
|
needRestart = true;
|
||||||
|
|
||||||
|
this.grid.setRowSelected(item, false);
|
||||||
|
|
||||||
|
item.refresh = true;
|
||||||
|
item.selectable = false;
|
||||||
|
this.grid.updateCell(item, "installed");
|
||||||
|
this.grid.updateCell(item, "tg-column-select");
|
||||||
|
|
||||||
|
this.showStatus(`Install ${item.name} successfully`);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
this.hideLoading();
|
this.hideLoading();
|
||||||
|
btn.classList.remove("cmm-btn-loading");
|
||||||
|
|
||||||
this.showStatus(`Install ${item.name} successfully`);
|
if (errorMsg) {
|
||||||
this.showMessage(`To apply the installed model, please click the 'Refresh' button on the main menu.`, "red")
|
this.showError(errorMsg);
|
||||||
|
} else {
|
||||||
|
this.showStatus(`Install ${list.length} models successfully`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needRestart) {
|
||||||
|
this.showMessage(`To apply the installed model, please click the 'Refresh' button on the main menu.`, "red")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -572,11 +650,15 @@ export class ModelManager {
|
|||||||
const baseMap = new Map();
|
const baseMap = new Map();
|
||||||
|
|
||||||
models.forEach((item, i) => {
|
models.forEach((item, i) => {
|
||||||
const { type, base, name, reference } = item;
|
const { type, base, name, reference, installed } = item;
|
||||||
item.originalData = JSON.parse(JSON.stringify(item));
|
item.originalData = JSON.parse(JSON.stringify(item));
|
||||||
item.hash = md5(name + reference);
|
item.hash = md5(name + reference);
|
||||||
item.id = i + 1;
|
item.id = i + 1;
|
||||||
|
|
||||||
|
if (installed === "True") {
|
||||||
|
item.selectable = false;
|
||||||
|
}
|
||||||
|
|
||||||
typeMap.set(type, type);
|
typeMap.set(type, type);
|
||||||
baseMap.set(base, base);
|
baseMap.set(base, base);
|
||||||
|
|
||||||
@ -658,6 +740,10 @@ export class ModelManager {
|
|||||||
|
|
||||||
// ===========================================================================================
|
// ===========================================================================================
|
||||||
|
|
||||||
|
showSelection(msg) {
|
||||||
|
this.element.querySelector(".cmm-manager-selection").innerHTML = msg;
|
||||||
|
}
|
||||||
|
|
||||||
showError(err) {
|
showError(err) {
|
||||||
this.showMessage(err, "red");
|
this.showMessage(err, "red");
|
||||||
}
|
}
|
||||||
@ -701,7 +787,8 @@ export class ModelManager {
|
|||||||
const list = [
|
const list = [
|
||||||
".cmm-manager-header input",
|
".cmm-manager-header input",
|
||||||
".cmm-manager-header select",
|
".cmm-manager-header select",
|
||||||
".cmm-manager-footer button"
|
".cmm-manager-footer button",
|
||||||
|
".cmm-manager-selection button"
|
||||||
].map(s => {
|
].map(s => {
|
||||||
return Array.from(this.element.querySelectorAll(s));
|
return Array.from(this.element.querySelectorAll(s));
|
||||||
})
|
})
|
||||||
@ -732,6 +819,7 @@ export class ModelManager {
|
|||||||
show() {
|
show() {
|
||||||
this.element.style.display = "flex";
|
this.element.style.display = "flex";
|
||||||
this.setKeywords("");
|
this.setKeywords("");
|
||||||
|
this.showSelection("");
|
||||||
this.showMessage("");
|
this.showMessage("");
|
||||||
this.loadData();
|
this.loadData();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user