mirror of
https://github.com/n8n-io/n8n.git
synced 2026-05-28 15:27:03 +02:00
fix(editor): Add rule to prevent undefined components (missing imports) in Vue (#20273)
This commit is contained in:
parent
4ca6e4f29f
commit
2d00ebd260
|
|
@ -60,6 +60,21 @@ export const frontendConfig = tseslint.config(
|
|||
'vue/no-multiple-template-root': 'error',
|
||||
'vue/v-slot-style': 'error',
|
||||
'vue/no-unused-components': 'error',
|
||||
'vue/no-undef-components': [
|
||||
'error',
|
||||
{
|
||||
ignorePatterns: [
|
||||
'FontAwesomeIcon', // Globally registered in plugins/icons/index.ts
|
||||
'RouterLink', // Vue Router global component
|
||||
'RouterView', // Vue Router global component
|
||||
'Teleport', // Vue 3 built-in
|
||||
'Transition', // Vue 3 built-in
|
||||
'TransitionGroup', // Vue 3 built-in
|
||||
'KeepAlive', // Vue 3 built-in
|
||||
'Suspense', // Vue 3 built-in
|
||||
],
|
||||
},
|
||||
],
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'vue/component-name-in-template-casing': [
|
||||
'error',
|
||||
|
|
|
|||
|
|
@ -10,5 +10,6 @@
|
|||
"moduleResolution": "nodenext",
|
||||
"declaration": true
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
"include": ["src/**/*.ts"],
|
||||
"files": []
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { render } from '@testing-library/vue';
|
||||
|
||||
import CanvasThinkingPill from './CanvasThinkingPill.vue';
|
||||
import N8nCanvasThinkingPill from './CanvasThinkingPill.vue';
|
||||
|
||||
describe('CanvasThinkingPill', () => {
|
||||
describe('N8nCanvasThinkingPill', () => {
|
||||
it('renders canvas thinking pill correctly', () => {
|
||||
const { container } = render(CanvasThinkingPill, {});
|
||||
const { container } = render(N8nCanvasThinkingPill, {});
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import AssistantIcon from '../AskAssistantIcon/AssistantIcon.vue';
|
|||
import N8nButton from '../N8nButton';
|
||||
|
||||
defineOptions({
|
||||
name: 'CanvasThinkingPill',
|
||||
name: 'N8nCanvasThinkingPill',
|
||||
});
|
||||
|
||||
defineProps<{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`CanvasThinkingPill > renders canvas thinking pill correctly 1`] = `
|
||||
exports[`N8nCanvasThinkingPill > renders canvas thinking pill correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="thinkingPill"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
import N8nCanvasThinkingPill from './CanvasThinkingPill.vue';
|
||||
|
||||
export default N8nCanvasThinkingPill;
|
||||
|
|
@ -12,6 +12,7 @@ export { default as N8nBadge } from './N8nBadge';
|
|||
export { default as N8nBlockUi } from './N8nBlockUi';
|
||||
export { default as N8nButton } from './N8nButton';
|
||||
export { default as N8nCallout } from './N8nCallout';
|
||||
export { default as N8nCanvasThinkingPill } from './CanvasThinkingPill';
|
||||
export { default as N8nCard } from './N8nCard';
|
||||
export { default as N8nCheckbox } from './N8nCheckbox';
|
||||
export { default as N8nCircleLoader } from './N8nCircleLoader';
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { statusDictionary } from '../shared/statusDictionary';
|
|||
import { getErrorBaseKey } from '@/components/Evaluations.ee/shared/errorCodes';
|
||||
import { I18nT } from 'vue-i18n';
|
||||
import { N8nHeading, N8nIcon, N8nText, N8nTooltip } from '@n8n/design-system';
|
||||
import AnimatedSpinner from '@/components/AnimatedSpinner.vue';
|
||||
const emit = defineEmits<{
|
||||
rowClick: [run: TestRunRecord & { index: number }];
|
||||
}>();
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import { useGlobalEntityCreation } from '@/composables/useGlobalEntityCreation';
|
|||
import { useBecomeTemplateCreatorStore } from '@/components/BecomeTemplateCreatorCta/becomeTemplateCreatorStore';
|
||||
import BecomeTemplateCreatorCta from '@/components/BecomeTemplateCreatorCta/BecomeTemplateCreatorCta.vue';
|
||||
import Logo from '@/components/Logo/Logo.vue';
|
||||
import MainSidebarSourceControl from '@/components/MainSidebarSourceControl.vue';
|
||||
import VersionUpdateCTA from '@/components/VersionUpdateCTA.vue';
|
||||
import { TemplateClickSource, trackTemplatesClick } from '@/utils/experiments';
|
||||
import { I18nT } from 'vue-i18n';
|
||||
|
|
|
|||
|
|
@ -83,7 +83,9 @@ import SourceControlPushModal from '@/components/SourceControlPushModal.ee.vue';
|
|||
import AnnotationTagsManager from '@/components/TagsManager/AnnotationTagsManager.ee.vue';
|
||||
import WorkflowTagsManager from '@/components/TagsManager/WorkflowTagsManager.vue';
|
||||
import UpdatesPanel from '@/components/UpdatesPanel.vue';
|
||||
import WhatsNewModal from '@/components/WhatsNewModal.vue';
|
||||
import WorkflowActivationConflictingWebhookModal from '@/components/WorkflowActivationConflictingWebhookModal.vue';
|
||||
import WorkflowExtractionNameModal from '@/components/WorkflowExtractionNameModal.vue';
|
||||
import WorkflowHistoryVersionRestoreModal from '@/components/WorkflowHistory/WorkflowHistoryVersionRestoreModal.vue';
|
||||
import WorkflowSettings from '@/components/WorkflowSettings.vue';
|
||||
import WorkflowShareModal from '@/components/WorkflowShareModal.ee.vue';
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import type { OpenTemplateItemProps } from '@/Interface';
|
||||
|
||||
import { N8nNodeCreatorNode, N8nNodeIcon } from '@n8n/design-system';
|
||||
import NodeIcon from '@/components/NodeIcon.vue';
|
||||
export interface Props {
|
||||
openTemplate: OpenTemplateItemProps;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ import { isCommunityPackageName } from '@/utils/nodeTypesUtils';
|
|||
import { useI18n } from '@n8n/i18n';
|
||||
import type { EventBus } from '@n8n/utils/event-bus';
|
||||
import { useResizeObserver } from '@vueuse/core';
|
||||
import CommunityNodeFooter from '@/components/Node/NodeCreator/Panel/CommunityNodeFooter.vue';
|
||||
import CommunityNodeUpdateInfo from '@/components/Node/NodeCreator/Panel/CommunityNodeUpdateInfo.vue';
|
||||
import NodeExecuteButton from './NodeExecuteButton.vue';
|
||||
|
||||
import { N8nBlockUi, N8nIcon, N8nNotice, N8nText } from '@n8n/design-system';
|
||||
|
|
|
|||
|
|
@ -21,8 +21,9 @@ import { type IRunDataDisplayMode } from '@/Interface';
|
|||
import { I18nT } from 'vue-i18n';
|
||||
import { useExecutionData } from '@/composables/useExecutionData';
|
||||
import NDVEmptyState from '@/components/NDVEmptyState.vue';
|
||||
import NodeExecuteButton from '@/components/NodeExecuteButton.vue';
|
||||
|
||||
import { N8nIcon, N8nRadioButtons, N8nText } from '@n8n/design-system';
|
||||
import { N8nIcon, N8nRadioButtons, N8nSpinner, N8nText } from '@n8n/design-system';
|
||||
// Types
|
||||
|
||||
type RunDataRef = InstanceType<typeof RunData>;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import ParameterInputWrapper from '@/components/ParameterInputWrapper.vue';
|
|||
import ParameterOptions from '@/components/ParameterOptions.vue';
|
||||
import FromAiOverrideButton from '@/components/ParameterInputOverrides/FromAiOverrideButton.vue';
|
||||
import FromAiOverrideField from '@/components/ParameterInputOverrides/FromAiOverrideField.vue';
|
||||
import ParameterOverrideSelectableList from '@/components/ParameterInputOverrides/ParameterOverrideSelectableList.vue';
|
||||
import { useI18n } from '@n8n/i18n';
|
||||
import { useToast } from '@/composables/useToast';
|
||||
import { useNDVStore } from '@/stores/ndv.store';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { useI18n } from '@n8n/i18n';
|
||||
import AiStarsIcon from '@/components/AiStarsIcon.vue';
|
||||
|
||||
import { N8nButton, N8nTooltip } from '@n8n/design-system';
|
||||
const i18n = useI18n();
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { createEventBus } from '@n8n/utils/event-bus';
|
|||
import { computed } from 'vue';
|
||||
import { useCalloutHelpers } from '@/composables/useCalloutHelpers';
|
||||
import type { INodeCreateElement } from '@/Interface';
|
||||
import ItemsRenderer from '@/components/Node/NodeCreator/Renderers/ItemsRenderer.vue';
|
||||
|
||||
import { N8nHeading } from '@n8n/design-system';
|
||||
const i18n = useI18n();
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@ import {
|
|||
} from '../../utils/fromAIOverrideUtils';
|
||||
import { completeExpressionSyntax } from '@/utils/expressions';
|
||||
import { useProjectsStore } from '@/stores/projects.store';
|
||||
import FromAiOverrideButton from '@/components/ParameterInputOverrides/FromAiOverrideButton.vue';
|
||||
import FromAiOverrideField from '@/components/ParameterInputOverrides/FromAiOverrideField.vue';
|
||||
import ParameterOverrideSelectableList from '@/components/ParameterInputOverrides/ParameterOverrideSelectableList.vue';
|
||||
|
||||
import {
|
||||
N8nIcon,
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import { useWorkflowsStore } from '@/stores/workflows.store';
|
|||
import { useDocumentVisibility } from '@/composables/useDocumentVisibility';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import { useProjectsStore } from '@/stores/projects.store';
|
||||
import ParameterInputFull from '@/components/ParameterInputFull.vue';
|
||||
|
||||
import { N8nButton, N8nCallout, N8nIcon, N8nNotice, N8nText } from '@n8n/design-system';
|
||||
type Props = {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import type {
|
|||
} from 'n8n-workflow';
|
||||
import { useI18n } from '@n8n/i18n';
|
||||
import DraggableTarget from '@/components/DraggableTarget.vue';
|
||||
import ExpressionParameterInput from '@/components/ExpressionParameterInput.vue';
|
||||
import ResourceLocatorDropdown from '@/components/ResourceLocator/ResourceLocatorDropdown.vue';
|
||||
import ParameterIssues from '@/components/ParameterIssues.vue';
|
||||
import { onClickOutside } from '@vueuse/core';
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ import {
|
|||
import { useViewportAutoAdjust } from './composables/useViewportAutoAdjust';
|
||||
import CanvasBackground from './elements/background/CanvasBackground.vue';
|
||||
import CanvasArrowHeadMarker from './elements/edges/CanvasArrowHeadMarker.vue';
|
||||
import CanvasConnectionLine from './elements/edges/CanvasConnectionLine.vue';
|
||||
import CanvasControlButtons from './elements/buttons/CanvasControlButtons.vue';
|
||||
import Edge from './elements/edges/CanvasEdge.vue';
|
||||
import Node from './elements/nodes/CanvasNode.vue';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts" setup>
|
||||
import AnnotationTagsDropdown from '@/components/AnnotationTagsDropdown.ee.vue';
|
||||
import WorkflowTagsDropdown from '@/components/WorkflowTagsDropdown.vue';
|
||||
import { useDebounce } from '@/composables/useDebounce';
|
||||
import { usePageRedirectionHelper } from '@/composables/usePageRedirectionHelper';
|
||||
import { useTelemetry } from '@/composables/useTelemetry';
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { ref, watchEffect } from 'vue';
|
|||
import { usePersonalizedTemplatesV3Store } from '../stores/personalizedTemplatesV3.store';
|
||||
import TemplateCard from './TemplateCard.vue';
|
||||
import { useI18n } from '@n8n/i18n';
|
||||
import { N8nText } from '@n8n/design-system';
|
||||
import { N8nCard, N8nIcon, N8nSpinner, N8nText } from '@n8n/design-system';
|
||||
|
||||
const uiStore = useUIStore();
|
||||
const {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import TemplateCard from './TemplateCard.vue';
|
|||
import YoutubeCard from './YoutubeCard.vue';
|
||||
import NodeIcon from '@/components/NodeIcon.vue';
|
||||
import { useI18n } from '@n8n/i18n';
|
||||
import { N8nRadioButtons } from '@n8n/design-system';
|
||||
import { N8nLink, N8nRadioButtons, N8nSpinner, N8nText } from '@n8n/design-system';
|
||||
|
||||
const props = defineProps<{
|
||||
modalName: string;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { useI18n } from '@n8n/i18n';
|
|||
import { computed } from 'vue';
|
||||
import DataStoreActions from '@/features/dataStore/components/DataStoreActions.vue';
|
||||
import { useDataStoreStore } from '@/features/dataStore/dataStore.store';
|
||||
import TimeAgo from '@/components/TimeAgo.vue';
|
||||
|
||||
import { N8nBadge, N8nCard, N8nIcon, N8nLink, N8nText } from '@n8n/design-system';
|
||||
type Props = {
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ const onInput = debounce(validateName, { debounceTime: 100 });
|
|||
<N8nText v-if="error.message" size="small" color="danger" tag="span">
|
||||
{{ error.message }}
|
||||
</N8nText>
|
||||
<Tooltip
|
||||
<N8nTooltip
|
||||
:content="error.description"
|
||||
placement="top"
|
||||
:disabled="!error.description"
|
||||
|
|
@ -186,7 +186,7 @@ const onInput = debounce(validateName, { debounceTime: 100 });
|
|||
color="text-base"
|
||||
data-test-id="add-column-error-help-icon"
|
||||
/>
|
||||
</Tooltip>
|
||||
</N8nTooltip>
|
||||
</div>
|
||||
</N8nInputLabel>
|
||||
<N8nInputLabel
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import { isIconOrEmoji, type IconOrEmoji } from '@n8n/design-system/components/N
|
|||
import { useMCPStore } from '@/features/mcpAccess/mcp.store';
|
||||
import { useUsersStore } from '@/stores/users.store';
|
||||
import MCPConnectionInstructions from '@/features/mcpAccess/components/MCPConnectionInstructions.vue';
|
||||
import ProjectIcon from '@/components/Projects/ProjectIcon.vue';
|
||||
|
||||
import { ElSwitch } from 'element-plus';
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import CredentialCard from '@/components/CredentialCard.vue';
|
||||
import EmptySharedSectionActionBox from '@/components/Folders/EmptySharedSectionActionBox.vue';
|
||||
import ResourcesListLayout from '@/components/layouts/ResourcesListLayout.vue';
|
||||
import type { BaseFilters, Resource, ICredentialTypeMap } from '@/Interface';
|
||||
import ProjectHeader from '@/components/Projects/ProjectHeader.vue';
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ import { type ContextMenuAction } from '@/composables/useContextMenuItems';
|
|||
import { useExperimentalNdvStore } from '@/components/canvas/experimental/experimentalNdv.store';
|
||||
import { useParentFolder } from '@/composables/useParentFolder';
|
||||
|
||||
import { N8nCallout } from '@n8n/design-system';
|
||||
import { N8nCallout, N8nCanvasThinkingPill } from '@n8n/design-system';
|
||||
|
||||
defineOptions({
|
||||
name: 'NodeView',
|
||||
|
|
@ -2069,7 +2069,7 @@ onBeforeUnmount(() => {
|
|||
{{ i18n.baseText('readOnlyEnv.cantEditOrRun') }}
|
||||
</N8nCallout>
|
||||
|
||||
<CanvasThinkingPill
|
||||
<N8nCanvasThinkingPill
|
||||
v-if="builderStore.streaming"
|
||||
:class="$style.thinkingPill"
|
||||
show-stop
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import { useRoute, useRouter } from 'vue-router';
|
|||
import { useTelemetry } from '@/composables/useTelemetry';
|
||||
import { useDocumentTitle } from '@/composables/useDocumentTitle';
|
||||
import { useI18n } from '@n8n/i18n';
|
||||
import TemplateDetails from '@/components/TemplateDetails.vue';
|
||||
import WorkflowPreview from '@/components/WorkflowPreview.vue';
|
||||
import TemplatesView from './TemplatesView.vue';
|
||||
|
||||
import { N8nButton, N8nHeading, N8nLoading, N8nMarkdown, N8nText } from '@n8n/design-system';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts" setup>
|
||||
import Draggable from '@/components/Draggable.vue';
|
||||
import EmptySharedSectionActionBox from '@/components/Folders/EmptySharedSectionActionBox.vue';
|
||||
import FolderBreadcrumbs from '@/components/Folders/FolderBreadcrumbs.vue';
|
||||
import FolderCard from '@/components/Folders/FolderCard.vue';
|
||||
import { FOLDER_LIST_ITEM_ACTIONS } from '@/components/Folders/constants';
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user