mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
fix(editor): Fix various typecheck issues (no-changelog) (#8739)
This commit is contained in:
@@ -34,7 +34,7 @@ import {
|
|||||||
type INodeListSearchItems,
|
type INodeListSearchItems,
|
||||||
type NodeParameterValueType,
|
type NodeParameterValueType,
|
||||||
type IDisplayOptions,
|
type IDisplayOptions,
|
||||||
type IExecutionsSummary,
|
type ExecutionSummary,
|
||||||
type FeatureFlags,
|
type FeatureFlags,
|
||||||
type ExecutionStatus,
|
type ExecutionStatus,
|
||||||
type ITelemetryTrackProperties,
|
type ITelemetryTrackProperties,
|
||||||
@@ -53,6 +53,7 @@ import type { BulkCommand, Undoable } from '@/models/history';
|
|||||||
import type { PartialBy, TupleToUnion } from '@/utils/typeHelpers';
|
import type { PartialBy, TupleToUnion } from '@/utils/typeHelpers';
|
||||||
import type { Component } from 'vue';
|
import type { Component } from 'vue';
|
||||||
import type { Scope } from '@n8n/permissions';
|
import type { Scope } from '@n8n/permissions';
|
||||||
|
import type { NotificationOptions as ElementNotificationOptions } from 'element-plus';
|
||||||
|
|
||||||
export * from 'n8n-design-system/types';
|
export * from 'n8n-design-system/types';
|
||||||
|
|
||||||
@@ -395,7 +396,7 @@ export interface IExecutionShortResponse {
|
|||||||
|
|
||||||
export interface IExecutionsListResponse {
|
export interface IExecutionsListResponse {
|
||||||
count: number;
|
count: number;
|
||||||
results: IExecutionsSummary[];
|
results: ExecutionSummary[];
|
||||||
estimated: boolean;
|
estimated: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1061,8 +1062,8 @@ export interface IUsedCredential {
|
|||||||
export interface WorkflowsState {
|
export interface WorkflowsState {
|
||||||
activeExecutions: IExecutionsCurrentSummaryExtended[];
|
activeExecutions: IExecutionsCurrentSummaryExtended[];
|
||||||
activeWorkflows: string[];
|
activeWorkflows: string[];
|
||||||
activeWorkflowExecution: IExecutionsSummary | null;
|
activeWorkflowExecution: ExecutionSummary | null;
|
||||||
currentWorkflowExecutions: IExecutionsSummary[];
|
currentWorkflowExecutions: ExecutionSummary[];
|
||||||
activeExecutionId: string | null;
|
activeExecutionId: string | null;
|
||||||
executingNode: string[];
|
executingNode: string[];
|
||||||
executionWaitingForWebhook: boolean;
|
executionWaitingForWebhook: boolean;
|
||||||
@@ -1189,9 +1190,9 @@ export type ModalState = {
|
|||||||
httpNodeParameters?: string;
|
httpNodeParameters?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type NewCredentialsModal = ModalState & {
|
export interface NewCredentialsModal extends ModalState {
|
||||||
showAuthSelector?: boolean;
|
showAuthSelector?: boolean;
|
||||||
};
|
}
|
||||||
|
|
||||||
export type IRunDataDisplayMode = 'table' | 'json' | 'binary' | 'schema' | 'html' | 'ai';
|
export type IRunDataDisplayMode = 'table' | 'json' | 'binary' | 'schema' | 'html' | 'ai';
|
||||||
export type NodePanelType = 'input' | 'output';
|
export type NodePanelType = 'input' | 'output';
|
||||||
@@ -1240,6 +1241,10 @@ export interface NDVState {
|
|||||||
isMappingOnboarded: boolean;
|
isMappingOnboarded: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface NotificationOptions extends Partial<ElementNotificationOptions> {
|
||||||
|
message: string | ElementNotificationOptions['message'];
|
||||||
|
}
|
||||||
|
|
||||||
export interface UIState {
|
export interface UIState {
|
||||||
activeActions: string[];
|
activeActions: string[];
|
||||||
activeCredentialType: string | null;
|
activeCredentialType: string | null;
|
||||||
@@ -1398,8 +1403,8 @@ export interface IUsersState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IWorkflowsState {
|
export interface IWorkflowsState {
|
||||||
currentWorkflowExecutions: IExecutionsSummary[];
|
currentWorkflowExecutions: ExecutionSummary[];
|
||||||
activeWorkflowExecution: IExecutionsSummary | null;
|
activeWorkflowExecution: ExecutionSummary | null;
|
||||||
finishedExecutionsCount: number;
|
finishedExecutionsCount: number;
|
||||||
}
|
}
|
||||||
export interface IWorkflowsMap {
|
export interface IWorkflowsMap {
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ import type {
|
|||||||
ExecutionFilterType,
|
ExecutionFilterType,
|
||||||
ExecutionsQueryFilter,
|
ExecutionsQueryFilter,
|
||||||
} from '@/Interface';
|
} from '@/Interface';
|
||||||
import type { IExecutionsSummary, ExecutionStatus } from 'n8n-workflow';
|
import type { ExecutionSummary, ExecutionStatus } from 'n8n-workflow';
|
||||||
import { range as _range } from 'lodash-es';
|
import { range as _range } from 'lodash-es';
|
||||||
import { useUIStore } from '@/stores/ui.store';
|
import { useUIStore } from '@/stores/ui.store';
|
||||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||||
@@ -342,7 +342,7 @@ export default defineComponent({
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isMounting: true,
|
isMounting: true,
|
||||||
finishedExecutions: [] as IExecutionsSummary[],
|
finishedExecutions: [] as ExecutionSummary[],
|
||||||
finishedExecutionsCount: 0,
|
finishedExecutionsCount: 0,
|
||||||
finishedExecutionsCountEstimated: false,
|
finishedExecutionsCountEstimated: false,
|
||||||
|
|
||||||
@@ -388,8 +388,8 @@ export default defineComponent({
|
|||||||
activeExecutions(): IExecutionsCurrentSummaryExtended[] {
|
activeExecutions(): IExecutionsCurrentSummaryExtended[] {
|
||||||
return this.workflowsStore.activeExecutions;
|
return this.workflowsStore.activeExecutions;
|
||||||
},
|
},
|
||||||
combinedExecutions(): IExecutionsSummary[] {
|
combinedExecutions(): ExecutionSummary[] {
|
||||||
const returnData: IExecutionsSummary[] = [];
|
const returnData: ExecutionSummary[] = [];
|
||||||
|
|
||||||
if (['all', 'running'].includes(this.filter.status)) {
|
if (['all', 'running'].includes(this.filter.status)) {
|
||||||
returnData.push(...this.activeExecutions);
|
returnData.push(...this.activeExecutions);
|
||||||
@@ -428,7 +428,7 @@ export default defineComponent({
|
|||||||
closeDialog() {
|
closeDialog() {
|
||||||
this.$emit('closeModal');
|
this.$emit('closeModal');
|
||||||
},
|
},
|
||||||
displayExecution(execution: IExecutionsSummary) {
|
displayExecution(execution: ExecutionSummary) {
|
||||||
const route = this.$router.resolve({
|
const route = this.$router.resolve({
|
||||||
name: VIEWS.EXECUTION_PREVIEW,
|
name: VIEWS.EXECUTION_PREVIEW,
|
||||||
params: { name: execution.workflowId, executionId: execution.id },
|
params: { name: execution.workflowId, executionId: execution.id },
|
||||||
@@ -529,7 +529,7 @@ export default defineComponent({
|
|||||||
this.handleClearSelection();
|
this.handleClearSelection();
|
||||||
this.isMounting = false;
|
this.isMounting = false;
|
||||||
},
|
},
|
||||||
async handleActionItemClick(commandData: { command: string; execution: IExecutionsSummary }) {
|
async handleActionItemClick(commandData: { command: string; execution: ExecutionSummary }) {
|
||||||
if (['currentlySaved', 'original'].includes(commandData.command)) {
|
if (['currentlySaved', 'original'].includes(commandData.command)) {
|
||||||
let loadWorkflow = false;
|
let loadWorkflow = false;
|
||||||
if (commandData.command === 'currentlySaved') {
|
if (commandData.command === 'currentlySaved') {
|
||||||
@@ -747,7 +747,7 @@ export default defineComponent({
|
|||||||
this.showError(error, this.i18n.baseText('executionsList.showError.loadWorkflows.title'));
|
this.showError(error, this.i18n.baseText('executionsList.showError.loadWorkflows.title'));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async retryExecution(execution: IExecutionsSummary, loadWorkflow?: boolean) {
|
async retryExecution(execution: ExecutionSummary, loadWorkflow?: boolean) {
|
||||||
this.isDataLoading = true;
|
this.isDataLoading = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -786,7 +786,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
this.isDataLoading = false;
|
this.isDataLoading = false;
|
||||||
},
|
},
|
||||||
getStatus(execution: IExecutionsSummary): ExecutionStatus {
|
getStatus(execution: ExecutionSummary): ExecutionStatus {
|
||||||
if (execution.status) {
|
if (execution.status) {
|
||||||
return execution.status;
|
return execution.status;
|
||||||
} else {
|
} else {
|
||||||
@@ -806,10 +806,10 @@ export default defineComponent({
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getRowClass(execution: IExecutionsSummary): string {
|
getRowClass(execution: ExecutionSummary): string {
|
||||||
return [this.$style.execRow, this.$style[this.getStatus(execution)]].join(' ');
|
return [this.$style.execRow, this.$style[this.getStatus(execution)]].join(' ');
|
||||||
},
|
},
|
||||||
getStatusText(entry: IExecutionsSummary): string {
|
getStatusText(entry: ExecutionSummary): string {
|
||||||
const status = this.getStatus(entry);
|
const status = this.getStatus(entry);
|
||||||
let text = '';
|
let text = '';
|
||||||
|
|
||||||
@@ -833,7 +833,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
getStatusTextTranslationPath(entry: IExecutionsSummary): string {
|
getStatusTextTranslationPath(entry: ExecutionSummary): string {
|
||||||
const status = this.getStatus(entry);
|
const status = this.getStatus(entry);
|
||||||
let path = '';
|
let path = '';
|
||||||
|
|
||||||
@@ -857,7 +857,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
return path;
|
return path;
|
||||||
},
|
},
|
||||||
getStatusTooltipText(entry: IExecutionsSummary): string {
|
getStatusTooltipText(entry: ExecutionSummary): string {
|
||||||
const status = this.getStatus(entry);
|
const status = this.getStatus(entry);
|
||||||
let text = '';
|
let text = '';
|
||||||
|
|
||||||
@@ -894,7 +894,7 @@ export default defineComponent({
|
|||||||
this.showError(error, this.i18n.baseText('executionsList.showError.stopExecution.title'));
|
this.showError(error, this.i18n.baseText('executionsList.showError.stopExecution.title'));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
isExecutionRetriable(execution: IExecutionsSummary): boolean {
|
isExecutionRetriable(execution: ExecutionSummary): boolean {
|
||||||
return (
|
return (
|
||||||
execution.stoppedAt !== undefined &&
|
execution.stoppedAt !== undefined &&
|
||||||
!execution.finished &&
|
!execution.finished &&
|
||||||
@@ -903,7 +903,7 @@ export default defineComponent({
|
|||||||
!execution.waitTill
|
!execution.waitTill
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
async deleteExecution(execution: IExecutionsSummary) {
|
async deleteExecution(execution: ExecutionSummary) {
|
||||||
this.isDataLoading = true;
|
this.isDataLoading = true;
|
||||||
try {
|
try {
|
||||||
await this.workflowsStore.deleteExecutions({ ids: [execution.id] });
|
await this.workflowsStore.deleteExecutions({ ids: [execution.id] });
|
||||||
@@ -921,17 +921,17 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
this.isDataLoading = true;
|
this.isDataLoading = true;
|
||||||
},
|
},
|
||||||
isWaitTillIndefinite(execution: IExecutionsSummary): boolean {
|
isWaitTillIndefinite(execution: ExecutionSummary): boolean {
|
||||||
if (!execution.waitTill) {
|
if (!execution.waitTill) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return new Date(execution.waitTill).toISOString() === WAIT_TIME_UNLIMITED;
|
return new Date(execution.waitTill).toISOString() === WAIT_TIME_UNLIMITED;
|
||||||
},
|
},
|
||||||
isRunning(execution: IExecutionsSummary): boolean {
|
isRunning(execution: ExecutionSummary): boolean {
|
||||||
return this.getStatus(execution) === 'running';
|
return this.getStatus(execution) === 'running';
|
||||||
},
|
},
|
||||||
selectAllVisibleExecutions() {
|
selectAllVisibleExecutions() {
|
||||||
this.combinedExecutions.forEach((execution: IExecutionsSummary) => {
|
this.combinedExecutions.forEach((execution: ExecutionSummary) => {
|
||||||
this.selectedItems = { ...this.selectedItems, [execution.id]: true };
|
this.selectedItems = { ...this.selectedItems, [execution.id]: true };
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -83,7 +83,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import type { IExecutionsSummary } from '@/Interface';
|
import type { ExecutionSummary } from '@/Interface';
|
||||||
import type { IExecutionUIData } from '@/mixins/executionsHelpers';
|
import type { IExecutionUIData } from '@/mixins/executionsHelpers';
|
||||||
import { executionHelpers } from '@/mixins/executionsHelpers';
|
import { executionHelpers } from '@/mixins/executionsHelpers';
|
||||||
import { VIEWS } from '@/constants';
|
import { VIEWS } from '@/constants';
|
||||||
@@ -97,7 +97,7 @@ export default defineComponent({
|
|||||||
mixins: [executionHelpers],
|
mixins: [executionHelpers],
|
||||||
props: {
|
props: {
|
||||||
execution: {
|
execution: {
|
||||||
type: Object as () => IExecutionsSummary,
|
type: Object as () => ExecutionSummary,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
highlight: {
|
highlight: {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ import type {
|
|||||||
IWorkflowDb,
|
IWorkflowDb,
|
||||||
} from '@/Interface';
|
} from '@/Interface';
|
||||||
import type {
|
import type {
|
||||||
IExecutionsSummary,
|
ExecutionSummary,
|
||||||
IConnection,
|
IConnection,
|
||||||
IConnections,
|
IConnections,
|
||||||
IDataObject,
|
IDataObject,
|
||||||
@@ -100,7 +100,7 @@ export default defineComponent({
|
|||||||
loading: false,
|
loading: false,
|
||||||
loadingMore: false,
|
loadingMore: false,
|
||||||
filter: {} as ExecutionFilterType,
|
filter: {} as ExecutionFilterType,
|
||||||
temporaryExecution: null as IExecutionsSummary | null,
|
temporaryExecution: null as ExecutionSummary | null,
|
||||||
autoRefresh: false,
|
autoRefresh: false,
|
||||||
autoRefreshTimeout: undefined as undefined | NodeJS.Timer,
|
autoRefreshTimeout: undefined as undefined | NodeJS.Timer,
|
||||||
};
|
};
|
||||||
@@ -284,7 +284,7 @@ export default defineComponent({
|
|||||||
this.loading = true;
|
this.loading = true;
|
||||||
try {
|
try {
|
||||||
const executionIndex = this.executions.findIndex(
|
const executionIndex = this.executions.findIndex(
|
||||||
(execution: IExecutionsSummary) => execution.id === this.$route.params.executionId,
|
(execution: ExecutionSummary) => execution.id === this.$route.params.executionId,
|
||||||
);
|
);
|
||||||
const nextExecution =
|
const nextExecution =
|
||||||
this.executions[executionIndex + 1] ||
|
this.executions[executionIndex + 1] ||
|
||||||
@@ -388,8 +388,8 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
async loadAutoRefresh(): Promise<void> {
|
async loadAutoRefresh(): Promise<void> {
|
||||||
// Most of the auto-refresh logic is taken from the `ExecutionsList` component
|
// Most of the auto-refresh logic is taken from the `ExecutionsList` component
|
||||||
const fetchedExecutions: IExecutionsSummary[] = await this.loadExecutions();
|
const fetchedExecutions: ExecutionSummary[] = await this.loadExecutions();
|
||||||
let existingExecutions: IExecutionsSummary[] = [...this.executions];
|
let existingExecutions: ExecutionSummary[] = [...this.executions];
|
||||||
const alreadyPresentExecutionIds = existingExecutions.map((exec) => parseInt(exec.id, 10));
|
const alreadyPresentExecutionIds = existingExecutions.map((exec) => parseInt(exec.id, 10));
|
||||||
let lastId = 0;
|
let lastId = 0;
|
||||||
const gaps = [] as number[];
|
const gaps = [] as number[];
|
||||||
@@ -465,7 +465,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async loadExecutions(): Promise<IExecutionsSummary[]> {
|
async loadExecutions(): Promise<ExecutionSummary[]> {
|
||||||
if (!this.currentWorkflow) {
|
if (!this.currentWorkflow) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -536,7 +536,7 @@ export default defineComponent({
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
this.temporaryExecution = existingExecution as IExecutionsSummary;
|
this.temporaryExecution = existingExecution as ExecutionSummary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// stop if the execution wasn't found in the first 1000 lookups
|
// stop if the execution wasn't found in the first 1000 lookups
|
||||||
@@ -716,7 +716,7 @@ export default defineComponent({
|
|||||||
async loadActiveWorkflows(): Promise<void> {
|
async loadActiveWorkflows(): Promise<void> {
|
||||||
await this.workflowsStore.fetchActiveWorkflows();
|
await this.workflowsStore.fetchActiveWorkflows();
|
||||||
},
|
},
|
||||||
async onRetryExecution(payload: { execution: IExecutionsSummary; command: string }) {
|
async onRetryExecution(payload: { execution: ExecutionSummary; command: string }) {
|
||||||
const loadWorkflow = payload.command === 'current-workflow';
|
const loadWorkflow = payload.command === 'current-workflow';
|
||||||
|
|
||||||
this.showMessage({
|
this.showMessage({
|
||||||
@@ -733,7 +733,7 @@ export default defineComponent({
|
|||||||
retry_type: loadWorkflow ? 'current' : 'original',
|
retry_type: loadWorkflow ? 'current' : 'original',
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
async retryExecution(execution: IExecutionsSummary, loadWorkflow?: boolean) {
|
async retryExecution(execution: ExecutionSummary, loadWorkflow?: boolean) {
|
||||||
try {
|
try {
|
||||||
const retrySuccessful = await this.workflowsStore.retryExecution(
|
const retrySuccessful = await this.workflowsStore.retryExecution(
|
||||||
execution.id,
|
execution.id,
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ import ExecutionCard from '@/components/ExecutionsView/ExecutionCard.vue';
|
|||||||
import ExecutionsInfoAccordion from '@/components/ExecutionsView/ExecutionsInfoAccordion.vue';
|
import ExecutionsInfoAccordion from '@/components/ExecutionsView/ExecutionsInfoAccordion.vue';
|
||||||
import ExecutionFilter from '@/components/ExecutionFilter.vue';
|
import ExecutionFilter from '@/components/ExecutionFilter.vue';
|
||||||
import { VIEWS } from '@/constants';
|
import { VIEWS } from '@/constants';
|
||||||
import type { IExecutionsSummary } from 'n8n-workflow';
|
import type { ExecutionSummary } from 'n8n-workflow';
|
||||||
import type { Route } from 'vue-router';
|
import type { Route } from 'vue-router';
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import type { PropType } from 'vue';
|
import type { PropType } from 'vue';
|
||||||
@@ -88,7 +88,7 @@ export default defineComponent({
|
|||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
executions: {
|
executions: {
|
||||||
type: Array as PropType<IExecutionsSummary[]>,
|
type: Array as PropType<ExecutionSummary[]>,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
loading: {
|
loading: {
|
||||||
@@ -100,7 +100,7 @@ export default defineComponent({
|
|||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
temporaryExecution: {
|
temporaryExecution: {
|
||||||
type: Object as PropType<IExecutionsSummary>,
|
type: Object as PropType<ExecutionSummary>,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import userEvent from '@testing-library/user-event';
|
|||||||
import { faker } from '@faker-js/faker';
|
import { faker } from '@faker-js/faker';
|
||||||
import { createRouter, createWebHistory } from 'vue-router';
|
import { createRouter, createWebHistory } from 'vue-router';
|
||||||
import { createPinia, PiniaVuePlugin, setActivePinia } from 'pinia';
|
import { createPinia, PiniaVuePlugin, setActivePinia } from 'pinia';
|
||||||
import type { IExecutionsSummary } from 'n8n-workflow';
|
import type { ExecutionSummary } from 'n8n-workflow';
|
||||||
import { useSettingsStore } from '@/stores/settings.store';
|
import { useSettingsStore } from '@/stores/settings.store';
|
||||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||||
import ExecutionPreview from '@/components/ExecutionsView/ExecutionPreview.vue';
|
import ExecutionPreview from '@/components/ExecutionsView/ExecutionPreview.vue';
|
||||||
@@ -48,7 +48,7 @@ const generateUndefinedNullOrString = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const executionDataFactory = (): IExecutionsSummary => ({
|
const executionDataFactory = (): ExecutionSummary => ({
|
||||||
id: faker.string.uuid(),
|
id: faker.string.uuid(),
|
||||||
finished: faker.datatype.boolean(),
|
finished: faker.datatype.boolean(),
|
||||||
mode: faker.helpers.arrayElement(['manual', 'trigger']),
|
mode: faker.helpers.arrayElement(['manual', 'trigger']),
|
||||||
@@ -65,7 +65,7 @@ const executionDataFactory = (): IExecutionsSummary => ({
|
|||||||
describe('ExecutionPreview.vue', () => {
|
describe('ExecutionPreview.vue', () => {
|
||||||
let workflowsStore: ReturnType<typeof useWorkflowsStore>;
|
let workflowsStore: ReturnType<typeof useWorkflowsStore>;
|
||||||
let settingsStore: ReturnType<typeof useSettingsStore>;
|
let settingsStore: ReturnType<typeof useSettingsStore>;
|
||||||
const executionData: IExecutionsSummary = executionDataFactory();
|
const executionData: ExecutionSummary = executionDataFactory();
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
pinia = createPinia();
|
pinia = createPinia();
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import type { Route, RouteLocationRaw } from 'vue-router';
|
import type { Route, RouteLocationRaw } from 'vue-router';
|
||||||
import { mapStores } from 'pinia';
|
import { mapStores } from 'pinia';
|
||||||
import type { IExecutionsSummary } from 'n8n-workflow';
|
import type { ExecutionSummary } from 'n8n-workflow';
|
||||||
import { pushConnection } from '@/mixins/pushConnection';
|
import { pushConnection } from '@/mixins/pushConnection';
|
||||||
import WorkflowDetails from '@/components/MainHeader/WorkflowDetails.vue';
|
import WorkflowDetails from '@/components/MainHeader/WorkflowDetails.vue';
|
||||||
import TabBar from '@/components/MainHeader/TabBar.vue';
|
import TabBar from '@/components/MainHeader/TabBar.vue';
|
||||||
@@ -79,8 +79,8 @@ export default defineComponent({
|
|||||||
(this.$route.meta.nodeView || this.$route.meta.keepWorkflowAlive === true)
|
(this.$route.meta.nodeView || this.$route.meta.keepWorkflowAlive === true)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
activeExecution(): IExecutionsSummary {
|
activeExecution(): ExecutionSummary {
|
||||||
return this.workflowsStore.activeWorkflowExecution as IExecutionsSummary;
|
return this.workflowsStore.activeWorkflowExecution as ExecutionSummary;
|
||||||
},
|
},
|
||||||
readOnly(): boolean {
|
readOnly(): boolean {
|
||||||
return this.sourceControlStore.preferences.branchReadOnly;
|
return this.sourceControlStore.preferences.branchReadOnly;
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ import {
|
|||||||
import { nodeBase } from '@/mixins/nodeBase';
|
import { nodeBase } from '@/mixins/nodeBase';
|
||||||
import type {
|
import type {
|
||||||
ConnectionTypes,
|
ConnectionTypes,
|
||||||
IExecutionsSummary,
|
ExecutionSummary,
|
||||||
INodeInputConfiguration,
|
INodeInputConfiguration,
|
||||||
INodeOutputConfiguration,
|
INodeOutputConfiguration,
|
||||||
INodeTypeDescription,
|
INodeTypeDescription,
|
||||||
@@ -494,7 +494,7 @@ export default defineComponent({
|
|||||||
return this.data.name;
|
return this.data.name;
|
||||||
},
|
},
|
||||||
waiting(): string | undefined {
|
waiting(): string | undefined {
|
||||||
const workflowExecution = this.workflowsStore.getWorkflowExecution as IExecutionsSummary;
|
const workflowExecution = this.workflowsStore.getWorkflowExecution as ExecutionSummary;
|
||||||
|
|
||||||
if (workflowExecution?.waitTill) {
|
if (workflowExecution?.waitTill) {
|
||||||
const lastNodeExecuted = get(workflowExecution, 'data.resultData.lastNodeExecuted');
|
const lastNodeExecuted = get(workflowExecution, 'data.resultData.lastNodeExecuted');
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { faker } from '@faker-js/faker';
|
|||||||
import { STORES, VIEWS } from '@/constants';
|
import { STORES, VIEWS } from '@/constants';
|
||||||
import ExecutionsList from '@/components/ExecutionsList.vue';
|
import ExecutionsList from '@/components/ExecutionsList.vue';
|
||||||
import type { IWorkflowDb } from '@/Interface';
|
import type { IWorkflowDb } from '@/Interface';
|
||||||
import type { IExecutionsSummary } from 'n8n-workflow';
|
import type { ExecutionSummary } from 'n8n-workflow';
|
||||||
import { retry, SETTINGS_STORE_DEFAULT_STATE, waitAllPromises } from '@/__tests__/utils';
|
import { retry, SETTINGS_STORE_DEFAULT_STATE, waitAllPromises } from '@/__tests__/utils';
|
||||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||||
import type { RenderOptions } from '@/__tests__/render';
|
import type { RenderOptions } from '@/__tests__/render';
|
||||||
@@ -48,7 +48,7 @@ const workflowDataFactory = (): IWorkflowDb => ({
|
|||||||
versionId: faker.number.int().toString(),
|
versionId: faker.number.int().toString(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const executionDataFactory = (): IExecutionsSummary => ({
|
const executionDataFactory = (): ExecutionSummary => ({
|
||||||
id: faker.string.uuid(),
|
id: faker.string.uuid(),
|
||||||
finished: faker.datatype.boolean(),
|
finished: faker.datatype.boolean(),
|
||||||
mode: faker.helpers.arrayElement(['manual', 'trigger']),
|
mode: faker.helpers.arrayElement(['manual', 'trigger']),
|
||||||
@@ -89,7 +89,7 @@ describe('ExecutionsList.vue', () => {
|
|||||||
let workflowsData: IWorkflowDb[];
|
let workflowsData: IWorkflowDb[];
|
||||||
let executionsData: Array<{
|
let executionsData: Array<{
|
||||||
count: number;
|
count: number;
|
||||||
results: IExecutionsSummary[];
|
results: ExecutionSummary[];
|
||||||
estimated: boolean;
|
estimated: boolean;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { vi } from 'vitest';
|
import { vi } from 'vitest';
|
||||||
import { createPinia, setActivePinia } from 'pinia';
|
import { createPinia, setActivePinia } from 'pinia';
|
||||||
import { waitFor } from '@testing-library/vue';
|
import { waitFor } from '@testing-library/vue';
|
||||||
import type { IExecutionsSummary } from 'n8n-workflow';
|
import type { ExecutionSummary } from 'n8n-workflow';
|
||||||
import { createComponentRenderer } from '@/__tests__/render';
|
import { createComponentRenderer } from '@/__tests__/render';
|
||||||
import type { INodeUi, IWorkflowDb } from '@/Interface';
|
import type { INodeUi, IWorkflowDb } from '@/Interface';
|
||||||
import WorkflowPreview from '@/components/WorkflowPreview.vue';
|
import WorkflowPreview from '@/components/WorkflowPreview.vue';
|
||||||
@@ -152,7 +152,7 @@ describe('WorkflowPreview', () => {
|
|||||||
it('should call also iframe postMessage with "setActiveExecution" if active execution is set', async () => {
|
it('should call also iframe postMessage with "setActiveExecution" if active execution is set', async () => {
|
||||||
vi.spyOn(workflowsStore, 'activeWorkflowExecution', 'get').mockReturnValue({
|
vi.spyOn(workflowsStore, 'activeWorkflowExecution', 'get').mockReturnValue({
|
||||||
id: 'abc',
|
id: 'abc',
|
||||||
} as IExecutionsSummary);
|
} as ExecutionSummary);
|
||||||
|
|
||||||
const executionId = '123';
|
const executionId = '123';
|
||||||
renderComponent({
|
renderComponent({
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ElNotification as Notification } from 'element-plus';
|
import { ElNotification as Notification } from 'element-plus';
|
||||||
import type { NotificationInstance, NotificationOptions, MessageBoxState } from 'element-plus';
|
import type { NotificationHandle, MessageBoxState } from 'element-plus';
|
||||||
|
import type { NotificationOptions } from '@/Interface';
|
||||||
import { sanitizeHtml } from '@/utils/htmlUtils';
|
import { sanitizeHtml } from '@/utils/htmlUtils';
|
||||||
import { useTelemetry } from '@/composables/useTelemetry';
|
import { useTelemetry } from '@/composables/useTelemetry';
|
||||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||||
@@ -8,12 +9,19 @@ import { useI18n } from './useI18n';
|
|||||||
import { useExternalHooks } from './useExternalHooks';
|
import { useExternalHooks } from './useExternalHooks';
|
||||||
import { VIEWS } from '@/constants';
|
import { VIEWS } from '@/constants';
|
||||||
|
|
||||||
|
export interface NotificationErrorWithNodeAndDescription extends Error {
|
||||||
|
node: {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
const messageDefaults: Partial<Omit<NotificationOptions, 'message'>> = {
|
const messageDefaults: Partial<Omit<NotificationOptions, 'message'>> = {
|
||||||
dangerouslyUseHTMLString: true,
|
dangerouslyUseHTMLString: true,
|
||||||
position: 'bottom-right',
|
position: 'bottom-right',
|
||||||
};
|
};
|
||||||
|
|
||||||
const stickyNotificationQueue: NotificationInstance[] = [];
|
const stickyNotificationQueue: NotificationHandle[] = [];
|
||||||
|
|
||||||
export function useToast() {
|
export function useToast() {
|
||||||
const telemetry = useTelemetry();
|
const telemetry = useTelemetry();
|
||||||
@@ -39,7 +47,7 @@ export function useToast() {
|
|||||||
telemetry.track('Instance FE emitted error', {
|
telemetry.track('Instance FE emitted error', {
|
||||||
error_title: messageData.title,
|
error_title: messageData.title,
|
||||||
error_message: messageData.message,
|
error_message: messageData.message,
|
||||||
caused_by_credential: causedByCredential(messageData.message),
|
caused_by_credential: causedByCredential(messageData.message as string),
|
||||||
workflow_id: workflowsStore.workflowId,
|
workflow_id: workflowsStore.workflowId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -59,7 +67,7 @@ export function useToast() {
|
|||||||
dangerouslyUseHTMLString?: boolean;
|
dangerouslyUseHTMLString?: boolean;
|
||||||
}) {
|
}) {
|
||||||
// eslint-disable-next-line prefer-const
|
// eslint-disable-next-line prefer-const
|
||||||
let notification: NotificationInstance;
|
let notification: NotificationHandle;
|
||||||
if (config.closeOnClick) {
|
if (config.closeOnClick) {
|
||||||
const cb = config.onClick;
|
const cb = config.onClick;
|
||||||
config.onClick = () => {
|
config.onClick = () => {
|
||||||
@@ -87,7 +95,7 @@ export function useToast() {
|
|||||||
return notification;
|
return notification;
|
||||||
}
|
}
|
||||||
|
|
||||||
function collapsableDetails({ description, node }: Error) {
|
function collapsableDetails({ description, node }: NotificationErrorWithNodeAndDescription) {
|
||||||
if (!description) return '';
|
if (!description) return '';
|
||||||
|
|
||||||
const errorDescription =
|
const errorDescription =
|
||||||
@@ -116,7 +124,7 @@ export function useToast() {
|
|||||||
message: `
|
message: `
|
||||||
${messageLine}
|
${messageLine}
|
||||||
<i>${error.message}</i>
|
<i>${error.message}</i>
|
||||||
${collapsableDetails(error)}`,
|
${collapsableDetails(error as NotificationErrorWithNodeAndDescription)}`,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
duration: 0,
|
duration: 0,
|
||||||
},
|
},
|
||||||
@@ -138,7 +146,7 @@ export function useToast() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function showAlert(config: NotificationOptions): NotificationInstance {
|
function showAlert(config: NotificationOptions): NotificationHandle {
|
||||||
return Notification(config);
|
return Notification(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import type {
|
|||||||
INodeTypesMaxCount,
|
INodeTypesMaxCount,
|
||||||
INodeUi,
|
INodeUi,
|
||||||
ITag,
|
ITag,
|
||||||
|
IUpdateInformation,
|
||||||
IWorkflowData,
|
IWorkflowData,
|
||||||
IWorkflowDataUpdate,
|
IWorkflowDataUpdate,
|
||||||
IWorkflowDb,
|
IWorkflowDb,
|
||||||
@@ -1021,7 +1022,7 @@ export function useWorkflowHelpers(router: Router) {
|
|||||||
key: 'webhookId',
|
key: 'webhookId',
|
||||||
value: changedNodes[nodeName],
|
value: changedNodes[nodeName],
|
||||||
name: nodeName,
|
name: nodeName,
|
||||||
};
|
} as IUpdateInformation;
|
||||||
workflowsStore.setNodeValue(changes);
|
workflowsStore.setNodeValue(changes);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { defineComponent } from 'vue';
|
|||||||
import { mapStores } from 'pinia';
|
import { mapStores } from 'pinia';
|
||||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||||
import { i18n as locale } from '@/plugins/i18n';
|
import { i18n as locale } from '@/plugins/i18n';
|
||||||
import type { IExecutionsSummary } from 'n8n-workflow';
|
import type { ExecutionSummary } from 'n8n-workflow';
|
||||||
import { convertToDisplayDate } from '@/utils/formatters/dateFormatter';
|
import { convertToDisplayDate } from '@/utils/formatters/dateFormatter';
|
||||||
|
|
||||||
export interface IExecutionUIData {
|
export interface IExecutionUIData {
|
||||||
@@ -24,15 +24,15 @@ export const executionHelpers = defineComponent({
|
|||||||
currentWorkflow(): string {
|
currentWorkflow(): string {
|
||||||
return this.$route.params.name || this.workflowsStore.workflowId;
|
return this.$route.params.name || this.workflowsStore.workflowId;
|
||||||
},
|
},
|
||||||
executions(): IExecutionsSummary[] {
|
executions(): ExecutionSummary[] {
|
||||||
return this.workflowsStore.currentWorkflowExecutions;
|
return this.workflowsStore.currentWorkflowExecutions;
|
||||||
},
|
},
|
||||||
activeExecution(): IExecutionsSummary | null {
|
activeExecution(): ExecutionSummary | null {
|
||||||
return this.workflowsStore.activeWorkflowExecution;
|
return this.workflowsStore.activeWorkflowExecution;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getExecutionUIDetails(execution: IExecutionsSummary): IExecutionUIData {
|
getExecutionUIDetails(execution: ExecutionSummary): IExecutionUIData {
|
||||||
const status = {
|
const status = {
|
||||||
name: 'unknown',
|
name: 'unknown',
|
||||||
startTime: this.formatDate(execution.startedAt),
|
startTime: this.formatDate(execution.startedAt),
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ import type {
|
|||||||
ThemeOption,
|
ThemeOption,
|
||||||
AppliedThemeOption,
|
AppliedThemeOption,
|
||||||
SuggestedTemplates,
|
SuggestedTemplates,
|
||||||
|
NotificationOptions,
|
||||||
|
ModalState,
|
||||||
} from '@/Interface';
|
} from '@/Interface';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { useRootStore } from '@/stores/n8nRoot.store';
|
import { useRootStore } from '@/stores/n8nRoot.store';
|
||||||
@@ -144,7 +146,7 @@ export const useUIStore = defineStore(STORES.UI, {
|
|||||||
mode: '',
|
mode: '',
|
||||||
activeId: null,
|
activeId: null,
|
||||||
showAuthSelector: false,
|
showAuthSelector: false,
|
||||||
},
|
} as ModalState,
|
||||||
},
|
},
|
||||||
modalStack: [],
|
modalStack: [],
|
||||||
sidebarMenuCollapsed: true,
|
sidebarMenuCollapsed: true,
|
||||||
@@ -172,6 +174,7 @@ export const useUIStore = defineStore(STORES.UI, {
|
|||||||
stateIsDirty: false,
|
stateIsDirty: false,
|
||||||
lastSelectedNode: null,
|
lastSelectedNode: null,
|
||||||
lastSelectedNodeOutputIndex: null,
|
lastSelectedNodeOutputIndex: null,
|
||||||
|
lastSelectedNodeEndpointUuid: null,
|
||||||
nodeViewOffsetPosition: [0, 0],
|
nodeViewOffsetPosition: [0, 0],
|
||||||
nodeViewMoveInProgress: false,
|
nodeViewMoveInProgress: false,
|
||||||
selectedNodes: [],
|
selectedNodes: [],
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ import type {
|
|||||||
IConnection,
|
IConnection,
|
||||||
IConnections,
|
IConnections,
|
||||||
IDataObject,
|
IDataObject,
|
||||||
IExecutionsSummary,
|
ExecutionSummary,
|
||||||
INode,
|
INode,
|
||||||
INodeConnections,
|
INodeConnections,
|
||||||
INodeCredentials,
|
INodeCredentials,
|
||||||
@@ -263,11 +263,11 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, {
|
|||||||
return (nodeName: string) => this.executingNode.includes(nodeName);
|
return (nodeName: string) => this.executingNode.includes(nodeName);
|
||||||
},
|
},
|
||||||
// Executions getters
|
// Executions getters
|
||||||
getExecutionDataById(): (id: string) => IExecutionsSummary | undefined {
|
getExecutionDataById(): (id: string) => ExecutionSummary | undefined {
|
||||||
return (id: string): IExecutionsSummary | undefined =>
|
return (id: string): ExecutionSummary | undefined =>
|
||||||
this.currentWorkflowExecutions.find((execution) => execution.id === id);
|
this.currentWorkflowExecutions.find((execution) => execution.id === id);
|
||||||
},
|
},
|
||||||
getAllLoadedFinishedExecutions(): IExecutionsSummary[] {
|
getAllLoadedFinishedExecutions(): ExecutionSummary[] {
|
||||||
return this.currentWorkflowExecutions.filter(
|
return this.currentWorkflowExecutions.filter(
|
||||||
(ex) => ex.finished === true || ex.stoppedAt !== undefined,
|
(ex) => ex.finished === true || ex.stoppedAt !== undefined,
|
||||||
);
|
);
|
||||||
@@ -1366,7 +1366,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, {
|
|||||||
|
|
||||||
async loadCurrentWorkflowExecutions(
|
async loadCurrentWorkflowExecutions(
|
||||||
requestFilter: ExecutionsQueryFilter,
|
requestFilter: ExecutionsQueryFilter,
|
||||||
): Promise<IExecutionsSummary[]> {
|
): Promise<ExecutionSummary[]> {
|
||||||
let activeExecutions = [];
|
let activeExecutions = [];
|
||||||
|
|
||||||
if (!requestFilter.workflowId) {
|
if (!requestFilter.workflowId) {
|
||||||
@@ -1392,11 +1392,11 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, {
|
|||||||
return await getExecutionData(rootStore.getRestApiContext, executionId);
|
return await getExecutionData(rootStore.getRestApiContext, executionId);
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteExecution(execution: IExecutionsSummary): void {
|
deleteExecution(execution: ExecutionSummary): void {
|
||||||
this.currentWorkflowExecutions.splice(this.currentWorkflowExecutions.indexOf(execution), 1);
|
this.currentWorkflowExecutions.splice(this.currentWorkflowExecutions.indexOf(execution), 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
addToCurrentExecutions(executions: IExecutionsSummary[]): void {
|
addToCurrentExecutions(executions: ExecutionSummary[]): void {
|
||||||
executions.forEach((execution) => {
|
executions.forEach((execution) => {
|
||||||
const exists = this.currentWorkflowExecutions.find((ex) => ex.id === execution.id);
|
const exists = this.currentWorkflowExecutions.find((ex) => ex.id === execution.id);
|
||||||
if (!exists && execution.workflowId === this.workflowId) {
|
if (!exists && execution.workflowId === this.workflowId) {
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ import type {
|
|||||||
IConnection,
|
IConnection,
|
||||||
IConnections,
|
IConnections,
|
||||||
IDataObject,
|
IDataObject,
|
||||||
IExecutionsSummary,
|
ExecutionSummary,
|
||||||
INode,
|
INode,
|
||||||
INodeConnections,
|
INodeConnections,
|
||||||
INodeCredentialsDetails,
|
INodeCredentialsDetails,
|
||||||
@@ -1280,7 +1280,7 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((data as IExecutionsSummary).waitTill) {
|
if ((data as ExecutionSummary).waitTill) {
|
||||||
this.showMessage({
|
this.showMessage({
|
||||||
title: this.$locale.baseText('nodeView.thisExecutionHasntFinishedYet'),
|
title: this.$locale.baseText('nodeView.thisExecutionHasntFinishedYet'),
|
||||||
message: `<a data-action="reload">${this.$locale.baseText(
|
message: `<a data-action="reload">${this.$locale.baseText(
|
||||||
|
|||||||
Reference in New Issue
Block a user