feat: update diff loading

This commit is contained in:
Alex Grozav 2024-10-30 15:21:39 +02:00
parent ed2a6a62b7
commit 0a15e85d63
8 changed files with 50 additions and 21 deletions

View file

@ -9,6 +9,7 @@ import type {
import WorkflowPreview from '@/components/WorkflowPreview.vue'; import WorkflowPreview from '@/components/WorkflowPreview.vue';
import WorkflowHistoryListItem from '@/components/WorkflowHistory/WorkflowHistoryListItem.vue'; import WorkflowHistoryListItem from '@/components/WorkflowHistory/WorkflowHistoryListItem.vue';
import { useI18n } from '@/composables/useI18n'; import { useI18n } from '@/composables/useI18n';
import { compareWorkflows } from '@/utils/workflowDiff';
const i18n = useI18n(); const i18n = useI18n();
@ -57,6 +58,14 @@ const workflowDiffPreview = computed<IWorkflowDb | undefined>(() => {
}; };
}); });
const workflowComparison = computed(() => {
if (!workflowVersionPreview.value || !workflowDiffPreview.value) {
return;
}
return compareWorkflows(workflowVersionPreview.value, workflowDiffPreview.value);
});
const actions = computed(() => const actions = computed(() =>
props.isFirstItemShown props.isFirstItemShown
? props.actions.filter((action) => action.value !== 'restore') ? props.actions.filter((action) => action.value !== 'restore')
@ -82,6 +91,7 @@ const onAction = ({
<WorkflowPreview <WorkflowPreview
v-if="props.workflowVersion" v-if="props.workflowVersion"
:workflow="workflowVersionPreview" :workflow="workflowVersionPreview"
:diff="workflowComparison"
:loading="props.isListLoading" :loading="props.isListLoading"
loader-type="spinner" loader-type="spinner"
/> />

View file

@ -4,13 +4,14 @@ import { useI18n } from '@/composables/useI18n';
import { useToast } from '@/composables/useToast'; import { useToast } from '@/composables/useToast';
import type { IWorkflowDb, IWorkflowTemplate } from '@/Interface'; import type { IWorkflowDb, IWorkflowTemplate } from '@/Interface';
import { useExecutionsStore } from '@/stores/executions.store'; import { useExecutionsStore } from '@/stores/executions.store';
import type { WorkflowDiff } from '@/types/workflowDiff.types';
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
id?: string;
loading?: boolean; loading?: boolean;
mode?: 'workflow' | 'execution'; mode?: 'workflow' | 'execution';
workflow?: IWorkflowDb | IWorkflowTemplate['workflow']; workflow?: IWorkflowDb | IWorkflowTemplate['workflow'];
diff?: WorkflowDiff;
executionId?: string; executionId?: string;
executionMode?: string; executionMode?: string;
loaderType?: 'image' | 'spinner'; loaderType?: 'image' | 'spinner';
@ -21,6 +22,7 @@ const props = withDefaults(
loading: false, loading: false,
mode: 'workflow', mode: 'workflow',
workflow: undefined, workflow: undefined,
diff: undefined,
executionId: undefined, executionId: undefined,
executionMode: undefined, executionMode: undefined,
loaderType: 'image', loaderType: 'image',
@ -75,6 +77,16 @@ const loadWorkflow = () => {
}), }),
'*', '*',
); );
if (props.diff) {
iframeRef.value?.contentWindow?.postMessage?.(
JSON.stringify({
command: 'setDiff',
diff: props.diff,
}),
'*',
);
}
} catch (error) { } catch (error) {
toast.showError( toast.showError(
error, error,

View file

@ -85,6 +85,7 @@ import { TelemetryHelpers } from 'n8n-workflow';
import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers'; import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { useSettingsStore } from './settings.store'; import { useSettingsStore } from './settings.store';
import type { WorkflowDiff } from '@/types';
const defaults: Omit<IWorkflowDb, 'id'> & { settings: NonNullable<IWorkflowDb['settings']> } = { const defaults: Omit<IWorkflowDb, 'id'> & { settings: NonNullable<IWorkflowDb['settings']> } = {
name: '', name: '',
@ -140,6 +141,8 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => {
const isInDebugMode = ref(false); const isInDebugMode = ref(false);
const chatMessages = ref<string[]>([]); const chatMessages = ref<string[]>([]);
const workflowDiff = ref<WorkflowDiff | undefined>();
const workflowName = computed(() => workflow.value.name); const workflowName = computed(() => workflow.value.name);
const workflowId = computed(() => workflow.value.id); const workflowId = computed(() => workflow.value.id);
@ -1652,6 +1655,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => {
getWorkflowExecution, getWorkflowExecution,
getTotalFinishedExecutionsCount, getTotalFinishedExecutionsCount,
getPastChatMessages, getPastChatMessages,
workflowDiff,
outgoingConnectionsByNodeName, outgoingConnectionsByNodeName,
incomingConnectionsByNodeName, incomingConnectionsByNodeName,
nodeHasOutputConnection, nodeHasOutputConnection,

View file

@ -1,3 +1,4 @@
export * from './workflowDiff.types';
export * from './canvas'; export * from './canvas';
export * from './externalHooks'; export * from './externalHooks';
export * from './pushConnection'; export * from './pushConnection';

View file

@ -1,8 +1,8 @@
export const enum NodeDiffStatus { export const enum NodeDiffStatus {
EQ, Eq = 'equal',
MODIFIED, Modified = 'modified',
ADDED, Added = 'added',
DELETED, Deleted = 'deleted',
} }
export type WorkflowDiff = Record<string, NodeDiffStatus>; export type WorkflowDiff = Record<string, NodeDiffStatus>;

View file

@ -201,12 +201,12 @@ describe('workflowDiff', () => {
const diff = compareWorkflows(baseWf, targetWf); const diff = compareWorkflows(baseWf, targetWf);
expect(diff).toEqual({ expect(diff).toEqual({
'180ad8e0-c891-4b37-bab3-0a5b306ca48d': NodeDiffStatus.EQ, '180ad8e0-c891-4b37-bab3-0a5b306ca48d': NodeDiffStatus.Eq,
'1cd4ee3f-5692-469c-a658-82483f1ef921': NodeDiffStatus.MODIFIED, '1cd4ee3f-5692-469c-a658-82483f1ef921': NodeDiffStatus.Modified,
'9eedaa9f-7735-4fef-af11-deba888005ac': NodeDiffStatus.MODIFIED, '9eedaa9f-7735-4fef-af11-deba888005ac': NodeDiffStatus.Modified,
'22593885-07ce-49ea-8a6c-ad17d983cada': NodeDiffStatus.ADDED, '22593885-07ce-49ea-8a6c-ad17d983cada': NodeDiffStatus.Added,
'bcf43c50-007f-4d04-a236-a3a1ef628fe2': NodeDiffStatus.ADDED, 'bcf43c50-007f-4d04-a236-a3a1ef628fe2': NodeDiffStatus.Added,
'f8279104-a3e6-4663-b9bc-77fdbc615742': NodeDiffStatus.DELETED, 'f8279104-a3e6-4663-b9bc-77fdbc615742': NodeDiffStatus.Deleted,
}); });
}); });
@ -214,12 +214,12 @@ describe('workflowDiff', () => {
const diff = compareWorkflows(targetWf, baseWf); const diff = compareWorkflows(targetWf, baseWf);
expect(diff).toEqual({ expect(diff).toEqual({
'180ad8e0-c891-4b37-bab3-0a5b306ca48d': NodeDiffStatus.EQ, '180ad8e0-c891-4b37-bab3-0a5b306ca48d': NodeDiffStatus.Eq,
'1cd4ee3f-5692-469c-a658-82483f1ef921': NodeDiffStatus.MODIFIED, '1cd4ee3f-5692-469c-a658-82483f1ef921': NodeDiffStatus.Modified,
'9eedaa9f-7735-4fef-af11-deba888005ac': NodeDiffStatus.MODIFIED, '9eedaa9f-7735-4fef-af11-deba888005ac': NodeDiffStatus.Modified,
'22593885-07ce-49ea-8a6c-ad17d983cada': NodeDiffStatus.DELETED, '22593885-07ce-49ea-8a6c-ad17d983cada': NodeDiffStatus.Deleted,
'bcf43c50-007f-4d04-a236-a3a1ef628fe2': NodeDiffStatus.DELETED, 'bcf43c50-007f-4d04-a236-a3a1ef628fe2': NodeDiffStatus.Deleted,
'f8279104-a3e6-4663-b9bc-77fdbc615742': NodeDiffStatus.ADDED, 'f8279104-a3e6-4663-b9bc-77fdbc615742': NodeDiffStatus.Added,
}); });
}); });
}); });

