Layout and button changes
- In Model View, moved "Set as Preview" button below radio buttons and disabled when Default selected. - General CSS layout improvements.
This commit is contained in:
@@ -651,10 +651,14 @@ async def move_model(request):
|
||||
if new_path is None:
|
||||
return web.json_response({ "success": False })
|
||||
new_path, _ = search_path_to_system_path(new_path)
|
||||
if new_path is None:
|
||||
return web.json_response({ "success": False })
|
||||
if not os.path.isdir(new_path):
|
||||
return web.json_response({ "success": False })
|
||||
|
||||
new_file = os.path.join(new_path, filename)
|
||||
if old_file == new_file:
|
||||
return web.json_response({ "success": False })
|
||||
try:
|
||||
shutil.move(old_file, new_file)
|
||||
except ValueError as e:
|
||||
|
||||
@@ -366,6 +366,7 @@
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.model-manager .model-select-dropdown {
|
||||
@@ -403,9 +404,15 @@
|
||||
|
||||
.model-manager .search-dropdown > p {
|
||||
margin: 0;
|
||||
padding-left: 20px;
|
||||
padding-top: 0.85em;
|
||||
padding-bottom: 0.85em;
|
||||
padding: 0.85em 20px;
|
||||
min-width: 0;
|
||||
}
|
||||
.model-manager .search-dropdown > p {
|
||||
-ms-overflow-style: none; /* Internet Explorer 10+ */
|
||||
scrollbar-width: none; /* Firefox */
|
||||
}
|
||||
.model-manager .search-dropdown > p::-webkit-scrollbar {
|
||||
display: none; /* Safari and Chrome */
|
||||
}
|
||||
|
||||
.model-manager .search-dropdown > p.search-dropdown-selected {
|
||||
|
||||
@@ -721,7 +721,7 @@ class DirectoryDropdown {
|
||||
dropdown.append.apply(dropdown, innerHtml);
|
||||
// TODO: handle when dropdown is near the bottom of the window
|
||||
const inputRect = input.getBoundingClientRect();
|
||||
dropdown.style.minWidth = inputRect.width + "px";
|
||||
dropdown.style.width = inputRect.width + "px";
|
||||
dropdown.style.top = (input.offsetTop + inputRect.height) + "px";
|
||||
dropdown.style.left = input.offsetLeft + "px";
|
||||
dropdown.style.display = "block";
|
||||
@@ -1338,7 +1338,7 @@ function updateRadioPreview(previewImageContainer, step) {
|
||||
* @param {String[]} defaultPreviews
|
||||
* @returns {[]}
|
||||
*/
|
||||
function radioGroupImageSelect(uniqueName, defaultPreviews, defaultChanges=false) {
|
||||
function radioGroupImageSelect(uniqueName, defaultPreviews) {
|
||||
const defaultImageCount = defaultPreviews.length;
|
||||
|
||||
const el_defaultUri = $el("div", {
|
||||
@@ -1457,10 +1457,10 @@ function radioGroupImageSelect(uniqueName, defaultPreviews, defaultChanges=false
|
||||
el_previewButtons,
|
||||
]);
|
||||
|
||||
const PREVIEW_NONE = "No Preview";
|
||||
const PREVIEW_DEFAULT = "Default";
|
||||
const PREVIEW_URL = "URL";
|
||||
const PREVIEW_UPLOAD = "Upload";
|
||||
const PREVIEW_URL = "URL";
|
||||
const PREVIEW_NONE = "No Preview";
|
||||
|
||||
const el_radioButtons = $radioGroup({
|
||||
name: uniqueName,
|
||||
@@ -1476,36 +1476,48 @@ function radioGroupImageSelect(uniqueName, defaultPreviews, defaultChanges=false
|
||||
el_urlImage.style.display = "none";
|
||||
|
||||
switch (value) {
|
||||
case PREVIEW_NONE:
|
||||
default:
|
||||
el_noImage.style.display = "block";
|
||||
break;
|
||||
case PREVIEW_DEFAULT:
|
||||
el_defaultImages.style.display = "block";
|
||||
el_previewButtons.style.display = el_defaultImages.children.length > 1 ? "block" : "none";
|
||||
break;
|
||||
case PREVIEW_URL:
|
||||
el_custom.style.display = "flex";
|
||||
el_urlImage.style.display = "block";
|
||||
break;
|
||||
case PREVIEW_UPLOAD:
|
||||
el_upload.style.display = "flex";
|
||||
el_uploadImage.style.display = "block";
|
||||
break;
|
||||
case PREVIEW_URL:
|
||||
el_custom.style.display = "flex";
|
||||
el_urlImage.style.display = "block";
|
||||
break;
|
||||
case PREVIEW_NONE:
|
||||
default:
|
||||
el_noImage.style.display = "block";
|
||||
break;
|
||||
}
|
||||
},
|
||||
options: (() => {
|
||||
const radios = [];
|
||||
radios.push({ value: PREVIEW_NONE });
|
||||
if (defaultImageCount > 0) {
|
||||
radios.push({ value: PREVIEW_DEFAULT });
|
||||
}
|
||||
radios.push({ value: PREVIEW_URL });
|
||||
radios.push({ value: PREVIEW_UPLOAD })
|
||||
radios.push({ value: PREVIEW_URL });
|
||||
radios.push({ value: PREVIEW_NONE });
|
||||
return radios;
|
||||
})(),
|
||||
});
|
||||
|
||||
const defaultIsChecked = () => {
|
||||
const children = el_radioButtons.children;
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const child = children[i];
|
||||
const radioButton = child.children[0];
|
||||
if (radioButton.value === PREVIEW_DEFAULT) {
|
||||
return radioButton.checked;
|
||||
}
|
||||
};
|
||||
return false;
|
||||
}
|
||||
|
||||
if (defaultImageCount > 0) {
|
||||
const children = el_radioButtons.children;
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
@@ -1583,7 +1595,8 @@ function radioGroupImageSelect(uniqueName, defaultPreviews, defaultChanges=false
|
||||
]),
|
||||
]);
|
||||
|
||||
return [el_radioGroup, el_preview, getImage, el_defaultUri, resetModelInfoPreview];
|
||||
// TODO: make this an object?
|
||||
return [el_radioGroup, el_radioButtons, el_preview, getImage, el_defaultUri, resetModelInfoPreview, defaultIsChecked];
|
||||
}
|
||||
|
||||
class ModelManager extends ComfyDialog {
|
||||
@@ -1593,8 +1606,10 @@ class ModelManager extends ComfyDialog {
|
||||
/** @type {HTMLDivElement} */ modelInfoUrl: null,
|
||||
/** @type {HTMLDivElement} */ modelInfoOverwrite: null,
|
||||
/** @type {HTMLDivElement} */ modelInfos: null,
|
||||
modelInfoRadioGroup: null,
|
||||
modelInfoPreview: null,
|
||||
modelInfoDefaultUri: null,
|
||||
setAsPreviewButton: null,
|
||||
|
||||
/** @type {HTMLDivElement} */ modelGrid: null,
|
||||
/** @type {HTMLSelectElement} */ modelTypeSelect: null,
|
||||
@@ -1635,6 +1650,7 @@ class ModelManager extends ComfyDialog {
|
||||
#systemSeparator = null;
|
||||
|
||||
#resetModelInfoPreview = () => {};
|
||||
#modelInfoDefaultIsChecked = () => { return false; };
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -1657,7 +1673,7 @@ class ModelManager extends ComfyDialog {
|
||||
true,
|
||||
);
|
||||
|
||||
const [el_radioGroup, el_preview, getImage, el_defaultUri, resetModelInfoPreview] = radioGroupImageSelect(
|
||||
const [el_radioGroup, el_radioButtons, el_preview, getImage, el_defaultUri, resetModelInfoPreview, defaultIsChecked] = radioGroupImageSelect(
|
||||
"model-info-preview-model-FYUIKMNVB",
|
||||
[imageUri()],
|
||||
);
|
||||
@@ -1666,6 +1682,70 @@ class ModelManager extends ComfyDialog {
|
||||
this.#el.modelInfoPreview = el_preview;
|
||||
this.#el.modelInfoDefaultUri = el_defaultUri;
|
||||
this.#resetModelInfoPreview = resetModelInfoPreview;
|
||||
this.#modelInfoDefaultIsChecked = defaultIsChecked;
|
||||
|
||||
const setAsPreviewButton = $el("button", {
|
||||
$: (el) => (this.#el.setAsPreviewButton = el),
|
||||
textContent: "Set as Preview",
|
||||
onclick: async(e) => {
|
||||
const confirmation = window.confirm("Change preview image PERMANENTLY?");
|
||||
let updatedPreview = false;
|
||||
if (confirmation) {
|
||||
e.target.disabled = true;
|
||||
const container = this.#el.modelInfoContainer;
|
||||
const path = container.dataset.path;
|
||||
const imageUrl = getImage();
|
||||
if (imageUrl === imageUri()) {
|
||||
const encodedPath = encodeURIComponent(path);
|
||||
updatedPreview = await request(
|
||||
`/model-manager/preview/delete?path=${encodedPath}`,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify({}),
|
||||
}
|
||||
)
|
||||
.then((result) => {
|
||||
return result["success"];
|
||||
})
|
||||
.catch((err) => {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
else {
|
||||
const formData = new FormData();
|
||||
formData.append("path", path);
|
||||
const image = imageUrl[0] == "/" ? "" : imageUrl;
|
||||
formData.append("image", image);
|
||||
updatedPreview = await request(
|
||||
`/model-manager/preview/set`,
|
||||
{
|
||||
method: "POST",
|
||||
body: formData,
|
||||
}
|
||||
)
|
||||
.then((result) => {
|
||||
return result["success"];
|
||||
})
|
||||
.catch((err) => {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
if (updatedPreview) {
|
||||
this.#modelTab_updateModels();
|
||||
this.#el.modelInfoDefaultUri.dataset.noimage = imageUri();
|
||||
this.#resetModelInfoPreview();
|
||||
this.#el.modelInfoView.style.display = "none";
|
||||
}
|
||||
|
||||
e.target.disabled = false;
|
||||
}
|
||||
buttonAlert(e.target, updatedPreview);
|
||||
},
|
||||
});
|
||||
|
||||
el_radioButtons.addEventListener("change", (e) => {
|
||||
setAsPreviewButton.style.display = defaultIsChecked() ? "none" : "block";
|
||||
});
|
||||
|
||||
this.element = $el(
|
||||
"div.comfy-modal.model-manager",
|
||||
@@ -1678,51 +1758,44 @@ class ModelManager extends ComfyDialog {
|
||||
$: (el) => (this.#el.modelInfoView = el),
|
||||
style: { display: "none" },
|
||||
}, [
|
||||
$el("div", {
|
||||
style: {
|
||||
display: "flex",
|
||||
gap: "8px",
|
||||
},
|
||||
}, [
|
||||
$el("button.icon-button", {
|
||||
textContent: "🗑︎",
|
||||
onclick: async(e) => {
|
||||
const affirmation = "delete";
|
||||
const confirmation = window.prompt("Type \"" + affirmation + "\" to delete the model PERMANENTLY.\n\nThis includes all image or text files.");
|
||||
let deleted = false;
|
||||
if (confirmation === affirmation) {
|
||||
const container = this.#el.modelInfoContainer;
|
||||
const path = encodeURIComponent(container.dataset.path);
|
||||
deleted = await request(
|
||||
`/model-manager/model/delete?path=${path}`,
|
||||
{
|
||||
method: "POST",
|
||||
}
|
||||
)
|
||||
.then((result) => {
|
||||
const deleted = result["success"];
|
||||
if (deleted)
|
||||
{
|
||||
container.innerHTML = "";
|
||||
this.#el.modelInfoView.style.display = "none";
|
||||
this.#modelTab_updateModels();
|
||||
}
|
||||
return deleted;
|
||||
})
|
||||
.catch((err) => {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
if (!deleted) {
|
||||
buttonAlert(e.target, false);
|
||||
}
|
||||
},
|
||||
}),
|
||||
]),
|
||||
$el("div.row.tab-header", {
|
||||
display: "block",
|
||||
}, [
|
||||
$el("div.row.tab-header-flex-block", [
|
||||
$el("button.icon-button", {
|
||||
textContent: "🗑︎",
|
||||
onclick: async(e) => {
|
||||
const affirmation = "delete";
|
||||
const confirmation = window.prompt("Type \"" + affirmation + "\" to delete the model PERMANENTLY.\n\nThis includes all image or text files.");
|
||||
let deleted = false;
|
||||
if (confirmation === affirmation) {
|
||||
const container = this.#el.modelInfoContainer;
|
||||
const path = encodeURIComponent(container.dataset.path);
|
||||
deleted = await request(
|
||||
`/model-manager/model/delete?path=${path}`,
|
||||
{
|
||||
method: "POST",
|
||||
}
|
||||
)
|
||||
.then((result) => {
|
||||
const deleted = result["success"];
|
||||
if (deleted)
|
||||
{
|
||||
container.innerHTML = "";
|
||||
this.#el.modelInfoView.style.display = "none";
|
||||
this.#modelTab_updateModels();
|
||||
}
|
||||
return deleted;
|
||||
})
|
||||
.catch((err) => {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
if (!deleted) {
|
||||
buttonAlert(e.target, false);
|
||||
}
|
||||
},
|
||||
}),
|
||||
$el("div.search-models", [
|
||||
moveDestination,
|
||||
searchDropdown.element,
|
||||
@@ -1730,33 +1803,36 @@ class ModelManager extends ComfyDialog {
|
||||
$el("button", {
|
||||
textContent: "Move",
|
||||
onclick: async(e) => {
|
||||
const container = this.#el.modelInfoContainer;
|
||||
const moved = await request(
|
||||
`/model-manager/model/move`,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
"oldFile": container.dataset.path,
|
||||
"newDirectory": moveDestination.value,
|
||||
}),
|
||||
}
|
||||
)
|
||||
.then((result) => {
|
||||
const moved = result["success"];
|
||||
if (moved)
|
||||
{
|
||||
container.innerHTML = "";
|
||||
this.#el.modelInfoView.style.display = "none";
|
||||
this.#modelTab_updateModels();
|
||||
}
|
||||
return moved;
|
||||
})
|
||||
.catch(err => {
|
||||
return false;
|
||||
});
|
||||
if (!moved) {
|
||||
buttonAlert(e.target, false);
|
||||
const confirmation = window.confirm("Move this file?");
|
||||
let moved = false;
|
||||
if (confirmation) {
|
||||
const container = this.#el.modelInfoContainer;
|
||||
moved = await request(
|
||||
`/model-manager/model/move`,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
"oldFile": container.dataset.path,
|
||||
"newDirectory": moveDestination.value,
|
||||
}),
|
||||
}
|
||||
)
|
||||
.then((result) => {
|
||||
const moved = result["success"];
|
||||
if (moved)
|
||||
{
|
||||
moveDestination.value = "";
|
||||
container.innerHTML = "";
|
||||
this.#el.modelInfoView.style.display = "none";
|
||||
this.#modelTab_updateModels();
|
||||
}
|
||||
return moved;
|
||||
})
|
||||
.catch(err => {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
buttonAlert(e.target, moved);
|
||||
},
|
||||
}),
|
||||
]),
|
||||
@@ -1960,73 +2036,23 @@ class ModelManager extends ComfyDialog {
|
||||
const imagePath = info["Preview"]["path"];
|
||||
const imageDateModified = info["Preview"]["dateModified"];
|
||||
this.#el.modelInfoDefaultUri.dataset.noimage = imageUri(imagePath, imageDateModified);
|
||||
this.#resetModelInfoPreview();
|
||||
}
|
||||
else {
|
||||
this.#el.modelInfoDefaultUri.dataset.noimage = imageUri();
|
||||
}
|
||||
this.#resetModelInfoPreview();
|
||||
|
||||
const setAsPreviewButton = this.#el.setAsPreviewButton;
|
||||
setAsPreviewButton.style.display = this.#modelInfoDefaultIsChecked() ? "none" : "block";
|
||||
|
||||
innerHtml.push($el("div", [
|
||||
this.#el.modelInfoPreview,
|
||||
$el("div.row.tab-header", [
|
||||
$el("div.row.tab-header-flex-block", [
|
||||
$el("button", {
|
||||
textContent: "Set as Preview",
|
||||
onclick: async(e) => {
|
||||
const confirmation = window.confirm("Change preview image PERMANENTLY?");
|
||||
let updatedPreview = false;
|
||||
if (confirmation) {
|
||||
e.target.disabled = true;
|
||||
const container = this.#el.modelInfoContainer;
|
||||
const path = container.dataset.path;
|
||||
const imageUrl = getImage();
|
||||
if (imageUrl === imageUri()) {
|
||||
const encodedPath = encodeURIComponent(path);
|
||||
updatedPreview = await request(
|
||||
`/model-manager/preview/delete?path=${encodedPath}`,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify({}),
|
||||
}
|
||||
)
|
||||
.then((result) => {
|
||||
return result["success"];
|
||||
})
|
||||
.catch((err) => {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
else {
|
||||
const formData = new FormData();
|
||||
formData.append("path", path);
|
||||
const image = imageUrl[0] == "/" ? "" : imageUrl;
|
||||
formData.append("image", image);
|
||||
updatedPreview = await request(
|
||||
`/model-manager/preview/set`,
|
||||
{
|
||||
method: "POST",
|
||||
body: formData,
|
||||
}
|
||||
)
|
||||
.then((result) => {
|
||||
return result["success"];
|
||||
})
|
||||
.catch((err) => {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
if (updatedPreview) {
|
||||
this.#modelTab_updateModels();
|
||||
this.#el.modelInfoDefaultUri.dataset.noimage = imageUri();
|
||||
this.#resetModelInfoPreview();
|
||||
this.#el.modelInfoView.style.display = "none";
|
||||
}
|
||||
|
||||
e.target.disabled = false;
|
||||
}
|
||||
buttonAlert(e.target, updatedPreview);
|
||||
},
|
||||
}),
|
||||
this.#el.modelInfoRadioGroup,
|
||||
]),
|
||||
$el("div.row.tab-header-flex-block", [
|
||||
this.#el.modelInfoRadioGroup,
|
||||
setAsPreviewButton,
|
||||
]),
|
||||
]),
|
||||
$el("div",
|
||||
@@ -2314,7 +2340,7 @@ class ModelManager extends ComfyDialog {
|
||||
* @returns {HTMLDivElement}
|
||||
*/
|
||||
#downloadTab_modelInfo(info, modelTypes, modelDirectories, searchSeparator, id) {
|
||||
const [el_radioGroup, el_preview, getImage, el_defaultUri, resetModelInfoPreview] = radioGroupImageSelect(
|
||||
const [el_radioGroup, el_radioButtons, el_preview, getImage, el_defaultUri, resetModelInfoPreview, defaultIsChecked] = radioGroupImageSelect(
|
||||
"model-download-info-preview-model" + "-" + id,
|
||||
info["images"],
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user