97 lines
3.2 KiB
JavaScript
97 lines
3.2 KiB
JavaScript
import { app } from "../../scripts/app.js";
|
|
|
|
// This is the "correct" way to add frontend logic
|
|
app.registerExtension({
|
|
name: "Rathius.TextUploader", // Unique name for our extension
|
|
|
|
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
|
// This runs for every node *before* it's added
|
|
|
|
// Check if this is our node by its Python class name
|
|
if (nodeData.name === "LoadTextFile_Rathius") {
|
|
|
|
// This function will be called *after* the node is created on the canvas
|
|
const onNodeCreated = nodeType.prototype.onNodeCreated;
|
|
nodeType.prototype.onNodeCreated = function () {
|
|
onNodeCreated?.apply(this, arguments);
|
|
|
|
// Find the default "file_name" widget we created in Python
|
|
const widget = this.widgets.find((w) => w.name === "file_name");
|
|
|
|
// Create the "Choose File" button
|
|
const fileInput = document.createElement("input");
|
|
fileInput.type = "file";
|
|
fileInput.accept = "text/plain,.txt";
|
|
fileInput.style.display = "none";
|
|
|
|
// Create the button widget
|
|
const uploadButton = this.addWidget("button", "Choose .txt File", "None", () => {
|
|
fileInput.click(); // Open the file picker when clicked
|
|
});
|
|
uploadButton.serialize = false; // Don't save this button's value in workflows
|
|
|
|
// Handle what happens when a file is selected
|
|
fileInput.addEventListener("change", (event) => {
|
|
if (fileInput.files.length) {
|
|
uploadFile(fileInput.files[0]);
|
|
}
|
|
});
|
|
|
|
// Create the upload function
|
|
const uploadFile = async (file) => {
|
|
const body = new FormData();
|
|
|
|
// 'input' is the default folder, but we can specify a subfolder
|
|
body.append("subfolder", "text_prompts");
|
|
body.append("overwrite", "true"); // Overwrite existing files
|
|
// The server's /upload/image endpoint handles *any* file
|
|
body.append("image", file, file.name);
|
|
|
|
uploadButton.name = "Uploading...";
|
|
|
|
try {
|
|
// Send the file to the server
|
|
const response = await fetch("/upload/image", {
|
|
method: "POST",
|
|
body: body,
|
|
});
|
|
|
|
if (response.status === 200) {
|
|
const data = await response.json();
|
|
// Set the value of the *original* (hidden) widget
|
|
// This is what Python will receive
|
|
let filePath = data.name;
|
|
if (data.subfolder) {
|
|
filePath = data.subfolder + "/" + filePath;
|
|
}
|
|
|
|
filePath = filePath.replace(/\\/g, "/"); // e.g., "text_prompts/my_prompt.txt"
|
|
widget.value = filePath;
|
|
|
|
// Truncate for display if too long
|
|
let displayName = filePath;
|
|
if (displayName.length > 30) {
|
|
displayName = displayName.substring(0, 20) + "..." + displayName.substring(displayName.length - 10);
|
|
}
|
|
|
|
uploadButton.name = `Loaded: ${displayName}`;
|
|
} else {
|
|
alert(response.status + " - " + response.statusText);
|
|
uploadButton.name = "Choose .txt File";
|
|
}
|
|
} catch (error) {
|
|
alert(error);
|
|
uploadButton.name = "Choose .txt File";
|
|
}
|
|
};
|
|
|
|
// Add the hidden file input to the document
|
|
document.body.appendChild(fileInput);
|
|
|
|
// Hide the original string widget
|
|
widget.type = "hidden"; // We don't want to see the text box
|
|
widget.serialize = true; // We *do* want to save its value
|
|
};
|
|
}
|
|
},
|
|
}); |