View file

@ -38,17 +38,17 @@ export function compareWorkflows(
Object.keys(baseNodes).forEach((id) => { Object.keys(baseNodes).forEach((id) => {
if (!targetNodes[id]) { if (!targetNodes[id]) {
diff[id] = NodeDiffStatus.DELETED; diff[id] = NodeDiffStatus.Deleted;
} else if (!nodesEqual(baseNodes[id], targetNodes[id])) { } else if (!nodesEqual(baseNodes[id], targetNodes[id])) {
diff[id] = NodeDiffStatus.MODIFIED; diff[id] = NodeDiffStatus.Modified;
} else { } else {
diff[id] = NodeDiffStatus.EQ; diff[id] = NodeDiffStatus.Eq;
} }
}); });
Object.keys(targetNodes).forEach((id) => { Object.keys(targetNodes).forEach((id) => {
if (!baseNodes[id]) { if (!baseNodes[id]) {
diff[id] = NodeDiffStatus.ADDED; diff[id] = NodeDiffStatus.Added;
} }
}); });

View file

@ -1349,6 +1349,8 @@ async function onPostMessageReceived(messageEvent: MessageEvent) {
executionsStore.activeExecution = (await executionsStore.fetchExecution( executionsStore.activeExecution = (await executionsStore.fetchExecution(
json.executionId, json.executionId,
)) as ExecutionSummary; )) as ExecutionSummary;
} else if (json?.command === 'setDiff') {
workflowsStore.workflowDiff = json.diff;
} }
} catch (e) {} } catch (e) {}
} }