281c04dd2e
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
192 lines
7.9 KiB
JavaScript
192 lines
7.9 KiB
JavaScript
import { app } from "../../scripts/app.js";
|
|
import { api } from "../../scripts/api.js";
|
|
|
|
app.registerExtension({
|
|
name: "json.manager.project.resolution",
|
|
|
|
async beforeQueuePrompt() {
|
|
if (!app.graph?._nodes) return;
|
|
for (const node of app.graph._nodes) {
|
|
if (node.type === "ProjectResolution" && node._syncFromSource) {
|
|
node._syncFromSource();
|
|
}
|
|
}
|
|
},
|
|
|
|
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
|
if (nodeData.name !== "ProjectResolution") return;
|
|
|
|
function hideWidget(widget) {
|
|
if (widget.origType === undefined) widget.origType = widget.type;
|
|
widget.type = "hidden";
|
|
widget.hidden = true;
|
|
widget.computeSize = () => [0, -4];
|
|
}
|
|
|
|
function replaceWithCombo(node, name, values, callback) {
|
|
const idx = node.widgets?.findIndex(w => w.name === name);
|
|
if (idx === -1 || idx === undefined) return null;
|
|
const oldWidget = node.widgets[idx];
|
|
const savedValue = oldWidget.value || "";
|
|
const comboValues = values.length > 0 ? values : [""];
|
|
if (savedValue && !comboValues.includes(savedValue)) {
|
|
comboValues.unshift(savedValue);
|
|
}
|
|
const defaultValue = savedValue || comboValues[0];
|
|
node.widgets.splice(idx, 1);
|
|
const combo = node.addWidget("combo", name, defaultValue, callback, { values: comboValues });
|
|
if (node.widgets.length > 1) {
|
|
node.widgets.splice(node.widgets.length - 1, 1);
|
|
node.widgets.splice(idx, 0, combo);
|
|
}
|
|
return combo;
|
|
}
|
|
|
|
const origOnNodeCreated = nodeType.prototype.onNodeCreated;
|
|
nodeType.prototype.onNodeCreated = function () {
|
|
origOnNodeCreated?.apply(this, arguments);
|
|
this._configured = false;
|
|
|
|
// Hide synced config widgets — index stays visible, user wires it from loop node
|
|
for (const name of ["manager_url", "project_name", "file_name", "sequence_number"]) {
|
|
const w = this.widgets?.find(w => w.name === name);
|
|
if (w) hideWidget(w);
|
|
}
|
|
|
|
const node = this;
|
|
const sourceLabels = this._getSourceLabels?.() || [];
|
|
const srcCombo = replaceWithCombo(this, "source_label", sourceLabels, function (value) {
|
|
node._syncFromSource();
|
|
node._refreshKeys();
|
|
});
|
|
if (srcCombo) srcCombo.value = sourceLabels[0] || "";
|
|
|
|
const keyCombo = replaceWithCombo(this, "key_name", [], function (value) {
|
|
node.title = value ? `Resolution: ${value}` : "Project Resolution";
|
|
app.graph?.setDirtyCanvas(true, true);
|
|
});
|
|
if (keyCombo) keyCombo.value = "";
|
|
|
|
queueMicrotask(() => {
|
|
if (!this._configured) {
|
|
this.setSize(this.computeSize());
|
|
}
|
|
});
|
|
};
|
|
|
|
nodeType.prototype._getSourceLabels = function () {
|
|
const seen = new Set();
|
|
const labels = [];
|
|
if (!this.graph) return labels;
|
|
for (const node of this.graph._nodes) {
|
|
if (node.type === "ProjectSource") {
|
|
const lw = node.widgets?.find(w => w.name === "label");
|
|
if (lw?.value && !seen.has(lw.value)) {
|
|
seen.add(lw.value);
|
|
labels.push(lw.value);
|
|
}
|
|
}
|
|
}
|
|
return labels;
|
|
};
|
|
|
|
nodeType.prototype._findSource = function (label) {
|
|
if (!this.graph || !label) return null;
|
|
for (const node of this.graph._nodes) {
|
|
if (node.type === "ProjectSource") {
|
|
const lw = node.widgets?.find(w => w.name === "label");
|
|
if (lw?.value === label) return node;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
nodeType.prototype._syncFromSource = function () {
|
|
const srcWidget = this.widgets?.find(w => w.name === "source_label");
|
|
const source = this._findSource(srcWidget?.value);
|
|
if (!source) return;
|
|
for (const name of ["manager_url", "project_name", "file_name", "sequence_number"]) {
|
|
const dst = this.widgets?.find(w => w.name === name);
|
|
const src = source.widgets?.find(w => w.name === name);
|
|
if (dst && src) dst.value = src.value;
|
|
}
|
|
};
|
|
|
|
nodeType.prototype._refreshKeys = async function () {
|
|
const urlW = this.widgets?.find(w => w.name === "manager_url");
|
|
const projW = this.widgets?.find(w => w.name === "project_name");
|
|
const fileW = this.widgets?.find(w => w.name === "file_name");
|
|
const seqW = this.widgets?.find(w => w.name === "sequence_number");
|
|
if (!urlW?.value || !projW?.value || !fileW?.value) return;
|
|
|
|
try {
|
|
const resp = await api.fetchApi(
|
|
`/json_manager/get_project_keys?url=${encodeURIComponent(urlW.value)}&project=${encodeURIComponent(projW.value)}&file=${encodeURIComponent(fileW.value)}&seq=${seqW?.value || 1}`
|
|
);
|
|
if (!resp.ok) return;
|
|
const data = await resp.json();
|
|
if (data.error || !Array.isArray(data.keys)) return;
|
|
|
|
const keyWidget = this.widgets?.find(w => w.name === "key_name");
|
|
if (keyWidget) {
|
|
keyWidget.options.values = data.keys.length > 0 ? data.keys : [""];
|
|
}
|
|
} catch (e) {
|
|
console.error("[ProjectResolution] Failed to refresh keys:", e);
|
|
}
|
|
};
|
|
|
|
const origOnMouseDown = nodeType.prototype.onMouseDown;
|
|
nodeType.prototype.onMouseDown = function (e, localPos, graphCanvas) {
|
|
origOnMouseDown?.apply(this, arguments);
|
|
const srcWidget = this.widgets?.find(w => w.name === "source_label");
|
|
if (srcWidget) srcWidget.options.values = this._getSourceLabels();
|
|
this._syncFromSource();
|
|
};
|
|
|
|
const origOnConfigure = nodeType.prototype.onConfigure;
|
|
nodeType.prototype.onConfigure = function (info) {
|
|
origOnConfigure?.apply(this, arguments);
|
|
this._configured = true;
|
|
|
|
for (const name of ["manager_url", "project_name", "file_name", "sequence_number"]) {
|
|
const w = this.widgets?.find(w => w.name === name);
|
|
if (w) hideWidget(w);
|
|
}
|
|
|
|
const srcWidget = this.widgets?.find(w => w.name === "source_label");
|
|
if (srcWidget && srcWidget.type !== "combo") {
|
|
const node = this;
|
|
replaceWithCombo(this, "source_label", this._getSourceLabels(), function (value) {
|
|
node._syncFromSource();
|
|
node._refreshKeys();
|
|
});
|
|
} else if (srcWidget) {
|
|
srcWidget.options.values = this._getSourceLabels();
|
|
}
|
|
|
|
const keyWidget = this.widgets?.find(w => w.name === "key_name");
|
|
if (keyWidget && keyWidget.type !== "combo") {
|
|
const node = this;
|
|
replaceWithCombo(this, "key_name", [], function (value) {
|
|
node.title = value ? `Resolution: ${value}` : "Project Resolution";
|
|
app.graph?.setDirtyCanvas(true, true);
|
|
});
|
|
}
|
|
|
|
const finalKeyWidget = this.widgets?.find(w => w.name === "key_name");
|
|
if (finalKeyWidget?.value) {
|
|
this.title = `Resolution: ${finalKeyWidget.value}`;
|
|
}
|
|
|
|
this.setSize(this.computeSize());
|
|
|
|
const node = this;
|
|
queueMicrotask(() => {
|
|
node._syncFromSource();
|
|
node._refreshKeys();
|
|
});
|
|
};
|
|
},
|
|
});
|