mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
move to table
This commit is contained in:
parent
376fa055e8
commit
a80a56021c
|
@ -199,10 +199,18 @@ export interface IStartRunData {
|
||||||
runData?: IRunData;
|
runData?: IRunData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SubworkflowExecutionInfo {
|
||||||
|
executionId: string;
|
||||||
|
workflowId?: string;
|
||||||
|
}
|
||||||
export interface ITableData {
|
export interface ITableData {
|
||||||
columns: string[];
|
columns: string[];
|
||||||
data: GenericValue[][];
|
data: GenericValue[][];
|
||||||
hasJson: { [key: string]: boolean };
|
hasJson: { [key: string]: boolean };
|
||||||
|
metadata: {
|
||||||
|
hasExecutionIds: boolean;
|
||||||
|
data: Array<SubworkflowExecutionInfo | undefined>;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simple version of n8n-workflow.Workflow
|
// Simple version of n8n-workflow.Workflow
|
||||||
|
|
|
@ -515,25 +515,6 @@ const subWorkflowData = computed((): { executionId: string; workflowId?: string
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
const itemSubWorkflowData = computed(
|
|
||||||
(): Array<{
|
|
||||||
metadata?: { executionId?: string; workflowId?: string };
|
|
||||||
itemIndex: number;
|
|
||||||
}> => {
|
|
||||||
const items = getData(props.runIndex, currentOutputIndex.value);
|
|
||||||
return items
|
|
||||||
.map((item, itemIndex) => {
|
|
||||||
return {
|
|
||||||
metadata: item.metadata,
|
|
||||||
itemIndex,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.filter((item) => {
|
|
||||||
return !!item.metadata;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const hasInputOverwrite = computed((): boolean => {
|
const hasInputOverwrite = computed((): boolean => {
|
||||||
if (!node.value) {
|
if (!node.value) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1222,16 +1203,6 @@ function onSearchClear() {
|
||||||
document.dispatchEvent(new KeyboardEvent('keyup', { key: '/' }));
|
document.dispatchEvent(new KeyboardEvent('keyup', { key: '/' }));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getData(
|
|
||||||
runIndex: number,
|
|
||||||
outputIndex: number,
|
|
||||||
connectionType: NodeConnectionType = NodeConnectionType.Main,
|
|
||||||
) {
|
|
||||||
const rawInputData = getRawInputData(runIndex, outputIndex, connectionType);
|
|
||||||
const pinOrLiveData = getPinDataOrLiveData(rawInputData);
|
|
||||||
return getFilteredData(pinOrLiveData);
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({ enterEditMode });
|
defineExpose({ enterEditMode });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -1418,21 +1389,6 @@ defineExpose({ enterEditMode });
|
||||||
>
|
>
|
||||||
{{ $locale.baseText('runData.openParentExecution') }}
|
{{ $locale.baseText('runData.openParentExecution') }}
|
||||||
</a>
|
</a>
|
||||||
<div v-if="itemSubWorkflowData.length">
|
|
||||||
<N8nSelect
|
|
||||||
size="small"
|
|
||||||
:class="$style.longSelect"
|
|
||||||
model-value="Select exectuion"
|
|
||||||
@change="openExecutionInNewTab($event.metadata.executionId, $event.metadata.workflowId)"
|
|
||||||
>
|
|
||||||
<N8nOption
|
|
||||||
v-for="subWorkflow in itemSubWorkflowData"
|
|
||||||
:key="subWorkflow.metadata?.executionId"
|
|
||||||
:value="subWorkflow"
|
|
||||||
:label="`item#${subWorkflow.itemIndex} exec#${subWorkflow.metadata?.executionId}`"
|
|
||||||
/>
|
|
||||||
</N8nSelect>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useExternalHooks } from '@/composables/useExternalHooks';
|
import { useExternalHooks } from '@/composables/useExternalHooks';
|
||||||
import type { INodeUi, IRunDataDisplayMode, ITableData } from '@/Interface';
|
import type {
|
||||||
|
INodeUi,
|
||||||
|
IRunDataDisplayMode,
|
||||||
|
ITableData,
|
||||||
|
SubworkflowExecutionInfo,
|
||||||
|
} from '@/Interface';
|
||||||
import { useNDVStore } from '@/stores/ndv.store';
|
import { useNDVStore } from '@/stores/ndv.store';
|
||||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||||
import { getMappedExpression } from '@/utils/mappingUtils';
|
import { getMappedExpression } from '@/utils/mappingUtils';
|
||||||
|
@ -13,8 +18,9 @@ import MappingPill from './MappingPill.vue';
|
||||||
import TextWithHighlights from './TextWithHighlights.vue';
|
import TextWithHighlights from './TextWithHighlights.vue';
|
||||||
import { useI18n } from '@/composables/useI18n';
|
import { useI18n } from '@/composables/useI18n';
|
||||||
import { useTelemetry } from '@/composables/useTelemetry';
|
import { useTelemetry } from '@/composables/useTelemetry';
|
||||||
import { N8nInfoTip, N8nTooltip, N8nTree } from 'n8n-design-system';
|
import { N8nIconButton, N8nInfoTip, N8nTooltip, N8nTree } from 'n8n-design-system';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { useExecutionHelpers } from '@/composables/useExecutionHelpers';
|
||||||
|
|
||||||
const MAX_COLUMNS_LIMIT = 40;
|
const MAX_COLUMNS_LIMIT = 40;
|
||||||
|
|
||||||
|
@ -63,6 +69,7 @@ const workflowsStore = useWorkflowsStore();
|
||||||
|
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
const telemetry = useTelemetry();
|
const telemetry = useTelemetry();
|
||||||
|
const { openExecutionInNewTab } = useExecutionHelpers();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
hoveringItem,
|
hoveringItem,
|
||||||
|
@ -304,6 +311,11 @@ function convertToTable(inputData: INodeExecutionData[]): ITableData {
|
||||||
let leftEntryColumns: string[], entryRows: GenericValue[];
|
let leftEntryColumns: string[], entryRows: GenericValue[];
|
||||||
// Go over all entries
|
// Go over all entries
|
||||||
let entry: IDataObject;
|
let entry: IDataObject;
|
||||||
|
|
||||||
|
const metadata: ITableData['metadata'] = {
|
||||||
|
hasExecutionIds: false,
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
const hasJson: { [key: string]: boolean } = {};
|
const hasJson: { [key: string]: boolean } = {};
|
||||||
inputData.forEach((data) => {
|
inputData.forEach((data) => {
|
||||||
if (!data.hasOwnProperty('json')) {
|
if (!data.hasOwnProperty('json')) {
|
||||||
|
@ -322,6 +334,16 @@ function convertToTable(inputData: INodeExecutionData[]): ITableData {
|
||||||
leftEntryColumns = entryColumns;
|
leftEntryColumns = entryColumns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.metadata?.executionId) {
|
||||||
|
metadata.data.push({
|
||||||
|
executionId: data.metadata.executionId,
|
||||||
|
workflowId: data.metadata?.workflowId,
|
||||||
|
});
|
||||||
|
metadata.hasExecutionIds = true;
|
||||||
|
} else {
|
||||||
|
metadata.data.push(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
// Go over all the already existing column-keys
|
// Go over all the already existing column-keys
|
||||||
tableColumns.forEach((key) => {
|
tableColumns.forEach((key) => {
|
||||||
if (entry.hasOwnProperty(key)) {
|
if (entry.hasOwnProperty(key)) {
|
||||||
|
@ -368,6 +390,7 @@ function convertToTable(inputData: INodeExecutionData[]): ITableData {
|
||||||
hasJson,
|
hasJson,
|
||||||
columns: tableColumns,
|
columns: tableColumns,
|
||||||
data: resultTableData,
|
data: resultTableData,
|
||||||
|
metadata,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,6 +398,10 @@ function switchToJsonView() {
|
||||||
emit('displayModeChange', 'json');
|
emit('displayModeChange', 'json');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openExecution({ executionId, workflowId }: SubworkflowExecutionInfo) {
|
||||||
|
openExecutionInNewTab(executionId, workflowId);
|
||||||
|
}
|
||||||
|
|
||||||
watch(focusedMappableInput, (curr) => {
|
watch(focusedMappableInput, (curr) => {
|
||||||
setTimeout(
|
setTimeout(
|
||||||
() => {
|
() => {
|
||||||
|
@ -415,6 +442,9 @@ watch(focusedMappableInput, (curr) => {
|
||||||
<table v-else :class="$style.table">
|
<table v-else :class="$style.table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>
|
||||||
|
<!-- column for item index and execution link -->
|
||||||
|
</th>
|
||||||
<th v-for="(column, i) in tableData.columns || []" :key="column">
|
<th v-for="(column, i) in tableData.columns || []" :key="column">
|
||||||
<N8nTooltip placement="bottom-start" :disabled="!mappingEnabled" :show-after="1000">
|
<N8nTooltip placement="bottom-start" :disabled="!mappingEnabled" :show-after="1000">
|
||||||
<template #content>
|
<template #content>
|
||||||
|
@ -502,6 +532,16 @@ watch(focusedMappableInput, (curr) => {
|
||||||
:class="{ [$style.hoveringRow]: isHoveringRow(index1) }"
|
:class="{ [$style.hoveringRow]: isHoveringRow(index1) }"
|
||||||
:data-test-id="isHoveringRow(index1) ? 'hovering-item' : undefined"
|
:data-test-id="isHoveringRow(index1) ? 'hovering-item' : undefined"
|
||||||
>
|
>
|
||||||
|
<td v-if="tableData.metadata.hasExecutionIds">
|
||||||
|
<N8nIconButton
|
||||||
|
v-if="tableData.metadata.data[index1]"
|
||||||
|
type="secondary"
|
||||||
|
icon="external-link-alt"
|
||||||
|
data-test-id="debug-sub-execution"
|
||||||
|
size="small"
|
||||||
|
@click="openExecution(tableData.metadata.data[index1])"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
<td
|
<td
|
||||||
v-for="(data, index2) in row"
|
v-for="(data, index2) in row"
|
||||||
:key="index2"
|
:key="index2"
|
||||||
|
|
Loading…
Reference in a new issue