refactor(editor): Migrate WorkflowExecutionsListView.vue to composition API (no-changelog) (#10198)

This commit is contained in:
Ricardo Espinoza 2024-07-31 07:11:24 -04:00 committed by GitHub
parent 3e96b29332
commit 8e960db16c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 85 additions and 168 deletions

View file

@ -5,10 +5,10 @@
:loading="loading && !executions.length"
:loading-more="loadingMore"
:temporary-execution="temporaryExecution"
@update:auto-refresh="$emit('update:auto-refresh', $event)"
@reload-executions="$emit('reload')"
@filter-updated="$emit('update:filters', $event)"
@load-more="$emit('load-more')"
@update:auto-refresh="emit('update:auto-refresh', $event)"
@reload-executions="emit('reload')"
@filter-updated="emit('update:filters', $event)"
@load-more="emit('load-more')"
@retry-execution="onRetryExecution"
/>
<div v-if="!hidePreview" :class="$style.content">
@ -23,177 +23,98 @@
</div>
</template>
<script lang="ts">
import type { PropType } from 'vue';
import { defineComponent } from 'vue';
import { mapStores } from 'pinia';
import { useRouter } from 'vue-router';
<script setup lang="ts">
import { computed } from 'vue';
import { onBeforeRouteLeave, useRouter } from 'vue-router';
import WorkflowExecutionsSidebar from '@/components/executions/workflow/WorkflowExecutionsSidebar.vue';
import {
MAIN_HEADER_TABS,
MODAL_CANCEL,
MODAL_CONFIRM,
PLACEHOLDER_EMPTY_WORKFLOW_ID,
VIEWS,
} from '@/constants';
import { MAIN_HEADER_TABS, VIEWS } from '@/constants';
import type { ExecutionFilterType, IWorkflowDb } from '@/Interface';
import type { ExecutionSummary, IDataObject } from 'n8n-workflow';
import { useMessage } from '@/composables/useMessage';
import { useToast } from '@/composables/useToast';
import type { ExecutionSummary } from 'n8n-workflow';
import { getNodeViewTab } from '@/utils/canvasUtils';
import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers';
import { useUIStore } from '@/stores/ui.store';
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';
import { watch } from 'vue';
export default defineComponent({
name: 'WorkflowExecutionsList',
components: {
WorkflowExecutionsSidebar,
const props = withDefaults(
defineProps<{
loading: boolean;
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;
}
if (this.uiStore.stateIsDirty) {
const confirmModal = await this.confirm(
this.$locale.baseText('generic.unsavedWork.confirmMessage.message'),
{
title: this.$locale.baseText('generic.unsavedWork.confirmMessage.headline'),
type: 'warning',
confirmButtonText: this.$locale.baseText(
'generic.unsavedWork.confirmMessage.confirmButtonText',
),
cancelButtonText: this.$locale.baseText(
'generic.unsavedWork.confirmMessage.cancelButtonText',
),
showClose: true,
},
);
router
.push({
name: VIEWS.EXECUTION_PREVIEW,
params: { name: props.workflow.id, executionId: value.id },
})
.catch(() => {});
},
);
if (confirmModal === MODAL_CONFIRM) {
const saved = await this.workflowHelpers.saveCurrentWorkflow({}, false);
if (saved) {
await this.npsSurveyStore.fetchPromptsData();
}
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();
onBeforeRouteLeave(async (to, _, next) => {
if (getNodeViewTab(to) === MAIN_HEADER_TABS.WORKFLOW) {
next();
return;
}
return {
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,
});
},
},
await workflowHelpers.promptSaveUnsavedWorkflowChanges(next);
});
</script>

View file

@ -12,7 +12,6 @@ import { PLACEHOLDER_EMPTY_WORKFLOW_ID, VIEWS } from '@/constants';
import { useRoute, useRouter } from 'vue-router';
import type { ExecutionSummary } from 'n8n-workflow';
import { useDebounce } from '@/composables/useDebounce';
import { storeToRefs } from 'pinia';
import { useTelemetry } from '@/composables/useTelemetry';
import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers';
import { useNodeHelpers } from '@/composables/useNodeHelpers';
@ -29,8 +28,6 @@ const { callDebounced } = useDebounce();
const workflowHelpers = useWorkflowHelpers({ router });
const nodeHelpers = useNodeHelpers();
const { filters } = storeToRefs(executionsStore);
const loading = ref(false);
const loadingMore = ref(false);
@ -311,7 +308,6 @@ async function loadMore(): Promise<void> {
v-if="workflow"
:executions="executions"
:execution="execution"
:filters="filters"
:workflow="workflow"
:loading="loading"
:loading-more="loadingMore"