mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
fix: refactor more
This commit is contained in:
parent
ad990236eb
commit
785b30e675
|
@ -202,17 +202,13 @@ 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: {
|
metadata: {
|
||||||
hasExecutionIds: boolean;
|
hasExecutionIds: boolean;
|
||||||
data: Array<SubworkflowExecutionInfo | undefined>;
|
data: Array<INodeExecutionData['metadata'] | undefined>;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -182,7 +182,7 @@ const nodeHelpers = useNodeHelpers();
|
||||||
const externalHooks = useExternalHooks();
|
const externalHooks = useExternalHooks();
|
||||||
const telemetry = useTelemetry();
|
const telemetry = useTelemetry();
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
const { openExecutionInNewTab } = useExecutionHelpers();
|
const { openRelatedExecution } = useExecutionHelpers();
|
||||||
|
|
||||||
const node = toRef(props, 'node');
|
const node = toRef(props, 'node');
|
||||||
|
|
||||||
|
@ -514,7 +514,6 @@ const subWorkflowData = computed((): ITaskMetadata | null => {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const metadata = get(workflowRunData.value, [node.value.name, props.runIndex, 'metadata'], null);
|
const metadata = get(workflowRunData.value, [node.value.name, props.runIndex, 'metadata'], null);
|
||||||
console.log('yo', metadata);
|
|
||||||
if (!metadata?.parentExecution && !metadata?.subExecution) {
|
if (!metadata?.parentExecution && !metadata?.subExecution) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1210,22 +1209,6 @@ function onSearchClear() {
|
||||||
document.dispatchEvent(new KeyboardEvent('keyup', { key: '/' }));
|
document.dispatchEvent(new KeyboardEvent('keyup', { key: '/' }));
|
||||||
}
|
}
|
||||||
|
|
||||||
function onOpenRelatedExecution({ parentExecution, subExecution }: ITaskMetadata) {
|
|
||||||
const info = parentExecution || subExecution;
|
|
||||||
if (!info) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
openExecutionInNewTab(info.executionId, info.workflowId);
|
|
||||||
|
|
||||||
telemetry.track(
|
|
||||||
parentExecution ? 'User clicked parent execution button' : 'User clicked inspect sub-workflow',
|
|
||||||
{
|
|
||||||
view: displayMode.value,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({ enterEditMode });
|
defineExpose({ enterEditMode });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -1454,7 +1437,7 @@ defineExpose({ enterEditMode });
|
||||||
v-if="subWorkflowData && !(paneType === 'input' && hasInputOverwrite)"
|
v-if="subWorkflowData && !(paneType === 'input' && hasInputOverwrite)"
|
||||||
:class="$style.parentExecutionInfo"
|
:class="$style.parentExecutionInfo"
|
||||||
>
|
>
|
||||||
<a @click.stop="onOpenRelatedExecution(subWorkflowData)">
|
<a @click.stop="openRelatedExecution(subWorkflowData, displayMode)">
|
||||||
<N8nIcon icon="external-link-alt" size="xsmall" />
|
<N8nIcon icon="external-link-alt" size="xsmall" />
|
||||||
{{
|
{{
|
||||||
subWorkflowData.parentExecution
|
subWorkflowData.parentExecution
|
||||||
|
|
|
@ -12,7 +12,6 @@ import { computed } from 'vue';
|
||||||
import NodeIcon from '@/components/NodeIcon.vue';
|
import NodeIcon from '@/components/NodeIcon.vue';
|
||||||
import AiRunContentBlock from './AiRunContentBlock.vue';
|
import AiRunContentBlock from './AiRunContentBlock.vue';
|
||||||
import { useExecutionHelpers } from '@/composables/useExecutionHelpers';
|
import { useExecutionHelpers } from '@/composables/useExecutionHelpers';
|
||||||
import { useTelemetry } from '@/composables/useTelemetry';
|
|
||||||
|
|
||||||
interface RunMeta {
|
interface RunMeta {
|
||||||
startTimeMs: number;
|
startTimeMs: number;
|
||||||
|
@ -33,9 +32,7 @@ const props = defineProps<{
|
||||||
const nodeTypesStore = useNodeTypesStore();
|
const nodeTypesStore = useNodeTypesStore();
|
||||||
const workflowsStore = useWorkflowsStore();
|
const workflowsStore = useWorkflowsStore();
|
||||||
|
|
||||||
const telemetry = useTelemetry();
|
const { openRelatedExecution } = useExecutionHelpers();
|
||||||
|
|
||||||
const { openExecutionInNewTab } = useExecutionHelpers();
|
|
||||||
|
|
||||||
type TokenUsageData = {
|
type TokenUsageData = {
|
||||||
completionTokens: number;
|
completionTokens: number;
|
||||||
|
@ -111,15 +108,6 @@ const outputError = computed(() => {
|
||||||
| NodeError
|
| NodeError
|
||||||
| undefined;
|
| undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
// todo unify function across components
|
|
||||||
function openExecution({ executionId, workflowId }: { workflowId: string; executionId: string }) {
|
|
||||||
openExecutionInNewTab(executionId, workflowId);
|
|
||||||
|
|
||||||
telemetry.track('User clicked inspect sub-workflow', {
|
|
||||||
view: 'ai',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -152,7 +140,7 @@ function openExecution({ executionId, workflowId }: { workflowId: string; execut
|
||||||
</n8n-tooltip>
|
</n8n-tooltip>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="runMeta?.subExecution">
|
<li v-if="runMeta?.subExecution">
|
||||||
<a @click.stop="openExecution(runMeta.subExecution)">
|
<a @click.stop="openRelatedExecution(runMeta, 'ai')">
|
||||||
<N8nIcon icon="external-link-alt" size="xsmall" />
|
<N8nIcon icon="external-link-alt" size="xsmall" />
|
||||||
{{ $locale.baseText('runData.openSubExecution') }}
|
{{ $locale.baseText('runData.openSubExecution') }}
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useExternalHooks } from '@/composables/useExternalHooks';
|
import { useExternalHooks } from '@/composables/useExternalHooks';
|
||||||
import type {
|
import type { INodeUi, IRunDataDisplayMode, ITableData } from '@/Interface';
|
||||||
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';
|
||||||
|
@ -69,7 +64,7 @@ const workflowsStore = useWorkflowsStore();
|
||||||
|
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
const telemetry = useTelemetry();
|
const telemetry = useTelemetry();
|
||||||
const { openExecutionInNewTab } = useExecutionHelpers();
|
const { openRelatedExecution } = useExecutionHelpers();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
hoveringItem,
|
hoveringItem,
|
||||||
|
@ -346,11 +341,8 @@ function convertToTable(inputData: INodeExecutionData[]): ITableData {
|
||||||
leftEntryColumns = entryColumns;
|
leftEntryColumns = entryColumns;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.metadata?.executionId) {
|
if (data.metadata?.subExecution) {
|
||||||
metadata.data.push({
|
metadata.data.push(data.metadata);
|
||||||
executionId: data.metadata.executionId,
|
|
||||||
workflowId: data.metadata?.workflowId,
|
|
||||||
});
|
|
||||||
metadata.hasExecutionIds = true;
|
metadata.hasExecutionIds = true;
|
||||||
} else {
|
} else {
|
||||||
metadata.data.push(undefined);
|
metadata.data.push(undefined);
|
||||||
|
@ -410,14 +402,6 @@ function switchToJsonView() {
|
||||||
emit('displayModeChange', 'json');
|
emit('displayModeChange', 'json');
|
||||||
}
|
}
|
||||||
|
|
||||||
function openExecution({ executionId, workflowId }: SubworkflowExecutionInfo) {
|
|
||||||
openExecutionInNewTab(executionId, workflowId);
|
|
||||||
|
|
||||||
telemetry.track('User clicked inspect sub-workflow', {
|
|
||||||
view: 'table',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(focusedMappableInput, (curr) => {
|
watch(focusedMappableInput, (curr) => {
|
||||||
setTimeout(
|
setTimeout(
|
||||||
() => {
|
() => {
|
||||||
|
@ -562,7 +546,7 @@ watch(focusedMappableInput, (curr) => {
|
||||||
icon="external-link-alt"
|
icon="external-link-alt"
|
||||||
data-test-id="debug-sub-execution"
|
data-test-id="debug-sub-execution"
|
||||||
size="mini"
|
size="mini"
|
||||||
@click="openExecution(tableData.metadata.data[index1])"
|
@click="openRelatedExecution(tableData.metadata.data[index1], 'table')"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import type { ExecutionSummary } from 'n8n-workflow';
|
import type { ExecutionSummary, RelatedExecution } from 'n8n-workflow';
|
||||||
import { convertToDisplayDate } from '@/utils/formatters/dateFormatter';
|
import { convertToDisplayDate } from '@/utils/formatters/dateFormatter';
|
||||||
import { useI18n } from '@/composables/useI18n';
|
import { useI18n } from '@/composables/useI18n';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { VIEWS } from '@/constants';
|
import { VIEWS } from '@/constants';
|
||||||
import { useExecutionsStore } from '@/stores/executions.store';
|
import { useTelemetry } from './useTelemetry';
|
||||||
import { useToast } from './useToast';
|
import type { IRunDataDisplayMode } from '@/Interface';
|
||||||
|
|
||||||
export interface IExecutionUIData {
|
export interface IExecutionUIData {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -19,8 +19,7 @@ export interface IExecutionUIData {
|
||||||
export function useExecutionHelpers() {
|
export function useExecutionHelpers() {
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const executionsStore = useExecutionsStore();
|
const telemetry = useTelemetry();
|
||||||
const toast = useToast();
|
|
||||||
|
|
||||||
function getUIDetails(execution: ExecutionSummary): IExecutionUIData {
|
function getUIDetails(execution: ExecutionSummary): IExecutionUIData {
|
||||||
const status = {
|
const status = {
|
||||||
|
@ -76,35 +75,34 @@ export function useExecutionHelpers() {
|
||||||
return ['crashed', 'error'].includes(execution.status) && !execution.retrySuccessId;
|
return ['crashed', 'error'].includes(execution.status) && !execution.retrySuccessId;
|
||||||
}
|
}
|
||||||
|
|
||||||
function openInNewTab(executionId: string, workflowId: string) {
|
function openExecutionInNewTab(executionId: string, workflowId: string): void {
|
||||||
const route = router.resolve({
|
const route = router.resolve({
|
||||||
name: VIEWS.EXECUTION_PREVIEW,
|
name: VIEWS.EXECUTION_PREVIEW,
|
||||||
params: { name: workflowId, executionId },
|
params: { name: workflowId, executionId },
|
||||||
});
|
});
|
||||||
|
|
||||||
window.open(route.href, '_blank');
|
window.open(route.href, '_blank');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function openExecutionById(executionId: string): Promise<void> {
|
function openRelatedExecution(
|
||||||
try {
|
metadata: { parentExecution?: RelatedExecution; subExecution?: RelatedExecution },
|
||||||
const execution = (await executionsStore.fetchExecution(executionId)) as ExecutionSummary;
|
view: IRunDataDisplayMode,
|
||||||
|
) {
|
||||||
openInNewTab(executionId, execution.workflowId);
|
const info = metadata.parentExecution || metadata.subExecution;
|
||||||
} catch (e) {
|
if (!info) {
|
||||||
toast.showMessage({
|
|
||||||
type: 'error',
|
|
||||||
message: i18n.baseText('nodeView.showError.openExecution.title'),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function openExecutionInNewTab(executionId: string, workflowId?: string): void {
|
|
||||||
// todo this does not work when workflowId is not set
|
|
||||||
if (!workflowId) {
|
|
||||||
void openExecutionById(executionId);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
openInNewTab(executionId, workflowId);
|
openExecutionInNewTab(info.executionId, info.workflowId);
|
||||||
|
|
||||||
|
telemetry.track(
|
||||||
|
metadata.parentExecution
|
||||||
|
? 'User clicked parent execution button'
|
||||||
|
: 'User clicked inspect sub-workflow',
|
||||||
|
{
|
||||||
|
view,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -112,5 +110,6 @@ export function useExecutionHelpers() {
|
||||||
formatDate,
|
formatDate,
|
||||||
isExecutionRetriable,
|
isExecutionRetriable,
|
||||||
openExecutionInNewTab,
|
openExecutionInNewTab,
|
||||||
|
openRelatedExecution,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,6 +211,7 @@ export class ExecuteWorkflow implements INodeType {
|
||||||
const items = this.getInputData();
|
const items = this.getInputData();
|
||||||
|
|
||||||
const workflowProxy = this.getWorkflowDataProxy(0);
|
const workflowProxy = this.getWorkflowDataProxy(0);
|
||||||
|
const currentWorkflowId = workflowProxy.$workflow.id as string;
|
||||||
|
|
||||||
if (mode === 'each') {
|
if (mode === 'each') {
|
||||||
const returnData: INodeExecutionData[][] = [];
|
const returnData: INodeExecutionData[][] = [];
|
||||||
|
@ -244,8 +245,10 @@ export class ExecuteWorkflow implements INodeType {
|
||||||
for (const item of outputData) {
|
for (const item of outputData) {
|
||||||
item.pairedItem = { item: i };
|
item.pairedItem = { item: i };
|
||||||
item.metadata = {
|
item.metadata = {
|
||||||
executionId: executionResult.executionId,
|
subExecution: {
|
||||||
workflowId: workflowInfo.id,
|
executionId: executionResult.executionId,
|
||||||
|
workflowId: workflowInfo.id ?? currentWorkflowId,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,7 +281,10 @@ export class ExecuteWorkflow implements INodeType {
|
||||||
returnData[0].push({
|
returnData[0].push({
|
||||||
...items[i],
|
...items[i],
|
||||||
metadata: {
|
metadata: {
|
||||||
executionId: executionResult.executionId,
|
subExecution: {
|
||||||
|
workflowId: workflowInfo.id ?? currentWorkflowId,
|
||||||
|
executionId: executionResult.executionId,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1215,8 +1215,7 @@ export interface INodeExecutionData {
|
||||||
error?: NodeApiError | NodeOperationError;
|
error?: NodeApiError | NodeOperationError;
|
||||||
pairedItem?: IPairedItemData | IPairedItemData[] | number;
|
pairedItem?: IPairedItemData | IPairedItemData[] | number;
|
||||||
metadata?: {
|
metadata?: {
|
||||||
executionId?: string;
|
subExecution: RelatedExecution;
|
||||||
workflowId?: string;
|
|
||||||
};
|
};
|
||||||
index?: number;
|
index?: number;
|
||||||
}
|
}
|
||||||
|
@ -2142,16 +2141,15 @@ export interface ITaskSubRunMetadata {
|
||||||
runIndex: number;
|
runIndex: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface RelatedExecution {
|
||||||
|
executionId: string;
|
||||||
|
workflowId: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ITaskMetadata {
|
export interface ITaskMetadata {
|
||||||
parentExecution?: {
|
|
||||||
executionId: string;
|
|
||||||
workflowId: string;
|
|
||||||
};
|
|
||||||
subExecution?: {
|
|
||||||
executionId: string;
|
|
||||||
workflowId: string;
|
|
||||||
};
|
|
||||||
subRun?: ITaskSubRunMetadata[];
|
subRun?: ITaskSubRunMetadata[];
|
||||||
|
parentExecution?: RelatedExecution;
|
||||||
|
subExecution?: RelatedExecution;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The data that gets returned when a node runs
|
// The data that gets returned when a node runs
|
||||||
|
|
Loading…
Reference in a new issue