mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
refactor(editor): Migrate WorkflowExecutionsListView.vue
to composition API (no-changelog) (#10198)
This commit is contained in:
parent
3e96b29332
commit
8e960db16c
|
@ -5,10 +5,10 @@
|
||||||
:loading="loading && !executions.length"
|
:loading="loading && !executions.length"
|
||||||
:loading-more="loadingMore"
|
:loading-more="loadingMore"
|
||||||
:temporary-execution="temporaryExecution"
|
:temporary-execution="temporaryExecution"
|
||||||
@update:auto-refresh="$emit('update:auto-refresh', $event)"
|
@update:auto-refresh="emit('update:auto-refresh', $event)"
|
||||||
@reload-executions="$emit('reload')"
|
@reload-executions="emit('reload')"
|
||||||
@filter-updated="$emit('update:filters', $event)"
|
@filter-updated="emit('update:filters', $event)"
|
||||||
@load-more="$emit('load-more')"
|
@load-more="emit('load-more')"
|
||||||
@retry-execution="onRetryExecution"
|
@retry-execution="onRetryExecution"
|
||||||
/>
|
/>
|
||||||
<div v-if="!hidePreview" :class="$style.content">
|
<div v-if="!hidePreview" :class="$style.content">
|
||||||
|
@ -23,177 +23,98 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import type { PropType } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { defineComponent } from 'vue';
|
import { onBeforeRouteLeave, useRouter } from 'vue-router';
|
||||||
import { mapStores } from 'pinia';
|
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
import WorkflowExecutionsSidebar from '@/components/executions/workflow/WorkflowExecutionsSidebar.vue';
|
import WorkflowExecutionsSidebar from '@/components/executions/workflow/WorkflowExecutionsSidebar.vue';
|
||||||
import {
|
import { MAIN_HEADER_TABS, VIEWS } from '@/constants';
|
||||||
MAIN_HEADER_TABS,
|
|
||||||
MODAL_CANCEL,
|
|
||||||
MODAL_CONFIRM,
|
|
||||||
PLACEHOLDER_EMPTY_WORKFLOW_ID,
|
|
||||||
VIEWS,
|
|
||||||
} from '@/constants';
|
|
||||||
import type { ExecutionFilterType, IWorkflowDb } from '@/Interface';
|
import type { ExecutionFilterType, IWorkflowDb } from '@/Interface';
|
||||||
import type { ExecutionSummary, IDataObject } from 'n8n-workflow';
|
import type { ExecutionSummary } from 'n8n-workflow';
|
||||||
import { useMessage } from '@/composables/useMessage';
|
|
||||||
import { useToast } from '@/composables/useToast';
|
|
||||||
import { getNodeViewTab } from '@/utils/canvasUtils';
|
import { getNodeViewTab } from '@/utils/canvasUtils';
|
||||||
import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers';
|
import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers';
|
||||||
import { useUIStore } from '@/stores/ui.store';
|
import { watch } from 'vue';
|
||||||
import { useSettingsStore } from '@/stores/settings.store';
|
|
||||||
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
|
||||||
import { useTagsStore } from '@/stores/tags.store';
|
|
||||||
import { executionFilterToQueryFilter } from '@/utils/executionUtils';
|
|
||||||
import { useExternalHooks } from '@/composables/useExternalHooks';
|
|
||||||
import { useDebounce } from '@/composables/useDebounce';
|
|
||||||
import { useNpsSurveyStore } from '@/stores/npsSurvey.store';
|
|
||||||
|
|
||||||
export default defineComponent({
|
const props = withDefaults(
|
||||||
name: 'WorkflowExecutionsList',
|
defineProps<{
|
||||||
components: {
|
loading: boolean;
|
||||||
WorkflowExecutionsSidebar,
|
workflow: IWorkflowDb;
|
||||||
|
executions: ExecutionSummary[];
|
||||||
|
execution?: ExecutionSummary;
|
||||||
|
loadingMore: boolean;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
loading: false,
|
||||||
|
executions: () => [] as ExecutionSummary[],
|
||||||
|
loadingMore: false,
|
||||||
},
|
},
|
||||||
async beforeRouteLeave(to, _, next) {
|
);
|
||||||
if (getNodeViewTab(to) === MAIN_HEADER_TABS.WORKFLOW) {
|
|
||||||
next();
|
const emit = defineEmits<{
|
||||||
|
'execution:delete': [value: string];
|
||||||
|
'execution:stop': [value: string];
|
||||||
|
'execution:retry': [value: { id: string; loadWorkflow: boolean }];
|
||||||
|
'update:auto-refresh': [value: boolean];
|
||||||
|
'update:filters': [value: ExecutionFilterType];
|
||||||
|
'load-more': [];
|
||||||
|
reload: [];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const workflowHelpers = useWorkflowHelpers({ router: useRouter() });
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const temporaryExecution = computed(() => {
|
||||||
|
const isTemporary = !props.executions.find((execution) => execution.id === props.execution?.id);
|
||||||
|
return isTemporary ? props.execution : undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
const hidePreview = computed(() => {
|
||||||
|
return props.loading || (!props.execution && props.executions.length);
|
||||||
|
});
|
||||||
|
|
||||||
|
const onDeleteCurrentExecution = () => {
|
||||||
|
if (!props.execution?.id) return;
|
||||||
|
|
||||||
|
emit('execution:delete', props.execution.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onStopExecution = () => {
|
||||||
|
if (!props.execution?.id) return;
|
||||||
|
|
||||||
|
emit('execution:stop', props.execution.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onRetryExecution = (payload: { execution: ExecutionSummary; command: string }) => {
|
||||||
|
const loadWorkflow = payload.command === 'current-workflow';
|
||||||
|
|
||||||
|
emit('execution:retry', {
|
||||||
|
id: payload.execution.id,
|
||||||
|
loadWorkflow,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.execution,
|
||||||
|
(value: ExecutionSummary | undefined) => {
|
||||||
|
if (!value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.uiStore.stateIsDirty) {
|
router
|
||||||
const confirmModal = await this.confirm(
|
.push({
|
||||||
this.$locale.baseText('generic.unsavedWork.confirmMessage.message'),
|
name: VIEWS.EXECUTION_PREVIEW,
|
||||||
{
|
params: { name: props.workflow.id, executionId: value.id },
|
||||||
title: this.$locale.baseText('generic.unsavedWork.confirmMessage.headline'),
|
})
|
||||||
type: 'warning',
|
.catch(() => {});
|
||||||
confirmButtonText: this.$locale.baseText(
|
},
|
||||||
'generic.unsavedWork.confirmMessage.confirmButtonText',
|
);
|
||||||
),
|
|
||||||
cancelButtonText: this.$locale.baseText(
|
|
||||||
'generic.unsavedWork.confirmMessage.cancelButtonText',
|
|
||||||
),
|
|
||||||
showClose: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (confirmModal === MODAL_CONFIRM) {
|
onBeforeRouteLeave(async (to, _, next) => {
|
||||||
const saved = await this.workflowHelpers.saveCurrentWorkflow({}, false);
|
if (getNodeViewTab(to) === MAIN_HEADER_TABS.WORKFLOW) {
|
||||||
if (saved) {
|
next();
|
||||||
await this.npsSurveyStore.fetchPromptsData();
|
return;
|
||||||
}
|
}
|
||||||
this.uiStore.stateIsDirty = false;
|
|
||||||
next();
|
|
||||||
} else if (confirmModal === MODAL_CANCEL) {
|
|
||||||
this.uiStore.stateIsDirty = false;
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
loading: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
workflow: {
|
|
||||||
type: Object as PropType<IWorkflowDb>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
executions: {
|
|
||||||
type: Array as PropType<ExecutionSummary[]>,
|
|
||||||
default: () => [],
|
|
||||||
},
|
|
||||||
filters: {
|
|
||||||
type: Object as PropType<ExecutionFilterType>,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
execution: {
|
|
||||||
type: Object as PropType<ExecutionSummary> | null,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
loadingMore: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
emits: [
|
|
||||||
'execution:delete',
|
|
||||||
'execution:stop',
|
|
||||||
'execution:retry',
|
|
||||||
'update:auto-refresh',
|
|
||||||
'update:filters',
|
|
||||||
'load-more',
|
|
||||||
'reload',
|
|
||||||
],
|
|
||||||
setup() {
|
|
||||||
const externalHooks = useExternalHooks();
|
|
||||||
const router = useRouter();
|
|
||||||
const workflowHelpers = useWorkflowHelpers({ router });
|
|
||||||
const { callDebounced } = useDebounce();
|
|
||||||
|
|
||||||
return {
|
await workflowHelpers.promptSaveUnsavedWorkflowChanges(next);
|
||||||
externalHooks,
|
|
||||||
workflowHelpers,
|
|
||||||
callDebounced,
|
|
||||||
...useToast(),
|
|
||||||
...useMessage(),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapStores(useTagsStore, useNodeTypesStore, useSettingsStore, useUIStore, useNpsSurveyStore),
|
|
||||||
temporaryExecution(): ExecutionSummary | undefined {
|
|
||||||
const isTemporary = !this.executions.find((execution) => execution.id === this.execution?.id);
|
|
||||||
return isTemporary ? this.execution : undefined;
|
|
||||||
},
|
|
||||||
hidePreview(): boolean {
|
|
||||||
return this.loading || (!this.execution && this.executions.length);
|
|
||||||
},
|
|
||||||
filterApplied(): boolean {
|
|
||||||
return this.filters.status !== 'all';
|
|
||||||
},
|
|
||||||
workflowDataNotLoaded(): boolean {
|
|
||||||
return this.workflow.id === PLACEHOLDER_EMPTY_WORKFLOW_ID && this.workflow.name === '';
|
|
||||||
},
|
|
||||||
requestFilter(): IDataObject {
|
|
||||||
return executionFilterToQueryFilter({
|
|
||||||
...this.filters,
|
|
||||||
workflowId: this.workflow.id,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
execution(value: ExecutionSummary) {
|
|
||||||
if (!value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$router
|
|
||||||
.push({
|
|
||||||
name: VIEWS.EXECUTION_PREVIEW,
|
|
||||||
params: { name: this.workflow.id, executionId: value.id },
|
|
||||||
})
|
|
||||||
.catch(() => {});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async onDeleteCurrentExecution(): Promise<void> {
|
|
||||||
this.$emit('execution:delete', this.execution?.id);
|
|
||||||
},
|
|
||||||
async onStopExecution(): Promise<void> {
|
|
||||||
this.$emit('execution:stop', this.execution?.id);
|
|
||||||
},
|
|
||||||
async onRetryExecution(payload: { execution: ExecutionSummary; command: string }) {
|
|
||||||
const loadWorkflow = payload.command === 'current-workflow';
|
|
||||||
|
|
||||||
this.$emit('execution:retry', {
|
|
||||||
id: payload.execution.id,
|
|
||||||
loadWorkflow,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ import { PLACEHOLDER_EMPTY_WORKFLOW_ID, VIEWS } from '@/constants';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import type { ExecutionSummary } from 'n8n-workflow';
|
import type { ExecutionSummary } from 'n8n-workflow';
|
||||||
import { useDebounce } from '@/composables/useDebounce';
|
import { useDebounce } from '@/composables/useDebounce';
|
||||||
import { storeToRefs } from 'pinia';
|
|
||||||
import { useTelemetry } from '@/composables/useTelemetry';
|
import { useTelemetry } from '@/composables/useTelemetry';
|
||||||
import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers';
|
import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers';
|
||||||
import { useNodeHelpers } from '@/composables/useNodeHelpers';
|
import { useNodeHelpers } from '@/composables/useNodeHelpers';
|
||||||
|
@ -29,8 +28,6 @@ const { callDebounced } = useDebounce();
|
||||||
const workflowHelpers = useWorkflowHelpers({ router });
|
const workflowHelpers = useWorkflowHelpers({ router });
|
||||||
const nodeHelpers = useNodeHelpers();
|
const nodeHelpers = useNodeHelpers();
|
||||||
|
|
||||||
const { filters } = storeToRefs(executionsStore);
|
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const loadingMore = ref(false);
|
const loadingMore = ref(false);
|
||||||
|
|
||||||
|
@ -311,7 +308,6 @@ async function loadMore(): Promise<void> {
|
||||||
v-if="workflow"
|
v-if="workflow"
|
||||||
:executions="executions"
|
:executions="executions"
|
||||||
:execution="execution"
|
:execution="execution"
|
||||||
:filters="filters"
|
|
||||||
:workflow="workflow"
|
:workflow="workflow"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:loading-more="loadingMore"
|
:loading-more="loadingMore"
|
||||||
|
|
Loading…
Reference in a new issue