mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
feat(editor): Implement loading and error states for dynamically loaded components in node parameter list (#8477)
This commit is contained in:
parent
121a55b691
commit
e643a126f4
|
@ -49,7 +49,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, defineAsyncComponent } from 'vue';
|
||||
import { ref, computed } from 'vue';
|
||||
import type { IUpdateInformation } from '@/Interface';
|
||||
|
||||
import type {
|
||||
|
@ -65,9 +65,6 @@ import { get } from 'lodash-es';
|
|||
import { useNDVStore } from '@/stores/ndv.store';
|
||||
import { useNodeHelpers } from '@/composables/useNodeHelpers';
|
||||
import { useI18n } from '@/composables/useI18n';
|
||||
const ParameterInputList = defineAsyncComponent(
|
||||
async () => await import('./ParameterInputList.vue'),
|
||||
);
|
||||
|
||||
const selectedOption = ref<string | undefined>(undefined);
|
||||
export interface Props {
|
||||
|
|
|
@ -122,7 +122,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineAsyncComponent, defineComponent } from 'vue';
|
||||
import { defineComponent } from 'vue';
|
||||
import type { PropType } from 'vue';
|
||||
import type { IUpdateInformation } from '@/Interface';
|
||||
|
||||
|
@ -136,15 +136,8 @@ import { deepCopy, isINodePropertyCollectionList } from 'n8n-workflow';
|
|||
|
||||
import { get } from 'lodash-es';
|
||||
|
||||
const ParameterInputList = defineAsyncComponent(
|
||||
async () => await import('./ParameterInputList.vue'),
|
||||
);
|
||||
|
||||
export default defineComponent({
|
||||
name: 'FixedCollectionParameter',
|
||||
components: {
|
||||
ParameterInputList,
|
||||
},
|
||||
props: {
|
||||
nodeValues: {
|
||||
type: Object as PropType<Record<string, INodeParameters[]>>,
|
||||
|
|
|
@ -65,26 +65,38 @@
|
|||
:underline="true"
|
||||
color="text-dark"
|
||||
/>
|
||||
<Suspense>
|
||||
<CollectionParameter
|
||||
v-if="parameter.type === 'collection'"
|
||||
:parameter="parameter"
|
||||
:values="nodeHelpers.getParameterValue(nodeValues, parameter.name, path)"
|
||||
:node-values="nodeValues"
|
||||
:path="getPath(parameter.name)"
|
||||
:is-read-only="isReadOnly"
|
||||
@valueChanged="valueChanged"
|
||||
/>
|
||||
<FixedCollectionParameter
|
||||
v-else-if="parameter.type === 'fixedCollection'"
|
||||
:parameter="parameter"
|
||||
:values="nodeHelpers.getParameterValue(nodeValues, parameter.name, path)"
|
||||
:node-values="nodeValues"
|
||||
:path="getPath(parameter.name)"
|
||||
:is-read-only="isReadOnly"
|
||||
@valueChanged="valueChanged"
|
||||
/>
|
||||
<Suspense v-if="!asyncLoadingError">
|
||||
<template #default>
|
||||
<CollectionParameter
|
||||
v-if="parameter.type === 'collection'"
|
||||
:parameter="parameter"
|
||||
:values="nodeHelpers.getParameterValue(nodeValues, parameter.name, path)"
|
||||
:node-values="nodeValues"
|
||||
:path="getPath(parameter.name)"
|
||||
:is-read-only="isReadOnly"
|
||||
@valueChanged="valueChanged"
|
||||
/>
|
||||
<FixedCollectionParameter
|
||||
v-else-if="parameter.type === 'fixedCollection'"
|
||||
:parameter="parameter"
|
||||
:values="nodeHelpers.getParameterValue(nodeValues, parameter.name, path)"
|
||||
:node-values="nodeValues"
|
||||
:path="getPath(parameter.name)"
|
||||
:is-read-only="isReadOnly"
|
||||
@valueChanged="valueChanged"
|
||||
/>
|
||||
</template>
|
||||
<template #fallback>
|
||||
<n8n-text size="small" class="async-notice">
|
||||
<n8n-icon icon="sync-alt" size="xsmall" :spin="true" />
|
||||
{{ $locale.baseText('parameterInputList.loadingFields') }}
|
||||
</n8n-text>
|
||||
</template>
|
||||
</Suspense>
|
||||
<n8n-text v-else size="small" color="danger" class="async-notice">
|
||||
<n8n-icon icon="exclamation-triangle" size="xsmall" />
|
||||
{{ $locale.baseText('parameterInputList.loadingError') }}
|
||||
</n8n-text>
|
||||
</div>
|
||||
<ResourceMapper
|
||||
v-else-if="parameter.type === 'resourceMapper'"
|
||||
|
@ -150,7 +162,7 @@ import type {
|
|||
import { deepCopy } from 'n8n-workflow';
|
||||
import { mapStores } from 'pinia';
|
||||
import type { PropType } from 'vue';
|
||||
import { defineAsyncComponent, defineComponent } from 'vue';
|
||||
import { defineAsyncComponent, defineComponent, onErrorCaptured, ref } from 'vue';
|
||||
|
||||
import type { INodeUi, IUpdateInformation } from '@/Interface';
|
||||
|
||||
|
@ -226,9 +238,31 @@ export default defineComponent({
|
|||
},
|
||||
setup() {
|
||||
const nodeHelpers = useNodeHelpers();
|
||||
const asyncLoadingError = ref(false);
|
||||
|
||||
// This will catch errors in async components
|
||||
onErrorCaptured((e, component) => {
|
||||
if (
|
||||
!['FixedCollectionParameter', 'CollectionParameter'].includes(
|
||||
component?.$options.name as string,
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
asyncLoadingError.value = true;
|
||||
console.error(e);
|
||||
window?.Sentry?.captureException(e, {
|
||||
tags: {
|
||||
asyncLoadingError: true,
|
||||
},
|
||||
});
|
||||
// Don't propagate the error further
|
||||
return false;
|
||||
});
|
||||
|
||||
return {
|
||||
nodeHelpers,
|
||||
asyncLoadingError,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -572,5 +606,10 @@ export default defineComponent({
|
|||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
}
|
||||
|
||||
.async-notice {
|
||||
display: block;
|
||||
padding: var(--spacing-3xs) 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -7,6 +7,7 @@ import { N8nPlugin } from 'n8n-design-system';
|
|||
import { useMessage } from '@/composables/useMessage';
|
||||
import EnterpriseEdition from '@/components/EnterpriseEdition.ee.vue';
|
||||
import RBAC from '@/components/RBAC.vue';
|
||||
import ParameterInputList from '@/components/ParameterInputList.vue';
|
||||
|
||||
export const GlobalComponentsPlugin: Plugin<{}> = {
|
||||
install(app) {
|
||||
|
@ -14,6 +15,7 @@ export const GlobalComponentsPlugin: Plugin<{}> = {
|
|||
|
||||
app.component('EnterpriseEdition', EnterpriseEdition);
|
||||
app.component('RBAC', RBAC);
|
||||
app.component('ParameterInputList', ParameterInputList);
|
||||
|
||||
app.use(ElementPlus);
|
||||
app.use(N8nPlugin);
|
||||
|
|
|
@ -1181,6 +1181,8 @@
|
|||
"parameterInputList.delete": "Delete",
|
||||
"parameterInputList.deleteParameter": "Delete Parameter",
|
||||
"parameterInputList.parameterOptions": "Parameter Options",
|
||||
"parameterInputList.loadingFields": "Loading fields...",
|
||||
"parameterInputList.loadingError": "Error loading fields. Refresh you page and try again.",
|
||||
"personalizationModal.businessOwner": "Business Owner",
|
||||
"personalizationModal.continue": "Continue",
|
||||
"personalizationModal.cicd": "CI/CD",
|
||||
|
|
Loading…
Reference in a new issue