n8n-editor-ui
Version:
Workflow Editor UI for n8n
495 lines (494 loc) • 22.5 kB
JavaScript
import { o as __toESM } from "./chunk-6z4oVpB-.js";
import { C as computed, Cn as toDisplayString, D as createElementBlock, E as createCommentVNode, Gt as unref, It as ref, M as createVNode, P as defineComponent, T as createBlock, _ as Fragment, _t as watch, bt as withCtx, et as openBlock, h as withModifiers, it as renderList, j as createTextVNode, q as onBeforeMount, vn as normalizeClass, w as createBaseVNode, y as Suspense } from "./vue.runtime.esm-bundler-tP5dCd7J.js";
import { _t as useI18n } from "./_MapCache-ficiegRb.js";
import { $ as N8nInputLabel_default, J as N8nSelect_default, Sn as N8nButton_default, Y as N8nOption_default, wn as N8nIcon_default, xn as N8nText_default, xt as N8nIconButton_default } from "./src-DgvumQTi.js";
import "./en-CF30SCh2.js";
import "./preload-helper-CR0ecmWK.js";
import { t as __plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BwBpWJRZ.js";
import { r as require_get } from "./truncate-B1HVeveJ.js";
import "./date-picker-B6nJ4qMb.js";
import { A as telemetry, Gn as useNodeHelpers, M as useNDVStore, N as useWorkflowsStore } from "./builder.store-sBTWwxRU.js";
import { r as require_vuedraggable_umd, t as ParameterInputList_default } from "./ParameterInputList-B4xJHjua.js";
import "./empty-BuGRxzl4.js";
import "./dialog-D5O6wJX0.js";
import "./sanitize-html-Cc45ZKm8.js";
import "./CalendarDate-zWqgZMlk.js";
import "./path-browserify-BtCDmZ3_.js";
import { ga as isINodePropertyCollectionList, ho as require_isEqual, wa as deepCopy } from "./constants-BbpucWL4.js";
import "./merge-k8vSyyXH.js";
import { A as storeToRefs } from "./_baseOrderBy-B_6CV8x6.js";
import "./dateformat-CM9k0--B.js";
import "./useDebounce-Bnb8W2LR.js";
import "./assistant.store-bS9AHOoo.js";
import "./chatPanel.store-4qGv1TCZ.js";
import "./retry-dP46utx2.js";
import "./executions.store-CXjGPxs0.js";
import "./useRunWorkflow-BQJbxiOd.js";
import "./usePinnedData-CL2qWhwp.js";
import "./nodeCreator.store-FJrC_Pu6.js";
import "./nodeIcon-DI2Acud1.js";
import "./useCanvasOperations-CAHezq7d.js";
import "./folders.store-BjAwtSH4.js";
import "./NodeIcon-BVhrZNYI.js";
import "./useClipboard-CyG-SBdG.js";
import "./RunData-B4jIonVZ.js";
import "./NDVEmptyState-CpUQ-969.js";
import "./exports-hpMZaOPT.js";
import "./externalSecrets.ee.store-D27nc9Y2.js";
import "./uniqBy-BwIeMDu6.js";
import "./RunDataHtml-CkjC7YuF.js";
import "./VueMarkdown-D9lDzMKr.js";
import "./Draggable-04Tfmp_H.js";
import "./VirtualSchema-D2LnRq9K.js";
import "./TextWithHighlights-DjzuDrgO.js";
import "./useTelemetryContext-5Wb7vBCv.js";
import "./schemaPreview.store-BFprwUEe.js";
import "./nodeTransforms-Lk_uXh7p.js";
import "./vue-json-pretty-DGKuDe33.js";
import "./dateFormatter-DDfPHI9I.js";
import "./useExecutionHelpers-BhJEW8lu.js";
import "./vue-Dg_43WEg.js";
var import_get = /* @__PURE__ */ __toESM(require_get());
var import_isEqual = /* @__PURE__ */ __toESM(require_isEqual());
var import_vuedraggable_umd = /* @__PURE__ */ __toESM(require_vuedraggable_umd());
var _hoisted_1 = ["data-test-id"];
var _hoisted_2 = {
key: 0,
class: "no-items-exist"
};
var _hoisted_3 = { key: 1 };
var _hoisted_4 = {
key: 0,
class: "icon-button default-top-padding"
};
var _hoisted_5 = {
key: 1,
class: "icon-button extra-top-padding"
};
var _hoisted_6 = {
key: 2,
class: "optional-values-picker add-option",
"data-test-id": "fixed-collection-add-property"
};
var _hoisted_7 = { class: "optional-value-item" };
var _hoisted_8 = {
key: 2,
class: "parameter-item"
};
var _hoisted_9 = { class: "parameter-item-wrapper" };
var _hoisted_10 = {
key: 0,
class: "icon-button"
};
var _hoisted_11 = {
key: 1,
class: "optional-values-picker add-option",
"data-test-id": "fixed-collection-add-property"
};
var _hoisted_12 = { class: "optional-value-item" };
var _hoisted_13 = {
key: 1,
class: "controls"
};
var _hoisted_14 = {
key: 1,
class: "add-option"
};
var FixedCollectionParameter_default = /* @__PURE__ */ __plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
__name: "FixedCollectionParameter",
props: {
nodeValues: {},
parameter: {},
path: {},
values: { default: () => ({}) },
isReadOnly: {
type: Boolean,
default: false
},
hiddenIssuesInputs: { default: () => [] }
},
emits: ["valueChanged"],
setup(__props, { emit: __emit }) {
const locale = useI18n();
const nodeHelpers = useNodeHelpers();
const props = __props;
const emit = __emit;
const workflowsStore = useWorkflowsStore();
const ndvStore = useNDVStore();
const { activeNode } = storeToRefs(ndvStore);
const getPlaceholderText = computed(() => {
const placeholder = locale.nodeText(activeNode.value?.type).placeholder(props.parameter, props.path);
return placeholder ? placeholder : locale.baseText("fixedCollectionParameter.choose");
});
const mutableValues = ref({});
const selectedOption = ref(null);
const propertyNames = computed(() => {
return new Set(Object.keys(mutableValues.value || {}));
});
const getProperties = computed(() => {
const returnProperties = [];
let tempProperties;
for (const name of propertyNames.value) {
tempProperties = getOptionProperties(name);
if (tempProperties !== void 0) returnProperties.push(tempProperties);
}
return returnProperties;
});
const multipleValues = computed(() => {
return !!props.parameter.typeOptions?.multipleValues;
});
const addedOptionalValues = ref(/* @__PURE__ */ new Map());
const parameterOptions = computed(() => {
if (!isINodePropertyCollectionList(props.parameter.options)) return [];
if (multipleValues.value) return props.parameter.options;
return (props.parameter.options ?? []).filter((option) => {
return !propertyNames.value.has(option.name);
});
});
const sortable = computed(() => {
return !!props.parameter.typeOptions?.sortable;
});
const hideOptionalFields = computed(() => {
return !!props.parameter.typeOptions?.hideOptionalFields;
});
const addOptionalFieldButtonText = computed(() => {
if (!props.parameter.typeOptions?.addOptionalFieldButtonText) return locale.baseText("fixedCollectionParameter.addField");
return locale.nodeText(activeNode.value?.type).addOptionalFieldButtonText(props.parameter);
});
const getOptionalValuesKey = (propertyName, index) => {
return index !== void 0 ? `${propertyName}-${index}` : propertyName;
};
const hasNonDefaultValue = (propertyDef, itemValues) => {
if (!itemValues) return false;
const value = itemValues[propertyDef.name];
if (value === void 0 || value === null) return false;
if (typeof value === "string" && value === "") return false;
if (typeof value === "object") return !(0, import_isEqual.default)(value, propertyDef.default);
return value !== propertyDef.default;
};
const initializeAddedOptionalValues = () => {
if (!hideOptionalFields.value) return;
if (!isINodePropertyCollectionList(props.parameter.options)) return;
addedOptionalValues.value.clear();
for (const property of props.parameter.options) {
const propertyPath = `${props.path}.${property.name}`;
const propertyValues = (0, import_get.default)(props.nodeValues, propertyPath);
if (!propertyValues) continue;
const optionalValueDefs = property.values.filter((v) => v.required !== true && v.type !== "notice");
if (multipleValues.value && Array.isArray(propertyValues)) propertyValues.forEach((itemValues, index) => {
const key = getOptionalValuesKey(property.name, index);
const addedValues = /* @__PURE__ */ new Set();
for (const valueDef of optionalValueDefs) if (hasNonDefaultValue(valueDef, itemValues)) addedValues.add(valueDef.name);
if (addedValues.size > 0) addedOptionalValues.value.set(key, addedValues);
});
else if (typeof propertyValues === "object" && !Array.isArray(propertyValues)) {
const key = getOptionalValuesKey(property.name);
const addedValues = /* @__PURE__ */ new Set();
for (const valueDef of optionalValueDefs) if (hasNonDefaultValue(valueDef, propertyValues)) addedValues.add(valueDef.name);
if (addedValues.size > 0) addedOptionalValues.value.set(key, addedValues);
}
}
};
const isOptionalValueAdded = (propertyName, valueName, index) => {
const key = getOptionalValuesKey(propertyName, index);
return addedOptionalValues.value.get(key)?.has(valueName) ?? false;
};
const getVisiblePropertyValues = (property, index) => {
if (!hideOptionalFields.value) return property.values;
const key = getOptionalValuesKey(property.name, index);
const addedValues = addedOptionalValues.value.get(key);
return property.values.filter((value) => {
if (value.required === true) return true;
if (value.type === "notice") return true;
if (addedValues?.has(value.name)) return true;
if (value.typeOptions?.showEvenWhenOptional) return true;
return false;
});
};
const getPickerPropertyValues = (property, index) => {
if (!hideOptionalFields.value) return [];
const itemPath = getPropertyPath(property.name, index);
return property.values.filter((value) => {
if (value.required === true) return false;
if (value.type === "notice") return false;
if (value.typeOptions?.showEvenWhenOptional) return false;
return nodeHelpers.displayParameter(props.nodeValues, value, itemPath, activeNode.value);
});
};
const toggleOptionalValue = (property, valueName, index) => {
const key = getOptionalValuesKey(property.name, index);
let valueSet = addedOptionalValues.value.get(key);
if (!valueSet) {
valueSet = /* @__PURE__ */ new Set();
addedOptionalValues.value.set(key, valueSet);
}
const valueDef = property.values.find((v) => v.name === valueName);
if (!valueDef) return;
const isCurrentlyAdded = valueSet.has(valueName);
if (isCurrentlyAdded) valueSet.delete(valueName);
else valueSet.add(valueName);
addedOptionalValues.value.set(key, valueSet);
emit("valueChanged", {
name: getPropertyPath(property.name, index) + `.${valueName}`,
value: isCurrentlyAdded ? void 0 : deepCopy(valueDef.default)
});
};
watch(() => props.values, (newValues) => {
mutableValues.value = deepCopy(newValues);
}, { deep: true });
onBeforeMount(() => {
mutableValues.value = deepCopy(props.values);
initializeAddedOptionalValues();
});
const deleteOption = (optionName, index) => {
const currentOptionsOfSameType = mutableValues.value[optionName];
if (!currentOptionsOfSameType || currentOptionsOfSameType.length > 1) emit("valueChanged", {
name: getPropertyPath(optionName, index),
value: void 0
});
else emit("valueChanged", {
name: getPropertyPath(optionName),
value: void 0
});
};
const getPropertyPath = (name, index) => {
return `${props.path}.${name}` + (index !== void 0 ? `[${index}]` : "");
};
const getOptionProperties = (optionName) => {
if (isINodePropertyCollectionList(props.parameter.options)) {
for (const option of props.parameter.options) if (option.name === optionName) return option;
}
};
const onAddButtonClick = (optionName) => {
optionSelected(optionName);
if (props.parameter.name === "workflowInputs") trackWorkflowInputFieldAdded();
};
const optionSelected = (optionName) => {
const option = getOptionProperties(optionName);
if (option === void 0) return;
const name = `${props.path}.${option.name}`;
const newParameterValue = {};
for (const optionParameter of option.values) if (optionParameter.type === "fixedCollection" && optionParameter.typeOptions !== void 0 && optionParameter.typeOptions.multipleValues === true) newParameterValue[optionParameter.name] = {};
else if (optionParameter.typeOptions !== void 0 && optionParameter.typeOptions.multipleValues === true) {
const multiValue = (0, import_get.default)(props.nodeValues, [props.path, optionParameter.name], []);
if (Array.isArray(optionParameter.default)) multiValue.push(...deepCopy(optionParameter.default));
else if (optionParameter.default !== "" && typeof optionParameter.default !== "object") multiValue.push(deepCopy(optionParameter.default));
newParameterValue[optionParameter.name] = multiValue;
} else newParameterValue[optionParameter.name] = deepCopy(optionParameter.default);
let newValue;
if (multipleValues.value) {
newValue = (0, import_get.default)(props.nodeValues, name, []);
newValue.push(newParameterValue);
} else newValue = newParameterValue;
emit("valueChanged", {
name,
value: newValue
});
selectedOption.value = void 0;
};
const valueChanged = (parameterData) => {
emit("valueChanged", parameterData);
if (props.parameter.name === "workflowInputs") trackWorkflowInputFieldTypeChange(parameterData);
};
const onDragChange = (optionName) => {
emit("valueChanged", {
name: getPropertyPath(optionName),
value: mutableValues.value[optionName],
type: "optionsOrderChanged"
});
};
const trackWorkflowInputFieldTypeChange = (parameterData) => {
telemetry.track("User changed workflow input field type", {
type: parameterData.value,
workflow_id: workflowsStore.workflow.id,
node_id: ndvStore.activeNode?.id
});
};
const trackWorkflowInputFieldAdded = () => {
telemetry.track("User added workflow input field", {
workflow_id: workflowsStore.workflow.id,
node_id: ndvStore.activeNode?.id
});
};
function getItemKey(item, property) {
return mutableValues.value[property.name]?.indexOf(item) ?? -1;
}
return (_ctx, _cache) => {
return openBlock(), createElementBlock("div", {
class: "fixed-collection-parameter",
"data-test-id": `fixed-collection-${props.parameter?.name}`,
onKeydown: _cache[2] || (_cache[2] = withModifiers(() => {}, ["stop"]))
}, [
getProperties.value.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_2, [createVNode(unref(N8nText_default), { size: "small" }, {
default: withCtx(() => [createTextVNode(toDisplayString(unref(locale).baseText("fixedCollectionParameter.currentlyNoItemsExist")), 1)]),
_: 1
})])) : createCommentVNode("", true),
(openBlock(true), createElementBlock(Fragment, null, renderList(getProperties.value, (property) => {
return openBlock(), createElementBlock("div", {
key: property.name,
class: "fixed-collection-parameter-property"
}, [property.displayName !== "" && _ctx.parameter.options && _ctx.parameter.options.length !== 1 ? (openBlock(), createBlock(unref(N8nInputLabel_default), {
key: 0,
label: unref(locale).nodeText(unref(activeNode)?.type).inputLabelDisplayName(property, _ctx.path),
underline: true,
size: "small",
color: "text-dark"
}, null, 8, ["label"])) : createCommentVNode("", true), multipleValues.value ? (openBlock(), createElementBlock("div", _hoisted_3, [createVNode(unref(import_vuedraggable_umd.default), {
modelValue: mutableValues.value[property.name],
"onUpdate:modelValue": ($event) => mutableValues.value[property.name] = $event,
"item-key": (item) => getItemKey(item, property),
handle: ".drag-handle",
"drag-class": "dragging",
"ghost-class": "ghost",
"chosen-class": "chosen",
onChange: ($event) => onDragChange(property.name)
}, {
item: withCtx(({ index }) => [(openBlock(), createElementBlock("div", {
key: property.name + "-" + index,
class: "parameter-item"
}, [createBaseVNode("div", { class: normalizeClass(index ? "border-top-dashed parameter-item-wrapper " : "parameter-item-wrapper") }, [
!_ctx.isReadOnly ? (openBlock(), createElementBlock("div", _hoisted_4, [sortable.value ? (openBlock(), createBlock(unref(N8nIconButton_default), {
key: 0,
type: "tertiary",
text: "",
size: "small",
icon: "grip-vertical",
title: unref(locale).baseText("fixedCollectionParameter.dragItem"),
class: "drag-handle"
}, null, 8, ["title"])) : createCommentVNode("", true)])) : createCommentVNode("", true),
!_ctx.isReadOnly ? (openBlock(), createElementBlock("div", _hoisted_5, [createVNode(unref(N8nIconButton_default), {
type: "tertiary",
text: "",
size: "small",
icon: "trash-2",
"data-test-id": "fixed-collection-delete",
title: unref(locale).baseText("fixedCollectionParameter.deleteItem"),
onClick: ($event) => deleteOption(property.name, index)
}, null, 8, ["title", "onClick"])])) : createCommentVNode("", true),
(openBlock(), createBlock(Suspense, null, {
default: withCtx(() => [createVNode(ParameterInputList_default, {
parameters: getVisiblePropertyValues(property, index),
"node-values": _ctx.nodeValues,
path: getPropertyPath(property.name, index),
"hide-delete": true,
"is-read-only": _ctx.isReadOnly,
"hidden-issues-inputs": _ctx.hiddenIssuesInputs,
onValueChanged: valueChanged
}, null, 8, [
"parameters",
"node-values",
"path",
"is-read-only",
"hidden-issues-inputs"
])]),
_: 2
}, 1024)),
getPickerPropertyValues(property, index).length > 0 && !_ctx.isReadOnly ? (openBlock(), createElementBlock("div", _hoisted_6, [createVNode(unref(N8nSelect_default), {
placeholder: addOptionalFieldButtonText.value,
size: "small",
filterable: "",
"model-value": null,
"onUpdate:modelValue": (valueName) => toggleOptionalValue(property, valueName, index)
}, {
default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(getPickerPropertyValues(property, index), (value) => {
return openBlock(), createBlock(unref(N8nOption_default), {
key: value.name,
label: value.displayName || value.name,
value: value.name
}, {
default: withCtx(() => [createBaseVNode("div", _hoisted_7, [createBaseVNode("span", null, toDisplayString(value.displayName || value.name), 1), isOptionalValueAdded(property.name, value.name, index) ? (openBlock(), createBlock(unref(N8nIcon_default), {
key: 0,
icon: "check",
size: "medium"
})) : createCommentVNode("", true)])]),
_: 2
}, 1032, ["label", "value"]);
}), 128))]),
_: 2
}, 1032, ["placeholder", "onUpdate:modelValue"])])) : createCommentVNode("", true)
], 2)]))]),
_: 2
}, 1032, [
"modelValue",
"onUpdate:modelValue",
"item-key",
"onChange"
])])) : (openBlock(), createElementBlock("div", _hoisted_8, [createBaseVNode("div", _hoisted_9, [
!_ctx.isReadOnly ? (openBlock(), createElementBlock("div", _hoisted_10, [createVNode(unref(N8nIconButton_default), {
type: "tertiary",
text: "",
size: "small",
icon: "trash-2",
"data-test-id": "fixed-collection-delete",
title: unref(locale).baseText("fixedCollectionParameter.deleteItem"),
onClick: ($event) => deleteOption(property.name)
}, null, 8, ["title", "onClick"])])) : createCommentVNode("", true),
createVNode(ParameterInputList_default, {
parameters: getVisiblePropertyValues(property),
"node-values": _ctx.nodeValues,
path: getPropertyPath(property.name),
"is-read-only": _ctx.isReadOnly,
class: "parameter-item",
"hide-delete": true,
"hidden-issues-inputs": _ctx.hiddenIssuesInputs,
onValueChanged: valueChanged
}, null, 8, [
"parameters",
"node-values",
"path",
"is-read-only",
"hidden-issues-inputs"
]),
getPickerPropertyValues(property).length > 0 && !_ctx.isReadOnly ? (openBlock(), createElementBlock("div", _hoisted_11, [createVNode(unref(N8nSelect_default), {
placeholder: addOptionalFieldButtonText.value,
size: "small",
filterable: "",
"model-value": null,
"onUpdate:modelValue": (valueName) => toggleOptionalValue(property, valueName)
}, {
default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(getPickerPropertyValues(property), (value) => {
return openBlock(), createBlock(unref(N8nOption_default), {
key: value.name,
label: value.displayName || value.name,
value: value.name
}, {
default: withCtx(() => [createBaseVNode("div", _hoisted_12, [createBaseVNode("span", null, toDisplayString(value.displayName || value.name), 1), isOptionalValueAdded(property.name, value.name) ? (openBlock(), createBlock(unref(N8nIcon_default), {
key: 0,
icon: "check",
size: "medium"
})) : createCommentVNode("", true)])]),
_: 2
}, 1032, ["label", "value"]);
}), 128))]),
_: 2
}, 1032, ["placeholder", "onUpdate:modelValue"])])) : createCommentVNode("", true)
])]))]);
}), 128)),
parameterOptions.value.length > 0 && !_ctx.isReadOnly ? (openBlock(), createElementBlock("div", _hoisted_13, [_ctx.parameter.options && _ctx.parameter.options.length === 1 ? (openBlock(), createBlock(unref(N8nButton_default), {
key: 0,
type: "tertiary",
block: "",
"data-test-id": "fixed-collection-add",
label: getPlaceholderText.value,
onClick: _cache[0] || (_cache[0] = ($event) => onAddButtonClick(_ctx.parameter.options[0].name))
}, null, 8, ["label"])) : (openBlock(), createElementBlock("div", _hoisted_14, [createVNode(unref(N8nSelect_default), {
modelValue: selectedOption.value,
"onUpdate:modelValue": [_cache[1] || (_cache[1] = ($event) => selectedOption.value = $event), optionSelected],
placeholder: getPlaceholderText.value,
size: "small",
filterable: ""
}, {
default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(parameterOptions.value, (item) => {
return openBlock(), createBlock(unref(N8nOption_default), {
key: item.name,
label: unref(locale).nodeText(unref(activeNode)?.type).collectionOptionDisplayName(_ctx.parameter, item, _ctx.path),
value: item.name
}, null, 8, ["label", "value"]);
}), 128))]),
_: 1
}, 8, ["modelValue", "placeholder"])]))])) : createCommentVNode("", true)
], 40, _hoisted_1);
};
}
}), [["__scopeId", "data-v-33c4afd7"]]);
export { FixedCollectionParameter_default as default };