fix(editor): Fix rundata type errors (no-changelog) (#9443)

This commit is contained in:
Csaba Tuncsik
2024-05-21 13:19:56 +02:00
committed by GitHub
parent 277511a9b5
commit cd751e7cc8
13 changed files with 95 additions and 55 deletions

View File

@@ -29,6 +29,7 @@ export default defineComponent({
}, },
type: { type: {
type: String, type: String,
required: true,
}, },
data: { data: {
type: String, type: String,

View File

@@ -1,5 +1,6 @@
<template> <template>
<RunData <RunData
v-if="currentNode"
:node="currentNode" :node="currentNode"
:run-index="runIndex" :run-index="runIndex"
:linked-runs="linkedRuns" :linked-runs="linkedRuns"
@@ -112,7 +113,7 @@
type="secondary" type="secondary"
hide-icon hide-icon
:transparent="true" :transparent="true"
:node-name="isActiveNodeConfig ? rootNode : currentNodeName" :node-name="isActiveNodeConfig ? rootNode : currentNodeName ?? ''"
:label="$locale.baseText('ndv.input.noOutputData.executePrevious')" :label="$locale.baseText('ndv.input.noOutputData.executePrevious')"
telemetry-source="inputs" telemetry-source="inputs"
data-test-id="execute-previous-node" data-test-id="execute-previous-node"
@@ -328,7 +329,7 @@ export default defineComponent({
rootNode(): string { rootNode(): string {
const workflow = this.currentWorkflow; const workflow = this.currentWorkflow;
const rootNodes = workflow.getChildNodes(this.activeNode.name, 'ALL_NON_MAIN'); const rootNodes = workflow.getChildNodes(this.activeNode?.name ?? '', 'ALL_NON_MAIN');
return rootNodes[0]; return rootNodes[0];
}, },
@@ -350,7 +351,7 @@ export default defineComponent({
return this.activeNode; return this.activeNode;
} }
return this.workflowsStore.getNodeByName(this.currentNodeName); return this.workflowsStore.getNodeByName(this.currentNodeName ?? '');
}, },
connectedCurrentNodeOutputs(): number[] | undefined { connectedCurrentNodeOutputs(): number[] | undefined {
const search = this.parentNodes.find(({ name }) => name === this.currentNodeName); const search = this.parentNodes.find(({ name }) => name === this.currentNodeName);

View File

@@ -110,7 +110,8 @@ export default defineComponent({
const triggeredNode = this.workflowsStore.executedNode; const triggeredNode = this.workflowsStore.executedNode;
return ( return (
this.workflowRunning && this.workflowRunning &&
(this.workflowsStore.isNodeExecuting(this.node.name) || triggeredNode === this.node.name) (this.workflowsStore.isNodeExecuting(this.node?.name ?? '') ||
triggeredNode === this.node?.name)
); );
}, },
workflowRunning(): boolean { workflowRunning(): boolean {
@@ -148,7 +149,7 @@ export default defineComponent({
const executedNode = this.workflowsStore.executedNode; const executedNode = this.workflowsStore.executedNode;
return ( return (
this.node && !!this.node &&
!this.node.disabled && !this.node.disabled &&
this.isTriggerNode && this.isTriggerNode &&
waitingOnWebhook && waitingOnWebhook &&
@@ -173,7 +174,7 @@ export default defineComponent({
return ''; return '';
} }
if (this.isTriggerNode && this.node.disabled) { if (this.isTriggerNode && this.node?.disabled) {
return this.$locale.baseText('ndv.execute.nodeIsDisabled'); return this.$locale.baseText('ndv.execute.nodeIsDisabled');
} }

View File

@@ -1,5 +1,6 @@
<template> <template>
<RunData <RunData
v-if="node"
ref="runData" ref="runData"
:node="node" :node="node"
:run-index="runIndex" :run-index="runIndex"
@@ -50,7 +51,7 @@
$locale.baseText('ndv.output.waitingToRun') $locale.baseText('ndv.output.waitingToRun')
}}</n8n-text> }}</n8n-text>
<n8n-text v-if="!workflowRunning" data-test-id="ndv-output-run-node-hint"> <n8n-text v-if="!workflowRunning" data-test-id="ndv-output-run-node-hint">
<template v-if="isSubNodeType.value"> <template v-if="isSubNodeType">
{{ $locale.baseText('ndv.output.runNodeHintSubNode') }} {{ $locale.baseText('ndv.output.runNodeHintSubNode') }}
</template> </template>
<template v-else> <template v-else>
@@ -120,7 +121,7 @@ type RunDataRef = InstanceType<typeof RunData>;
const OUTPUT_TYPE = { const OUTPUT_TYPE = {
REGULAR: 'regular', REGULAR: 'regular',
LOGS: 'logs', LOGS: 'logs',
}; } as const;
export default defineComponent({ export default defineComponent({
name: 'OutputPanel', name: 'OutputPanel',
@@ -192,7 +193,7 @@ export default defineComponent({
return null; return null;
}, },
isTriggerNode(): boolean { isTriggerNode(): boolean {
return this.nodeTypesStore.isTriggerNode(this.node.type); return this.nodeTypesStore.isTriggerNode(this.node?.type ?? '');
}, },
hasAiMetadata(): boolean { hasAiMetadata(): boolean {
if (this.node) { if (this.node) {
@@ -213,7 +214,7 @@ export default defineComponent({
return !!(this.nodeType && this.nodeType.group.includes('schedule')); return !!(this.nodeType && this.nodeType.group.includes('schedule'));
}, },
isNodeRunning(): boolean { isNodeRunning(): boolean {
return this.node && this.workflowsStore.isNodeExecuting(this.node.name); return !!this.node && this.workflowsStore.isNodeExecuting(this.node.name);
}, },
workflowRunning(): boolean { workflowRunning(): boolean {
return this.uiStore.isActionActive('workflowRunning'); return this.uiStore.isActionActive('workflowRunning');
@@ -301,7 +302,7 @@ export default defineComponent({
this.$telemetry.track('User clicked ndv link', { this.$telemetry.track('User clicked ndv link', {
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
push_ref: this.pushRef, push_ref: this.pushRef,
node_type: this.node.type, node_type: this.node?.type,
pane: 'output', pane: 'output',
type: 'insert-test-data', type: 'insert-test-data',
}); });
@@ -316,7 +317,7 @@ export default defineComponent({
openSettings() { openSettings() {
this.$emit('openSettings'); this.$emit('openSettings');
this.$telemetry.track('User clicked ndv link', { this.$telemetry.track('User clicked ndv link', {
node_type: this.node.type, node_type: this.node?.type,
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
push_ref: this.pushRef, push_ref: this.pushRef,
pane: 'output', pane: 'output',
@@ -326,7 +327,7 @@ export default defineComponent({
onRunIndexChange(run: number) { onRunIndexChange(run: number) {
this.$emit('runChange', run); this.$emit('runChange', run);
}, },
onUpdateOutputMode(outputMode: (typeof OUTPUT_TYPE)[string]) { onUpdateOutputMode(outputMode: (typeof OUTPUT_TYPE)[keyof typeof OUTPUT_TYPE]) {
if (outputMode === OUTPUT_TYPE.LOGS) { if (outputMode === OUTPUT_TYPE.LOGS) {
ndvEventBus.emit('setPositionByName', 'minLeft'); ndvEventBus.emit('setPositionByName', 'minLeft');
} else { } else {

View File

@@ -63,7 +63,7 @@
v-show="!editMode.enabled" v-show="!editMode.enabled"
:title="$locale.baseText('runData.editOutput')" :title="$locale.baseText('runData.editOutput')"
:circle="false" :circle="false"
:disabled="node.disabled" :disabled="node?.disabled"
class="ml-2xs" class="ml-2xs"
icon="pencil-alt" icon="pencil-alt"
type="tertiary" type="tertiary"
@@ -158,7 +158,7 @@
:class="$style.hintCallout" :class="$style.hintCallout"
:theme="hint.type || 'info'" :theme="hint.type || 'info'"
> >
<n8n-text v-html="hint.message" size="small"></n8n-text> <n8n-text size="small" v-html="hint.message"></n8n-text>
</n8n-callout> </n8n-callout>
<div <div
@@ -251,7 +251,7 @@
<slot name="node-not-run"></slot> <slot name="node-not-run"></slot>
</div> </div>
<div v-else-if="paneType === 'input' && node.disabled" :class="$style.center"> <div v-else-if="paneType === 'input' && node?.disabled" :class="$style.center">
<n8n-text> <n8n-text>
{{ $locale.baseText('ndv.input.disabled', { interpolate: { nodeName: node.name } }) }} {{ $locale.baseText('ndv.input.disabled', { interpolate: { nodeName: node.name } }) }}
<n8n-link @click="enableNode"> <n8n-link @click="enableNode">
@@ -268,14 +268,14 @@
<n8n-text v-if="isPaneTypeInput" :class="$style.center" size="large" tag="p" bold> <n8n-text v-if="isPaneTypeInput" :class="$style.center" size="large" tag="p" bold>
{{ {{
$locale.baseText('nodeErrorView.inputPanel.previousNodeError.title', { $locale.baseText('nodeErrorView.inputPanel.previousNodeError.title', {
interpolate: { nodeName: node.name }, interpolate: { nodeName: node?.name ?? '' },
}) })
}} }}
</n8n-text> </n8n-text>
<slot v-else-if="$slots['content']" name="content"></slot> <slot v-else-if="$slots['content']" name="content"></slot>
<NodeErrorView <NodeErrorView
v-else v-else-if="hasRunError"
:error="workflowRunData[node.name][runIndex].error" :error="workflowRunErrorAsNodeError"
:class="$style.dataDisplay" :class="$style.dataDisplay"
/> />
</div> </div>
@@ -387,7 +387,7 @@
/> />
</Suspense> </Suspense>
<Suspense v-else-if="hasNodeRun && displayMode === 'json'"> <Suspense v-else-if="hasNodeRun && displayMode === 'json' && node">
<RunDataJson <RunDataJson
:pane-type="paneType" :pane-type="paneType"
:edit-mode="editMode" :edit-mode="editMode"
@@ -403,7 +403,7 @@
</Suspense> </Suspense>
<Suspense v-else-if="hasNodeRun && isPaneTypeOutput && displayMode === 'html'"> <Suspense v-else-if="hasNodeRun && isPaneTypeOutput && displayMode === 'html'">
<RunDataHtml :input-html="inputDataPage[0].json.html" /> <RunDataHtml :input-html="inputHtml" />
</Suspense> </Suspense>
<Suspense v-else-if="hasNodeRun && isSchemaView"> <Suspense v-else-if="hasNodeRun && isSchemaView">
@@ -567,6 +567,7 @@ import type {
IRunData, IRunData,
IRunExecutionData, IRunExecutionData,
NodeHint, NodeHint,
NodeError,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { NodeHelpers, NodeConnectionType } from 'n8n-workflow'; import { NodeHelpers, NodeConnectionType } from 'n8n-workflow';
@@ -595,7 +596,7 @@ import BinaryDataDisplay from '@/components/BinaryDataDisplay.vue';
import NodeErrorView from '@/components/Error/NodeErrorView.vue'; import NodeErrorView from '@/components/Error/NodeErrorView.vue';
import JsonEditor from '@/components/JsonEditor/JsonEditor.vue'; import JsonEditor from '@/components/JsonEditor/JsonEditor.vue';
import type { PinDataSource } from '@/composables/usePinnedData'; import type { PinDataSource, UnpinDataSource } from '@/composables/usePinnedData';
import { usePinnedData } from '@/composables/usePinnedData'; import { usePinnedData } from '@/composables/usePinnedData';
import { dataPinningEventBus } from '@/event-bus'; import { dataPinningEventBus } from '@/event-bus';
import { clearJsonKey, isEmpty } from '@/utils/typesUtils'; import { clearJsonKey, isEmpty } from '@/utils/typesUtils';
@@ -644,7 +645,7 @@ export default defineComponent({
props: { props: {
node: { node: {
type: Object as PropType<INodeUi>, type: Object as PropType<INodeUi>,
default: null, required: true,
}, },
runIndex: { runIndex: {
type: Number, type: Number,
@@ -683,6 +684,7 @@ export default defineComponent({
}, },
distanceFromActive: { distanceFromActive: {
type: Number, type: Number,
default: 0,
}, },
blockUI: { blockUI: {
type: Boolean, type: Boolean,
@@ -716,7 +718,7 @@ export default defineComponent({
}, },
data() { data() {
return { return {
connectionType: NodeConnectionType.Main, connectionType: NodeConnectionType.Main as ConnectionTypes,
binaryDataPreviewActive: false, binaryDataPreviewActive: false,
dataSize: 0, dataSize: 0,
showData: false, showData: false,
@@ -825,11 +827,20 @@ export default defineComponent({
isArtificialRecoveredEventItem(): boolean { isArtificialRecoveredEventItem(): boolean {
return !!this.rawInputData?.[0]?.json?.isArtificialRecoveredEventItem; return !!this.rawInputData?.[0]?.json?.isArtificialRecoveredEventItem;
}, },
subworkflowExecutionError(): Error | null { subworkflowExecutionError(): NodeError {
return this.workflowsStore.subWorkflowExecutionError; return {
node: this.node,
messages: [this.workflowsStore.subWorkflowExecutionError?.message ?? ''],
} as NodeError;
}, },
hasSubworkflowExecutionError(): boolean { hasSubworkflowExecutionError(): boolean {
return Boolean(this.subworkflowExecutionError); return Boolean(this.workflowsStore.subWorkflowExecutionError);
},
workflowRunErrorAsNodeError(): NodeError {
return {
node: this.node,
messages: [this.workflowRunData?.[this.node?.name]?.[this.runIndex]?.error?.message ?? ''],
} as NodeError;
}, },
hasRunError(): boolean { hasRunError(): boolean {
return Boolean(this.node && this.workflowRunData?.[this.node.name]?.[this.runIndex]?.error); return Boolean(this.node && this.workflowRunData?.[this.node.name]?.[this.runIndex]?.error);
@@ -938,6 +949,9 @@ export default defineComponent({
); );
return binaryData.filter((data) => Boolean(data && Object.keys(data).length)); return binaryData.filter((data) => Boolean(data && Object.keys(data).length));
}, },
inputHtml(): string {
return String(this.inputData[0]?.json?.html ?? '');
},
currentOutputIndex(): number { currentOutputIndex(): number {
if (this.overrideOutputs?.length && !this.overrideOutputs.includes(this.outputIndex)) { if (this.overrideOutputs?.length && !this.overrideOutputs.includes(this.outputIndex)) {
return this.overrideOutputs[0]; return this.overrideOutputs[0];
@@ -1005,7 +1019,7 @@ export default defineComponent({
return this.hasNodeRun && !this.hasRunError; return this.hasNodeRun && !this.hasRunError;
}, },
showIoSearchNoMatchContent(): boolean { showIoSearchNoMatchContent(): boolean {
return this.hasNodeRun && !this.inputData.length && this.search; return this.hasNodeRun && !this.inputData.length && !!this.search;
}, },
}, },
watch: { watch: {
@@ -1195,7 +1209,11 @@ export default defineComponent({
? clearJsonKey(this.pinnedData.data.value) ? clearJsonKey(this.pinnedData.data.value)
: executionDataToJson(this.rawInputData); : executionDataToJson(this.rawInputData);
const data = inputData.length > 0 ? inputData : TEST_PIN_DATA; const inputDataLength = Array.isArray(inputData)
? inputData.length
: Object.keys(inputData ?? {}).length;
const data = inputDataLength > 0 ? inputData : TEST_PIN_DATA;
this.ndvStore.setOutputPanelEditModeEnabled(true); this.ndvStore.setOutputPanelEditModeEnabled(true);
this.ndvStore.setOutputPanelEditModeValue(JSON.stringify(data, null, 2)); this.ndvStore.setOutputPanelEditModeValue(JSON.stringify(data, null, 2));
@@ -1244,14 +1262,14 @@ export default defineComponent({
type, type,
}); });
}, },
async onTogglePinData({ source }: { source: PinDataSource }) { async onTogglePinData({ source }: { source: PinDataSource | UnpinDataSource }) {
if (!this.node) { if (!this.node) {
return; return;
} }
if (source === 'pin-icon-click') { if (source === 'pin-icon-click') {
const telemetryPayload = { const telemetryPayload = {
node_type: this.activeNode.type, node_type: this.activeNode?.type,
push_ref: this.pushRef, push_ref: this.pushRef,
run_index: this.runIndex, run_index: this.runIndex,
view: !this.hasNodeRun && !this.pinnedData.hasData.value ? 'none' : this.displayMode, view: !this.hasNodeRun && !this.pinnedData.hasData.value ? 'none' : this.displayMode,
@@ -1300,7 +1318,7 @@ export default defineComponent({
this.$telemetry.track('User changed ndv branch', { this.$telemetry.track('User changed ndv branch', {
push_ref: this.pushRef, push_ref: this.pushRef,
branch_index: value, branch_index: value,
node_type: this.activeNode.type, node_type: this.activeNode?.type,
node_type_input_selection: this.nodeType ? this.nodeType.name : '', node_type_input_selection: this.nodeType ? this.nodeType.name : '',
pane: this.paneType, pane: this.paneType,
}); });
@@ -1308,7 +1326,7 @@ export default defineComponent({
showTooMuchData() { showTooMuchData() {
this.showData = true; this.showData = true;
this.$telemetry.track('User clicked ndv button', { this.$telemetry.track('User clicked ndv button', {
node_type: this.activeNode.type, node_type: this.activeNode?.type,
workflow_id: this.workflowsStore.workflowId, workflow_id: this.workflowsStore.workflowId,
push_ref: this.pushRef, push_ref: this.pushRef,
pane: this.paneType, pane: this.paneType,
@@ -1324,7 +1342,7 @@ export default defineComponent({
unlinkRun() { unlinkRun() {
this.$emit('unlinkRun'); this.$emit('unlinkRun');
}, },
onCurrentPageChange(value) { onCurrentPageChange(value: number) {
this.currentPage = value; this.currentPage = value;
this.$telemetry.track('User changed ndv page', { this.$telemetry.track('User changed ndv page', {
node_type: this.activeNode?.type, node_type: this.activeNode?.type,
@@ -1487,21 +1505,21 @@ export default defineComponent({
this.workflowsStore.setWorkflowExecutionData(null); this.workflowsStore.setWorkflowExecutionData(null);
this.nodeHelpers.updateNodesExecutionIssues(); this.nodeHelpers.updateNodesExecutionIssues();
}, },
isViewable(index: number, key: string): boolean { isViewable(index: number, key: string | number): boolean {
const { fileType } = this.binaryData[index][key]; const { fileType } = this.binaryData[index][key];
return ( return (
!!fileType && ['image', 'audio', 'video', 'text', 'json', 'pdf', 'html'].includes(fileType) !!fileType && ['image', 'audio', 'video', 'text', 'json', 'pdf', 'html'].includes(fileType)
); );
}, },
isDownloadable(index: number, key: string): boolean { isDownloadable(index: number, key: string | number): boolean {
const { mimeType, fileName } = this.binaryData[index][key]; const { mimeType, fileName } = this.binaryData[index][key];
return !!(mimeType && fileName); return !!(mimeType && fileName);
}, },
async downloadBinaryData(index: number, key: string) { async downloadBinaryData(index: number, key: string | number) {
const { id, data, fileName, fileExtension, mimeType } = this.binaryData[index][key]; const { id, data, fileName, fileExtension, mimeType } = this.binaryData[index][key];
if (id) { if (id) {
const url = this.workflowsStore.getBinaryUrl(id, 'download', fileName, mimeType); const url = this.workflowsStore.getBinaryUrl(id, 'download', fileName ?? '', mimeType);
saveAs(url, [fileName, fileExtension].join('.')); saveAs(url, [fileName, fileExtension].join('.'));
return; return;
} else { } else {
@@ -1518,7 +1536,8 @@ export default defineComponent({
saveAs(blob, `${fileName}.json`); saveAs(blob, `${fileName}.json`);
}, },
displayBinaryData(index: number, key: string) { displayBinaryData(index: number, key: string | number) {
const { data, mimeType } = this.binaryData[index][key];
this.binaryDataDisplayVisible = true; this.binaryDataDisplayVisible = true;
this.binaryDataDisplayData = { this.binaryDataDisplayData = {
@@ -1527,6 +1546,8 @@ export default defineComponent({
outputIndex: this.currentOutputIndex, outputIndex: this.currentOutputIndex,
index, index,
key, key,
data,
mimeType,
}; };
}, },
getOutputName(outputIndex: number) { getOutputName(outputIndex: number) {

View File

@@ -3,7 +3,6 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import type { PropType } from 'vue';
import sanitizeHtml, { defaults, type IOptions as SanitizeOptions } from 'sanitize-html'; import sanitizeHtml, { defaults, type IOptions as SanitizeOptions } from 'sanitize-html';
const sanitizeOptions: SanitizeOptions = { const sanitizeOptions: SanitizeOptions = {
@@ -24,7 +23,8 @@ export default {
name: 'RunDataHtml', name: 'RunDataHtml',
props: { props: {
inputHtml: { inputHtml: {
type: String as PropType<string>, type: String,
required: true,
}, },
}, },
computed: { computed: {

View File

@@ -108,7 +108,8 @@ export default defineComponent({
}, },
props: { props: {
editMode: { editMode: {
type: Object as () => { enabled?: boolean; value?: string }, type: Object as PropType<{ enabled?: boolean; value?: string }>,
default: () => ({}),
}, },
pushRef: { pushRef: {
type: String, type: String,
@@ -118,15 +119,18 @@ export default defineComponent({
}, },
node: { node: {
type: Object as PropType<INodeUi>, type: Object as PropType<INodeUi>,
required: true,
}, },
inputData: { inputData: {
type: Array as PropType<INodeExecutionData[]>, type: Array as PropType<INodeExecutionData[]>,
required: true,
}, },
mappingEnabled: { mappingEnabled: {
type: Boolean, type: Boolean,
}, },
distanceFromActive: { distanceFromActive: {
type: Number, type: Number,
required: true,
}, },
runIndex: { runIndex: {
type: Number, type: Number,

View File

@@ -64,6 +64,7 @@ export default defineComponent({
props: { props: {
node: { node: {
type: Object as PropType<INodeUi>, type: Object as PropType<INodeUi>,
required: true,
}, },
paneType: { paneType: {
type: String, type: String,
@@ -156,14 +157,14 @@ export default defineComponent({
const pathParts = newPath.split(']'); const pathParts = newPath.split(']');
const index = pathParts[0].slice(1); const index = pathParts[0].slice(1);
path = pathParts.slice(1).join(']'); path = pathParts.slice(1).join(']');
startPath = `$item(${index}).$node["${this.node!.name}"].json`; startPath = `$item(${index}).$node["${this.node.name}"].json`;
return { path, startPath }; return { path, startPath };
}, },
getJsonParameterPath(): JsonPathData { getJsonParameterPath(): JsonPathData {
const newPath = convertPath(this.normalisedJsonPath); const newPath = convertPath(this.normalisedJsonPath);
const path = newPath.split(']').slice(1).join(']'); const path = newPath.split(']').slice(1).join(']');
let startPath = `$node["${this.node!.name}"].json`; let startPath = `$node["${this.node.name}"].json`;
if (this.distanceFromActive === 1) { if (this.distanceFromActive === 1) {
startPath = '$json'; startPath = '$json';
@@ -221,7 +222,7 @@ export default defineComponent({
}[commandData.command]; }[commandData.command];
this.$telemetry.track('User copied ndv data', { this.$telemetry.track('User copied ndv data', {
node_type: this.activeNode.type, node_type: this.activeNode?.type,
push_ref: this.pushRef, push_ref: this.pushRef,
run_index: this.runIndex, run_index: this.runIndex,
view: 'json', view: 'json',

View File

@@ -22,6 +22,9 @@ type Props = {
const props = defineProps<Props>(); const props = defineProps<Props>();
const isSchemaValueArray = computed(() => Array.isArray(props.schema.value)); const isSchemaValueArray = computed(() => Array.isArray(props.schema.value));
const schemaArray = computed(
() => (isSchemaValueArray.value ? props.schema.value : []) as Schema[],
);
const isSchemaParentTypeArray = computed(() => props.parent?.type === 'array'); const isSchemaParentTypeArray = computed(() => props.parent?.type === 'array');
const isFlat = computed( const isFlat = computed(
() => () =>
@@ -71,9 +74,10 @@ const getIconBySchemaType = (type: Schema['type']): string => {
return 'sun'; return 'sun';
case 'undefined': case 'undefined':
return 'ban'; return 'ban';
} default:
checkExhaustive(type); checkExhaustive(type);
return '';
}
}; };
</script> </script>
@@ -117,7 +121,7 @@ const getIconBySchemaType = (type: Schema['type']): string => {
</label> </label>
<div v-if="isSchemaValueArray" :class="{ [$style.sub]: true, [$style.flat]: isFlat }"> <div v-if="isSchemaValueArray" :class="{ [$style.sub]: true, [$style.flat]: isFlat }">
<run-data-schema-item <run-data-schema-item
v-for="(s, i) in schema.value" v-for="(s, i) in schemaArray"
:key="`${s.type}-${level}-${i}`" :key="`${s.type}-${level}-${i}`"
:schema="s" :schema="s"
:level="level + 1" :level="level + 1"

View File

@@ -187,15 +187,18 @@ export default defineComponent({
props: { props: {
node: { node: {
type: Object as PropType<INodeUi>, type: Object as PropType<INodeUi>,
required: true,
}, },
inputData: { inputData: {
type: Array as PropType<INodeExecutionData[]>, type: Array as PropType<INodeExecutionData[]>,
required: true,
}, },
mappingEnabled: { mappingEnabled: {
type: Boolean, type: Boolean,
}, },
distanceFromActive: { distanceFromActive: {
type: Number, type: Number,
required: true,
}, },
runIndex: { runIndex: {
type: Number, type: Number,
@@ -208,6 +211,7 @@ export default defineComponent({
}, },
pageOffset: { pageOffset: {
type: Number, type: Number,
required: true,
}, },
hasDefaultHoverState: { hasDefaultHoverState: {
type: Boolean, type: Boolean,
@@ -237,7 +241,7 @@ export default defineComponent({
}, },
mounted() { mounted() {
if (this.tableData && this.tableData.columns && this.$refs.draggable) { if (this.tableData && this.tableData.columns && this.$refs.draggable) {
const tbody = (this.$refs.draggable as DraggableRef).$refs.wrapper; const tbody = (this.$refs.draggable as DraggableRef).$refs.wrapper as HTMLElement;
if (tbody) { if (tbody) {
this.$emit('mounted', { this.$emit('mounted', {
avgRowHeight: tbody.offsetHeight / this.tableData.data.length, avgRowHeight: tbody.offsetHeight / this.tableData.data.length,
@@ -280,7 +284,7 @@ export default defineComponent({
return true; return true;
} }
const itemNodeId = getPairedItemId( const itemNodeId = getPairedItemId(
this.node.name, this.node?.name ?? '',
this.runIndex || 0, this.runIndex || 0,
this.outputIndex || 0, this.outputIndex || 0,
itemIndex, itemIndex,
@@ -398,7 +402,7 @@ export default defineComponent({
if (value === true || value === false || typeof value === 'number') { if (value === true || value === false || typeof value === 'number') {
return value.toString(); return value.toString();
} }
return value; return JSON.stringify(value);
}, },
onDragStart() { onDragStart() {
this.draggedColumn = true; this.draggedColumn = true;

View File

@@ -28,7 +28,8 @@ export type PinDataSource =
| 'duplicate-node' | 'duplicate-node'
| 'add-nodes' | 'add-nodes'
| 'context-menu' | 'context-menu'
| 'keyboard-shortcut'; | 'keyboard-shortcut'
| 'banner-link';
export type UnpinDataSource = export type UnpinDataSource =
| 'unpin-and-execute-modal' | 'unpin-and-execute-modal'
@@ -242,7 +243,7 @@ export function usePinnedData(
onSetDataSuccess({ source }); onSetDataSuccess({ source });
} }
function onUnsetData({ source }: { source: UnpinDataSource }) { function onUnsetData({ source }: { source: PinDataSource | UnpinDataSource }) {
const targetNode = unref(node); const targetNode = unref(node);
const runIndex = unref(options.runIndex); const runIndex = unref(options.runIndex);
@@ -255,7 +256,7 @@ export function usePinnedData(
}); });
} }
function unsetData(source: UnpinDataSource): void { function unsetData(source: PinDataSource | UnpinDataSource): void {
const targetNode = unref(node); const targetNode = unref(node);
if (!targetNode) { if (!targetNode) {
return; return;

View File

@@ -1479,6 +1479,7 @@
"runData.executeNode": "Test Node", "runData.executeNode": "Test Node",
"runData.executionTime": "Execution Time", "runData.executionTime": "Execution Time",
"runData.fileExtension": "File Extension", "runData.fileExtension": "File Extension",
"runData.directory": "Directory",
"runData.fileName": "File Name", "runData.fileName": "File Name",
"runData.invalidPinnedData": "Invalid pinned data", "runData.invalidPinnedData": "Invalid pinned data",
"runData.items": "Items", "runData.items": "Items",

View File

@@ -39,7 +39,7 @@ export type IAllExecuteFunctions =
export type BinaryFileType = 'text' | 'json' | 'image' | 'audio' | 'video' | 'pdf' | 'html'; export type BinaryFileType = 'text' | 'json' | 'image' | 'audio' | 'video' | 'pdf' | 'html';
export interface IBinaryData { export interface IBinaryData {
[key: string]: string | undefined; [key: string]: string | number | undefined;
data: string; data: string;
mimeType: string; mimeType: string;
fileType?: BinaryFileType; fileType?: BinaryFileType;