mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-10 06:34:05 -08:00
feat: Replace this.$refs.refName as Vue with InstanceType<T> (no-changelog) (#6050)
* refactor: use InstanceType<T> for all this.$refs types * refactor: update refs type in N8nSelect * fix: remove inputRef non-null assertion Co-authored-by: Mutasem Aldmour <4711238+mutdmour@users.noreply.github.com> * fix: remove non-null assertion --------- Co-authored-by: Mutasem Aldmour <4711238+mutdmour@users.noreply.github.com>
This commit is contained in:
parent
19f540ecf9
commit
54f99a7d0d
|
@ -13,6 +13,8 @@ const classToTypeMap = {
|
|||
'el-picker-panel__link-btn': 'secondary',
|
||||
};
|
||||
|
||||
type ButtonRef = InstanceType<typeof N8nButton>;
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
N8nButton,
|
||||
|
@ -32,7 +34,7 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
Object.entries(classToTypeMap).forEach(([className, mappedType]) => {
|
||||
if (this.$refs.button && (this.$refs.button as Vue).$el.classList.contains(className)) {
|
||||
if ((this.$refs.button as ButtonRef)?.$el.classList.contains(className)) {
|
||||
type = mappedType;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
import { Input as ElInput } from 'element-ui';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
type InputRef = InstanceType<typeof ElInput>;
|
||||
|
||||
export default defineComponent({
|
||||
name: 'n8n-input',
|
||||
components: {
|
||||
|
@ -92,7 +94,7 @@ export default defineComponent({
|
|||
},
|
||||
methods: {
|
||||
focus() {
|
||||
const innerInput = this.$refs.innerInput as Vue | undefined;
|
||||
const innerInput = this.$refs.innerInput as InputRef | undefined;
|
||||
|
||||
if (!innerInput) return;
|
||||
|
||||
|
@ -105,7 +107,7 @@ export default defineComponent({
|
|||
inputElement.focus();
|
||||
},
|
||||
blur() {
|
||||
const innerInput = this.$refs.innerInput as Vue | undefined;
|
||||
const innerInput = this.$refs.innerInput as InputRef | undefined;
|
||||
|
||||
if (!innerInput) return;
|
||||
|
||||
|
@ -118,7 +120,7 @@ export default defineComponent({
|
|||
inputElement.blur();
|
||||
},
|
||||
select() {
|
||||
const innerInput = this.$refs.innerInput as Vue | undefined;
|
||||
const innerInput = this.$refs.innerInput as InputRef | undefined;
|
||||
|
||||
if (!innerInput) return;
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
import { Select as ElSelect } from 'element-ui';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
type InnerSelectRef = InstanceType<typeof ElSelect>;
|
||||
|
||||
export interface IProps {
|
||||
size?: string;
|
||||
limitPopperWidth?: string;
|
||||
|
@ -117,23 +119,23 @@ export default defineComponent({
|
|||
},
|
||||
methods: {
|
||||
focus() {
|
||||
const select = this.$refs.innerSelect as (Vue & HTMLElement) | undefined;
|
||||
if (select) {
|
||||
select.focus();
|
||||
const selectRef = this.$refs.innerSelect as InnerSelectRef | undefined;
|
||||
if (selectRef) {
|
||||
selectRef.focus();
|
||||
}
|
||||
},
|
||||
blur() {
|
||||
const select = this.$refs.innerSelect as (Vue & HTMLElement) | undefined;
|
||||
if (select) {
|
||||
select.blur();
|
||||
const selectRef = this.$refs.innerSelect as InnerSelectRef | undefined;
|
||||
if (selectRef) {
|
||||
selectRef.blur();
|
||||
}
|
||||
},
|
||||
focusOnInput() {
|
||||
const select = this.$refs.innerSelect as (Vue & HTMLElement) | undefined;
|
||||
if (select) {
|
||||
const input = select.$refs.input as (Vue & HTMLElement) | undefined;
|
||||
if (input) {
|
||||
input.focus();
|
||||
const selectRef = this.$refs.innerSelect as InnerSelectRef | undefined;
|
||||
if (selectRef) {
|
||||
const inputRef = selectRef.$refs.input as HTMLInputElement | undefined;
|
||||
if (inputRef) {
|
||||
inputRef.focus();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
49
packages/design-system/src/components/index.ts
Normal file
49
packages/design-system/src/components/index.ts
Normal file
|
@ -0,0 +1,49 @@
|
|||
export { default as N8nActionBox } from './N8nActionBox';
|
||||
export { default as N8nActionDropdown } from './N8nActionDropdown';
|
||||
export { default as N8nActionToggle } from './N8nActionToggle';
|
||||
export { default as N8nAlert } from './N8nAlert';
|
||||
export { default as N8nAvatar } from './N8nAvatar';
|
||||
export { default as N8nBadge } from './N8nBadge';
|
||||
export { default as N8nBlockUi } from './N8nBlockUi';
|
||||
export { default as N8nButton } from './N8nButton';
|
||||
export { N8nElButton } from './N8nButton/overrides';
|
||||
export { default as N8nCallout } from './N8nCallout';
|
||||
export { default as N8nCard } from './N8nCard';
|
||||
export { default as N8nDatatable } from './N8nDatatable';
|
||||
export { default as N8nFormBox } from './N8nFormBox';
|
||||
export { default as N8nFormInputs } from './N8nFormInputs';
|
||||
export { default as N8nFormInput } from './N8nFormInput';
|
||||
export { default as N8nHeading } from './N8nHeading';
|
||||
export { default as N8nIcon } from './N8nIcon';
|
||||
export { default as N8nIconButton } from './N8nIconButton';
|
||||
export { default as N8nInfoAccordion } from './N8nInfoAccordion';
|
||||
export { default as N8nInfoTip } from './N8nInfoTip';
|
||||
export { default as N8nInput } from './N8nInput';
|
||||
export { default as N8nInputLabel } from './N8nInputLabel';
|
||||
export { default as N8nInputNumber } from './N8nInputNumber';
|
||||
export { default as N8nLink } from './N8nLink';
|
||||
export { default as N8nLoading } from './N8nLoading';
|
||||
export { default as N8nMarkdown } from './N8nMarkdown';
|
||||
export { default as N8nMenu } from './N8nMenu';
|
||||
export { default as N8nMenuItem } from './N8nMenuItem';
|
||||
export { default as N8nNodeCreatorNode } from './N8nNodeCreatorNode';
|
||||
export { default as N8nNodeIcon } from './N8nNodeIcon';
|
||||
export { default as N8nNotice } from './N8nNotice';
|
||||
export { default as N8nOption } from './N8nOption';
|
||||
export { default as N8nPopover } from './N8nPopover';
|
||||
export { default as N8nPulse } from './N8nPulse';
|
||||
export { default as N8nRadioButtons } from './N8nRadioButtons';
|
||||
export { default as N8nSelect } from './N8nSelect';
|
||||
export { default as N8nSpinner } from './N8nSpinner';
|
||||
export { default as N8nSticky } from './N8nSticky';
|
||||
export { default as N8nTabs } from './N8nTabs';
|
||||
export { default as N8nTag } from './N8nTag';
|
||||
export { default as N8nTags } from './N8nTags';
|
||||
export { default as N8nText } from './N8nText';
|
||||
export { default as N8nTooltip } from './N8nTooltip';
|
||||
export { default as N8nTree } from './N8nTree';
|
||||
export { default as N8nUserInfo } from './N8nUserInfo';
|
||||
export { default as N8nUserSelect } from './N8nUserSelect';
|
||||
export { default as N8nUsersList } from './N8nUsersList';
|
||||
export { default as N8nResizeWrapper } from './N8nResizeWrapper';
|
||||
export { default as N8nRecycleScroller } from './N8nRecycleScroller';
|
|
@ -1,6 +1,7 @@
|
|||
import * as locale from './locale';
|
||||
import designSystemComponents from './plugins/n8nComponents';
|
||||
|
||||
export * from './components';
|
||||
export * from './plugin';
|
||||
export * from './types';
|
||||
export * from './utils';
|
||||
export { locale, designSystemComponents };
|
||||
export { locale };
|
||||
|
|
107
packages/design-system/src/plugin.ts
Normal file
107
packages/design-system/src/plugin.ts
Normal file
|
@ -0,0 +1,107 @@
|
|||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import type { PluginObject } from 'vue';
|
||||
import {
|
||||
N8nActionBox,
|
||||
N8nActionDropdown,
|
||||
N8nActionToggle,
|
||||
N8nAlert,
|
||||
N8nAvatar,
|
||||
N8nBadge,
|
||||
N8nBlockUi,
|
||||
N8nButton,
|
||||
N8nElButton,
|
||||
N8nCallout,
|
||||
N8nCard,
|
||||
N8nDatatable,
|
||||
N8nFormBox,
|
||||
N8nFormInputs,
|
||||
N8nFormInput,
|
||||
N8nHeading,
|
||||
N8nIcon,
|
||||
N8nIconButton,
|
||||
N8nInfoAccordion,
|
||||
N8nInfoTip,
|
||||
N8nInput,
|
||||
N8nInputLabel,
|
||||
N8nInputNumber,
|
||||
N8nLink,
|
||||
N8nLoading,
|
||||
N8nMarkdown,
|
||||
N8nMenu,
|
||||
N8nMenuItem,
|
||||
N8nNodeCreatorNode,
|
||||
N8nNodeIcon,
|
||||
N8nNotice,
|
||||
N8nOption,
|
||||
N8nPopover,
|
||||
N8nPulse,
|
||||
N8nRadioButtons,
|
||||
N8nSelect,
|
||||
N8nSpinner,
|
||||
N8nSticky,
|
||||
N8nTabs,
|
||||
N8nTag,
|
||||
N8nTags,
|
||||
N8nText,
|
||||
N8nTooltip,
|
||||
N8nTree,
|
||||
N8nUserInfo,
|
||||
N8nUserSelect,
|
||||
N8nUsersList,
|
||||
N8nResizeWrapper,
|
||||
N8nRecycleScroller,
|
||||
} from './components';
|
||||
|
||||
export const N8nPlugin: PluginObject<{}> = {
|
||||
install: (app) => {
|
||||
app.component('n8n-info-accordion', N8nInfoAccordion);
|
||||
app.component('n8n-action-box', N8nActionBox);
|
||||
app.component('n8n-action-dropdown', N8nActionDropdown);
|
||||
app.component('n8n-action-toggle', N8nActionToggle);
|
||||
app.component('n8n-alert', N8nAlert);
|
||||
app.component('n8n-avatar', N8nAvatar);
|
||||
app.component('n8n-badge', N8nBadge);
|
||||
app.component('n8n-block-ui', N8nBlockUi);
|
||||
app.component('n8n-button', N8nButton);
|
||||
app.component('el-button', N8nElButton);
|
||||
app.component('n8n-callout', N8nCallout);
|
||||
app.component('n8n-card', N8nCard);
|
||||
app.component('n8n-datatable', N8nDatatable);
|
||||
app.component('n8n-form-box', N8nFormBox);
|
||||
app.component('n8n-form-inputs', N8nFormInputs);
|
||||
app.component('n8n-form-input', N8nFormInput);
|
||||
app.component('n8n-icon', N8nIcon);
|
||||
app.component('n8n-icon-button', N8nIconButton);
|
||||
app.component('n8n-info-tip', N8nInfoTip);
|
||||
app.component('n8n-input', N8nInput);
|
||||
app.component('n8n-input-label', N8nInputLabel);
|
||||
app.component('n8n-input-number', N8nInputNumber);
|
||||
app.component('n8n-loading', N8nLoading);
|
||||
app.component('n8n-heading', N8nHeading);
|
||||
app.component('n8n-link', N8nLink);
|
||||
app.component('n8n-markdown', N8nMarkdown);
|
||||
app.component('n8n-menu', N8nMenu);
|
||||
app.component('n8n-menu-item', N8nMenuItem);
|
||||
app.component('n8n-node-creator-node', N8nNodeCreatorNode);
|
||||
app.component('n8n-node-icon', N8nNodeIcon);
|
||||
app.component('n8n-notice', N8nNotice);
|
||||
app.component('n8n-option', N8nOption);
|
||||
app.component('n8n-popover', N8nPopover);
|
||||
app.component('n8n-pulse', N8nPulse);
|
||||
app.component('n8n-select', N8nSelect);
|
||||
app.component('n8n-spinner', N8nSpinner);
|
||||
app.component('n8n-sticky', N8nSticky);
|
||||
app.component('n8n-radio-buttons', N8nRadioButtons);
|
||||
app.component('n8n-tags', N8nTags);
|
||||
app.component('n8n-tabs', N8nTabs);
|
||||
app.component('n8n-tag', N8nTag);
|
||||
app.component('n8n-text', N8nText);
|
||||
app.component('n8n-tooltip', N8nTooltip);
|
||||
app.component('n8n-user-info', N8nUserInfo);
|
||||
app.component('n8n-tree', N8nTree);
|
||||
app.component('n8n-users-list', N8nUsersList);
|
||||
app.component('n8n-user-select', N8nUserSelect);
|
||||
app.component('n8n-resize-wrapper', N8nResizeWrapper);
|
||||
app.component('n8n-recycle-scroller', N8nRecycleScroller);
|
||||
},
|
||||
};
|
|
@ -1,106 +0,0 @@
|
|||
import type { PluginObject } from 'vue';
|
||||
import N8nActionBox from '../components/N8nActionBox';
|
||||
import N8nActionDropdown from '../components/N8nActionDropdown';
|
||||
import N8nActionToggle from '../components/N8nActionToggle';
|
||||
import N8nAlert from '../components/N8nAlert';
|
||||
import N8nAvatar from '../components/N8nAvatar';
|
||||
import N8nBadge from '../components/N8nBadge';
|
||||
import N8nBlockUi from '../components/N8nBlockUi';
|
||||
import N8nButton from '../components/N8nButton';
|
||||
import { N8nElButton } from '../components/N8nButton/overrides';
|
||||
import N8nCallout from '../components/N8nCallout';
|
||||
import N8nCard from '../components/N8nCard';
|
||||
import N8nDatatable from '../components/N8nDatatable';
|
||||
import N8nFormBox from '../components/N8nFormBox';
|
||||
import N8nFormInputs from '../components/N8nFormInputs';
|
||||
import N8nFormInput from '../components/N8nFormInput';
|
||||
import N8nHeading from '../components/N8nHeading';
|
||||
import N8nIcon from '../components/N8nIcon';
|
||||
import N8nIconButton from '../components/N8nIconButton';
|
||||
import N8nInfoAccordion from '../components/N8nInfoAccordion';
|
||||
import N8nInfoTip from '../components/N8nInfoTip';
|
||||
import { default as N8nInput } from '../components/N8nInput';
|
||||
import N8nInputLabel from '../components/N8nInputLabel';
|
||||
import N8nInputNumber from '../components/N8nInputNumber';
|
||||
import N8nLink from '../components/N8nLink';
|
||||
import N8nLoading from '../components/N8nLoading';
|
||||
import N8nMarkdown from '../components/N8nMarkdown';
|
||||
import N8nMenu from '../components/N8nMenu';
|
||||
import N8nMenuItem from '../components/N8nMenuItem';
|
||||
import N8nNodeCreatorNode from '../components/N8nNodeCreatorNode';
|
||||
import N8nNodeIcon from '../components/N8nNodeIcon';
|
||||
import N8nNotice from '../components/N8nNotice';
|
||||
import N8nOption from '../components/N8nOption';
|
||||
import N8nPopover from '../components/N8nPopover';
|
||||
import N8nPulse from '../components/N8nPulse';
|
||||
import N8nRadioButtons from '../components/N8nRadioButtons';
|
||||
import N8nSelect from '../components/N8nSelect';
|
||||
import N8nSpinner from '../components/N8nSpinner';
|
||||
import N8nSticky from '../components/N8nSticky';
|
||||
import N8nTabs from '../components/N8nTabs';
|
||||
import N8nTag from '../components/N8nTag';
|
||||
import N8nTags from '../components/N8nTags';
|
||||
import N8nText from '../components/N8nText';
|
||||
import N8nTooltip from '../components/N8nTooltip';
|
||||
import N8nTree from '../components/N8nTree';
|
||||
import N8nUserInfo from '../components/N8nUserInfo';
|
||||
import N8nUserSelect from '../components/N8nUserSelect';
|
||||
import N8nUsersList from '../components/N8nUsersList';
|
||||
import N8nResizeWrapper from '../components/N8nResizeWrapper';
|
||||
import N8nRecycleScroller from '../components/N8nRecycleScroller';
|
||||
|
||||
const n8nComponentsPlugin: PluginObject<{}> = {
|
||||
install: (app) => {
|
||||
app.component('n8n-info-accordion', N8nInfoAccordion);
|
||||
app.component('n8n-action-box', N8nActionBox);
|
||||
app.component('n8n-action-dropdown', N8nActionDropdown);
|
||||
app.component('n8n-action-toggle', N8nActionToggle);
|
||||
app.component('n8n-alert', N8nAlert);
|
||||
app.component('n8n-avatar', N8nAvatar);
|
||||
app.component('n8n-badge', N8nBadge);
|
||||
app.component('n8n-block-ui', N8nBlockUi);
|
||||
app.component('n8n-button', N8nButton);
|
||||
app.component('el-button', N8nElButton);
|
||||
app.component('n8n-callout', N8nCallout);
|
||||
app.component('n8n-card', N8nCard);
|
||||
app.component('n8n-datatable', N8nDatatable);
|
||||
app.component('n8n-form-box', N8nFormBox);
|
||||
app.component('n8n-form-inputs', N8nFormInputs);
|
||||
app.component('n8n-form-input', N8nFormInput);
|
||||
app.component('n8n-icon', N8nIcon);
|
||||
app.component('n8n-icon-button', N8nIconButton);
|
||||
app.component('n8n-info-tip', N8nInfoTip);
|
||||
app.component('n8n-input', N8nInput);
|
||||
app.component('n8n-input-label', N8nInputLabel);
|
||||
app.component('n8n-input-number', N8nInputNumber);
|
||||
app.component('n8n-loading', N8nLoading);
|
||||
app.component('n8n-heading', N8nHeading);
|
||||
app.component('n8n-link', N8nLink);
|
||||
app.component('n8n-markdown', N8nMarkdown);
|
||||
app.component('n8n-menu', N8nMenu);
|
||||
app.component('n8n-menu-item', N8nMenuItem);
|
||||
app.component('n8n-node-creator-node', N8nNodeCreatorNode);
|
||||
app.component('n8n-node-icon', N8nNodeIcon);
|
||||
app.component('n8n-notice', N8nNotice);
|
||||
app.component('n8n-option', N8nOption);
|
||||
app.component('n8n-popover', N8nPopover);
|
||||
app.component('n8n-pulse', N8nPulse);
|
||||
app.component('n8n-select', N8nSelect);
|
||||
app.component('n8n-spinner', N8nSpinner);
|
||||
app.component('n8n-sticky', N8nSticky);
|
||||
app.component('n8n-radio-buttons', N8nRadioButtons);
|
||||
app.component('n8n-tags', N8nTags);
|
||||
app.component('n8n-tabs', N8nTabs);
|
||||
app.component('n8n-tag', N8nTag);
|
||||
app.component('n8n-text', N8nText);
|
||||
app.component('n8n-tooltip', N8nTooltip);
|
||||
app.component('n8n-user-info', N8nUserInfo);
|
||||
app.component('n8n-tree', N8nTree);
|
||||
app.component('n8n-users-list', N8nUsersList);
|
||||
app.component('n8n-user-select', N8nUserSelect);
|
||||
app.component('n8n-resize-wrapper', N8nResizeWrapper);
|
||||
app.component('n8n-recycle-scroller', N8nRecycleScroller);
|
||||
},
|
||||
};
|
||||
|
||||
export default n8nComponentsPlugin;
|
|
@ -95,15 +95,15 @@ export default mixins(linterExtension, completerExtension, workflowHelpers).exte
|
|||
methods: {
|
||||
onMouseOver(event: MouseEvent) {
|
||||
const fromElement = event.relatedTarget as HTMLElement;
|
||||
const ref = this.$refs.codeNodeEditorContainer as HTMLDivElement;
|
||||
const ref = this.$refs.codeNodeEditorContainer as HTMLDivElement | undefined;
|
||||
|
||||
if (!ref.contains(fromElement)) this.isEditorHovered = true;
|
||||
if (!ref?.contains(fromElement)) this.isEditorHovered = true;
|
||||
},
|
||||
onMouseOut(event: MouseEvent) {
|
||||
const fromElement = event.relatedTarget as HTMLElement;
|
||||
const ref = this.$refs.codeNodeEditorContainer as HTMLDivElement;
|
||||
const ref = this.$refs.codeNodeEditorContainer as HTMLDivElement | undefined;
|
||||
|
||||
if (!ref.contains(fromElement)) this.isEditorHovered = false;
|
||||
if (!ref?.contains(fromElement)) this.isEditorHovered = false;
|
||||
},
|
||||
onAskAiButtonClick() {
|
||||
this.$telemetry.track('User clicked ask ai button', { source: 'code' });
|
||||
|
|
|
@ -35,6 +35,8 @@ import VueAgile from 'vue-agile';
|
|||
import { genericHelpers } from '@/mixins/genericHelpers';
|
||||
import mixins from 'vue-typed-mixins';
|
||||
|
||||
type SliderRef = InstanceType<typeof VueAgile>;
|
||||
|
||||
export default mixins(genericHelpers).extend({
|
||||
name: 'CollectionsCarousel',
|
||||
props: {
|
||||
|
@ -97,22 +99,23 @@ export default mixins(genericHelpers).extend({
|
|||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
const slider = this.$refs.slider;
|
||||
if (!slider) {
|
||||
const sliderRef = this.$refs.slider as SliderRef | undefined;
|
||||
if (!sliderRef) {
|
||||
return;
|
||||
}
|
||||
// @ts-ignore
|
||||
this.listElement = slider.$el.querySelector('.agile__list');
|
||||
|
||||
this.listElement = sliderRef.$el.querySelector('.agile__list');
|
||||
if (this.listElement) {
|
||||
this.listElement.addEventListener('scroll', this.updateCarouselScroll);
|
||||
}
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.$refs.slider) {
|
||||
// @ts-ignore
|
||||
this.$refs.slider.destroy();
|
||||
const sliderRef = this.$refs.slider as SliderRef | undefined;
|
||||
if (sliderRef) {
|
||||
sliderRef.destroy();
|
||||
}
|
||||
|
||||
window.removeEventListener('scroll', this.updateCarouselScroll);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -672,18 +672,18 @@ export default mixins(showMessage, nodeHelpers).extend({
|
|||
|
||||
scrollToTop() {
|
||||
setTimeout(() => {
|
||||
const content = this.$refs.content as Element;
|
||||
if (content) {
|
||||
content.scrollTop = 0;
|
||||
const contentRef = this.$refs.content as Element | undefined;
|
||||
if (contentRef) {
|
||||
contentRef.scrollTop = 0;
|
||||
}
|
||||
}, 0);
|
||||
},
|
||||
|
||||
scrollToBottom() {
|
||||
setTimeout(() => {
|
||||
const content = this.$refs.content as Element;
|
||||
if (content) {
|
||||
content.scrollTop = content.scrollHeight;
|
||||
const contentRef = this.$refs.content as Element | undefined;
|
||||
if (contentRef) {
|
||||
contentRef.scrollTop = contentRef.scrollHeight;
|
||||
}
|
||||
}, 0);
|
||||
},
|
||||
|
|
|
@ -61,6 +61,9 @@ import ScopesNotice from '@/components/ScopesNotice.vue';
|
|||
import NodeCredentials from '@/components/NodeCredentials.vue';
|
||||
import { mapStores } from 'pinia';
|
||||
import { useCredentialsStore } from '@/stores/credentials';
|
||||
import { N8nSelect } from 'n8n-design-system';
|
||||
|
||||
type N8nSelectRef = InstanceType<typeof N8nSelect>;
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'CredentialsSelect',
|
||||
|
@ -93,9 +96,9 @@ export default Vue.extend({
|
|||
},
|
||||
methods: {
|
||||
focus() {
|
||||
const select = this.$refs.innerSelect as (Vue & HTMLElement) | undefined;
|
||||
if (select) {
|
||||
select.focus();
|
||||
const selectRef = this.$refs.innerSelect as N8nSelectRef | undefined;
|
||||
if (selectRef) {
|
||||
selectRef.focus();
|
||||
}
|
||||
},
|
||||
/**
|
||||
|
|
|
@ -80,9 +80,9 @@ export default mixins(externalHooks).extend({
|
|||
this.loading = false;
|
||||
|
||||
setTimeout(() => {
|
||||
const element = this.$refs.select as HTMLSelectElement;
|
||||
if (element) {
|
||||
element.focus();
|
||||
const elementRef = this.$refs.select as HTMLSelectElement | undefined;
|
||||
if (elementRef) {
|
||||
elementRef.focus();
|
||||
}
|
||||
}, 0);
|
||||
},
|
||||
|
|
|
@ -55,10 +55,10 @@ export default Vue.extend({
|
|||
},
|
||||
methods: {
|
||||
onMouseMove(e: MouseEvent) {
|
||||
const target = this.$refs.target as HTMLElement;
|
||||
const targetRef = this.$refs.target as HTMLElement | undefined;
|
||||
|
||||
if (target && this.isDragging) {
|
||||
const dim = target.getBoundingClientRect();
|
||||
if (targetRef && this.isDragging) {
|
||||
const dim = targetRef.getBoundingClientRect();
|
||||
|
||||
this.hovering =
|
||||
e.clientX >= dim.left &&
|
||||
|
|
|
@ -115,9 +115,9 @@ export default mixins(showMessage, workflowHelpers, restApi).extend({
|
|||
this.dropdownBus.emit('focus');
|
||||
},
|
||||
focusOnNameInput() {
|
||||
const input = this.$refs.nameInput as HTMLElement;
|
||||
if (input && input.focus) {
|
||||
input.focus();
|
||||
const inputRef = this.$refs.nameInput as HTMLElement | undefined;
|
||||
if (inputRef && inputRef.focus) {
|
||||
inputRef.focus();
|
||||
}
|
||||
},
|
||||
onTagsBlur() {
|
||||
|
|
|
@ -137,6 +137,8 @@ import { useUIStore } from '@/stores/ui';
|
|||
import { Dropdown as ElDropdown } from 'element-ui';
|
||||
import { IAbstractEventMessage } from 'n8n-workflow';
|
||||
|
||||
type RetryDropdownRef = InstanceType<typeof ElDropdown> & { hide: () => void };
|
||||
|
||||
export default mixins(restApi, showMessage, executionHelpers).extend({
|
||||
name: 'execution-preview',
|
||||
components: {
|
||||
|
@ -182,9 +184,9 @@ export default mixins(restApi, showMessage, executionHelpers).extend({
|
|||
},
|
||||
onRetryButtonBlur(event: FocusEvent): void {
|
||||
// Hide dropdown when clicking outside of current document
|
||||
const retryDropdown = this.$refs.retryDropdown as (Vue & { hide: () => void }) | undefined;
|
||||
if (retryDropdown && event.relatedTarget === null) {
|
||||
retryDropdown.hide();
|
||||
const retryDropdownRef = this.$refs.retryDropdown as RetryDropdownRef | undefined;
|
||||
if (retryDropdownRef && event.relatedTarget === null) {
|
||||
retryDropdownRef.hide();
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
@ -77,6 +77,8 @@ import { useUIStore } from '@/stores/ui';
|
|||
import { useWorkflowsStore } from '@/stores/workflows';
|
||||
import { ExecutionFilterType } from '@/Interface';
|
||||
|
||||
type ExecutionCardRef = InstanceType<typeof ExecutionCard>;
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'executions-sidebar',
|
||||
components: {
|
||||
|
@ -144,10 +146,11 @@ export default Vue.extend({
|
|||
methods: {
|
||||
loadMore(limit = 20): void {
|
||||
if (!this.loading) {
|
||||
const executionsList = this.$refs.executionList as HTMLElement;
|
||||
if (executionsList) {
|
||||
const executionsListRef = this.$refs.executionList as HTMLElement | undefined;
|
||||
if (executionsListRef) {
|
||||
const diff =
|
||||
executionsList.offsetHeight - (executionsList.scrollHeight - executionsList.scrollTop);
|
||||
executionsListRef.offsetHeight -
|
||||
(executionsListRef.scrollHeight - executionsListRef.scrollTop);
|
||||
if (diff > -10 && diff < 10) {
|
||||
this.$emit('loadMore', limit);
|
||||
}
|
||||
|
@ -178,16 +181,16 @@ export default Vue.extend({
|
|||
}
|
||||
},
|
||||
checkListSize(): void {
|
||||
const sidebarContainer = this.$refs.container as HTMLElement;
|
||||
const currentExecutionCard = this.$refs[
|
||||
const sidebarContainerRef = this.$refs.container as HTMLElement | undefined;
|
||||
const currentExecutionCardRefs = this.$refs[
|
||||
`execution-${this.workflowsStore.activeWorkflowExecution?.id}`
|
||||
] as Vue[];
|
||||
] as ExecutionCardRef[] | undefined;
|
||||
|
||||
// Find out how many execution card can fit into list
|
||||
// and load more if needed
|
||||
if (sidebarContainer && currentExecutionCard?.length) {
|
||||
const cardElement = currentExecutionCard[0].$el as HTMLElement;
|
||||
const listCapacity = Math.ceil(sidebarContainer.clientHeight / cardElement.clientHeight);
|
||||
if (sidebarContainerRef && currentExecutionCardRefs?.length) {
|
||||
const cardElement = currentExecutionCardRefs[0].$el as HTMLElement;
|
||||
const listCapacity = Math.ceil(sidebarContainerRef.clientHeight / cardElement.clientHeight);
|
||||
|
||||
if (listCapacity > this.executions.length) {
|
||||
this.$emit('loadMore', listCapacity - this.executions.length);
|
||||
|
@ -195,21 +198,21 @@ export default Vue.extend({
|
|||
}
|
||||
},
|
||||
scrollToActiveCard(): void {
|
||||
const executionsList = this.$refs.executionList as HTMLElement;
|
||||
const currentExecutionCard = this.$refs[
|
||||
const executionsListRef = this.$refs.executionList as HTMLElement | undefined;
|
||||
const currentExecutionCardRefs = this.$refs[
|
||||
`execution-${this.workflowsStore.activeWorkflowExecution?.id}`
|
||||
] as Vue[];
|
||||
] as ExecutionCardRef[] | undefined;
|
||||
|
||||
if (
|
||||
executionsList &&
|
||||
currentExecutionCard?.length &&
|
||||
executionsListRef &&
|
||||
currentExecutionCardRefs?.length &&
|
||||
this.workflowsStore.activeWorkflowExecution
|
||||
) {
|
||||
const cardElement = currentExecutionCard[0].$el as HTMLElement;
|
||||
const cardElement = currentExecutionCardRefs[0].$el as HTMLElement;
|
||||
const cardRect = cardElement.getBoundingClientRect();
|
||||
const LIST_HEADER_OFFSET = 200;
|
||||
if (cardRect.top > executionsList.offsetHeight) {
|
||||
executionsList.scrollTo({ top: cardRect.top - LIST_HEADER_OFFSET });
|
||||
if (cardRect.top > executionsListRef.offsetHeight) {
|
||||
executionsListRef.scrollTo({ top: cardRect.top - LIST_HEADER_OFFSET });
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -79,6 +79,8 @@ import { EXPRESSIONS_DOCS_URL } from '@/constants';
|
|||
import type { Segment } from '@/types/expressions';
|
||||
import type { TargetItem } from '@/Interface';
|
||||
|
||||
type InlineExpressionEditorInputRef = InstanceType<typeof InlineExpressionEditorInput>;
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'ExpressionParameterInput',
|
||||
components: {
|
||||
|
@ -127,9 +129,10 @@ export default Vue.extend({
|
|||
},
|
||||
methods: {
|
||||
focus() {
|
||||
const inlineInput = this.$refs.inlineInput as (Vue & HTMLElement) | undefined;
|
||||
|
||||
if (inlineInput?.$el) inlineInput.focus();
|
||||
const inlineInputRef = this.$refs.inlineInput as InlineExpressionEditorInputRef | undefined;
|
||||
if (inlineInputRef?.$el) {
|
||||
inlineInputRef.focus();
|
||||
}
|
||||
},
|
||||
onFocus() {
|
||||
this.isFocused = true;
|
||||
|
|
|
@ -169,11 +169,12 @@ export default mixins(expressionManager).extend({
|
|||
|
||||
methods: {
|
||||
root() {
|
||||
const root = this.$refs.htmlEditor as HTMLDivElement | undefined;
|
||||
const rootRef = this.$refs.htmlEditor as HTMLDivElement | undefined;
|
||||
if (!rootRef) {
|
||||
throw new Error('Expected div with ref "htmlEditor"');
|
||||
}
|
||||
|
||||
if (!root) throw new Error('Expected div with ref "htmlEditor"');
|
||||
|
||||
return root;
|
||||
return rootRef;
|
||||
},
|
||||
|
||||
isMissingHtmlTags() {
|
||||
|
|
|
@ -65,9 +65,9 @@ export default mixins(showMessage).extend({
|
|||
this.isNameEdit = true;
|
||||
|
||||
setTimeout(() => {
|
||||
const input = this.$refs.nameInput as HTMLInputElement;
|
||||
if (input) {
|
||||
input.focus();
|
||||
const inputRef = this.$refs.nameInput as HTMLInputElement | undefined;
|
||||
if (inputRef) {
|
||||
inputRef.focus();
|
||||
}
|
||||
}, 0);
|
||||
},
|
||||
|
|
|
@ -424,9 +424,9 @@ export default mixins(workflowHelpers).extend({
|
|||
this.$root.$emit('importWorkflowData', { data: workflowData });
|
||||
};
|
||||
|
||||
const input = this.$refs.importFile as HTMLInputElement;
|
||||
if (input !== null && input.files !== null && input.files.length !== 0) {
|
||||
reader.readAsText(input!.files[0]!);
|
||||
const inputRef = this.$refs.importFile as HTMLInputElement | undefined;
|
||||
if (inputRef?.files && inputRef.files.length !== 0) {
|
||||
reader.readAsText(inputRef.files[0]);
|
||||
}
|
||||
},
|
||||
async onWorkflowMenuSelect(action: string): Promise<void> {
|
||||
|
|
|
@ -70,9 +70,9 @@ export default Vue.extend({
|
|||
this.newName = this.value;
|
||||
this.editName = true;
|
||||
this.$nextTick(() => {
|
||||
const input = this.$refs.input;
|
||||
if (input) {
|
||||
(input as HTMLInputElement).focus();
|
||||
const inputRef = this.$refs.input as HTMLInputElement | undefined;
|
||||
if (inputRef) {
|
||||
inputRef.focus();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
@ -111,7 +111,7 @@ import { useWorkflowsStore } from '@/stores/workflows';
|
|||
import { useNDVStore } from '@/stores/ndv';
|
||||
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||
|
||||
type RunDataRef = Vue & { enterEditMode: (args: EnterEditModeArgs) => void };
|
||||
type RunDataRef = InstanceType<typeof RunData>;
|
||||
|
||||
export default mixins(pinData).extend({
|
||||
name: 'OutputPanel',
|
||||
|
@ -242,8 +242,9 @@ export default mixins(pinData).extend({
|
|||
},
|
||||
methods: {
|
||||
insertTestData() {
|
||||
if (this.$refs.runData) {
|
||||
(this.$refs.runData as RunDataRef).enterEditMode({
|
||||
const runDataRef = this.$refs.runData as RunDataRef | undefined;
|
||||
if (runDataRef) {
|
||||
runDataRef.enterEditMode({
|
||||
origin: 'insertTestDataLink',
|
||||
});
|
||||
|
||||
|
|
|
@ -375,6 +375,8 @@ import { useNodeTypesStore } from '@/stores/nodeTypes';
|
|||
import { useCredentialsStore } from '@/stores/credentials';
|
||||
import { htmlEditorEventBus } from '@/event-bus';
|
||||
|
||||
type ResourceLocatorRef = InstanceType<typeof ResourceLocator>;
|
||||
|
||||
export default mixins(
|
||||
externalHooks,
|
||||
nodeHelpers,
|
||||
|
@ -1099,10 +1101,9 @@ export default mixins(
|
|||
}
|
||||
} else if (command === 'refreshOptions') {
|
||||
if (this.isResourceLocatorParameter) {
|
||||
const resourceLocator = this.$refs.resourceLocator;
|
||||
if (resourceLocator) {
|
||||
(resourceLocator as Vue).$emit('refreshList');
|
||||
}
|
||||
const resourceLocatorRef = this.$refs.resourceLocator as ResourceLocatorRef | undefined;
|
||||
|
||||
resourceLocatorRef?.$emit('refreshList');
|
||||
}
|
||||
this.loadRemoteParameterOptions();
|
||||
} else if (command === 'formatHtml') {
|
||||
|
|
|
@ -65,6 +65,8 @@ import { INodeParameterResourceLocator, INodeProperties, IParameterLabel } from
|
|||
import { mapStores } from 'pinia';
|
||||
import { useWorkflowsStore } from '@/stores/workflows';
|
||||
|
||||
type ParamRef = InstanceType<typeof ParameterInputWrapper>;
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'parameter-input-expanded',
|
||||
components: {
|
||||
|
@ -145,7 +147,7 @@ export default Vue.extend({
|
|||
},
|
||||
optionSelected(command: string) {
|
||||
if (this.$refs.param) {
|
||||
(this.$refs.param as Vue).$emit('optionSelected', command);
|
||||
(this.$refs.param as ParamRef).$emit('optionSelected', command);
|
||||
}
|
||||
},
|
||||
valueChanged(parameterData: IUpdateInformation) {
|
||||
|
|
|
@ -92,6 +92,8 @@ import { useSegment } from '@/stores/segment';
|
|||
import { externalHooks } from '@/mixins/externalHooks';
|
||||
import { getMappedResult } from '../utils/mappingUtils';
|
||||
|
||||
type ParamterInputWrapperRef = InstanceType<typeof ParameterInputWrapper>;
|
||||
|
||||
const DISPLAY_MODES_WITH_DATA_MAPPING = ['table', 'json', 'schema'];
|
||||
|
||||
export default mixins(showMessage, externalHooks).extend({
|
||||
|
@ -219,18 +221,17 @@ export default mixins(showMessage, externalHooks).extend({
|
|||
this.menuExpanded = expanded;
|
||||
},
|
||||
optionSelected(command: string) {
|
||||
if (this.$refs.param) {
|
||||
(this.$refs.param as Vue).$emit('optionSelected', command);
|
||||
}
|
||||
const paramRef = this.$refs.param as ParamterInputWrapperRef | undefined;
|
||||
paramRef?.$emit('optionSelected', command);
|
||||
},
|
||||
valueChanged(parameterData: IUpdateInformation) {
|
||||
this.$emit('valueChanged', parameterData);
|
||||
},
|
||||
onTextInput(parameterData: IUpdateInformation) {
|
||||
const param = this.$refs.param as Vue | undefined;
|
||||
const paramRef = this.$refs.param as ParamterInputWrapperRef | undefined;
|
||||
|
||||
if (isValueExpression(this.parameter, parameterData.value)) {
|
||||
param?.$emit('optionSelected', 'addExpression');
|
||||
paramRef?.$emit('optionSelected', 'addExpression');
|
||||
}
|
||||
},
|
||||
onDrop(newParamValue: string) {
|
||||
|
|
|
@ -62,6 +62,8 @@ import { isValueExpression } from '@/utils';
|
|||
import { mapStores } from 'pinia';
|
||||
import { useNDVStore } from '@/stores/ndv';
|
||||
|
||||
type ParamRef = InstanceType<typeof ParameterInput>;
|
||||
|
||||
export default mixins(showMessage, workflowHelpers).extend({
|
||||
name: 'parameter-input-wrapper',
|
||||
components: {
|
||||
|
@ -208,9 +210,9 @@ export default mixins(showMessage, workflowHelpers).extend({
|
|||
this.$emit('drop', data);
|
||||
},
|
||||
optionSelected(command: string) {
|
||||
if (this.$refs.param) {
|
||||
(this.$refs.param as Vue).$emit('optionSelected', command);
|
||||
}
|
||||
const paramRef = this.$refs.param as ParamRef | undefined;
|
||||
|
||||
paramRef?.$emit('optionSelected', command);
|
||||
},
|
||||
onValueChanged(parameterData: IUpdateInformation) {
|
||||
this.$emit('valueChanged', parameterData);
|
||||
|
|
|
@ -166,6 +166,8 @@ import { useRootStore } from '@/stores/n8nRootStore';
|
|||
import { useNDVStore } from '@/stores/ndv';
|
||||
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||
|
||||
type ResourceLocatorDropdownRef = InstanceType<typeof ResourceLocatorDropdown>;
|
||||
|
||||
interface IResourceLocatorQuery {
|
||||
results: INodeListSearchItems[];
|
||||
nextPageToken: unknown;
|
||||
|
@ -407,9 +409,9 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
|
|||
watch: {
|
||||
currentQueryError(curr: boolean, prev: boolean) {
|
||||
if (this.showResourceDropdown && curr && !prev) {
|
||||
const input = this.$refs.input;
|
||||
if (input) {
|
||||
(input as HTMLElement).focus();
|
||||
const inputRef = this.$refs.input as HTMLInputElement | undefined;
|
||||
if (inputRef) {
|
||||
inputRef.focus();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -445,7 +447,7 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
|
|||
},
|
||||
methods: {
|
||||
setWidth() {
|
||||
const containerRef = this.$refs.container as HTMLElement;
|
||||
const containerRef = this.$refs.container as HTMLElement | undefined;
|
||||
if (containerRef) {
|
||||
this.width = containerRef?.offsetWidth;
|
||||
}
|
||||
|
@ -465,9 +467,9 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
|
|||
this.trackEvent('User refreshed resource locator list');
|
||||
},
|
||||
onKeyDown(e: MouseEvent) {
|
||||
const dropdown = this.$refs.dropdown;
|
||||
if (dropdown && this.showResourceDropdown && !this.isSearchable) {
|
||||
(dropdown as Vue).$emit('keyDown', e);
|
||||
const dropdownRef = this.$refs.dropdown as ResourceLocatorDropdownRef | undefined;
|
||||
if (dropdownRef && this.showResourceDropdown && !this.isSearchable) {
|
||||
dropdownRef.$emit('keyDown', e);
|
||||
}
|
||||
},
|
||||
openResource(url: string) {
|
||||
|
|
|
@ -167,18 +167,21 @@ export default Vue.extend({
|
|||
window.open(url, '_blank');
|
||||
},
|
||||
onKeyDown(e: KeyboardEvent) {
|
||||
const container = this.$refs.resultsContainer as HTMLElement;
|
||||
const containerRef = this.$refs.resultsContainer as HTMLElement | undefined;
|
||||
|
||||
if (e.key === 'ArrowDown') {
|
||||
if (this.hoverIndex < this.sortedResources.length - 1) {
|
||||
this.hoverIndex++;
|
||||
|
||||
const items = this.$refs[`item-${this.hoverIndex}`] as HTMLElement[];
|
||||
if (container && Array.isArray(items) && items.length === 1) {
|
||||
const item = items[0];
|
||||
if (item.offsetTop + item.clientHeight > container.scrollTop + container.offsetHeight) {
|
||||
const top = item.offsetTop - container.offsetHeight + item.clientHeight;
|
||||
container.scrollTo({ top });
|
||||
const itemRefs = this.$refs[`item-${this.hoverIndex}`] as HTMLElement[] | undefined;
|
||||
if (containerRef && Array.isArray(itemRefs) && itemRefs.length === 1) {
|
||||
const item = itemRefs[0];
|
||||
if (
|
||||
item.offsetTop + item.clientHeight >
|
||||
containerRef.scrollTop + containerRef.offsetHeight
|
||||
) {
|
||||
const top = item.offsetTop - containerRef.offsetHeight + item.clientHeight;
|
||||
containerRef.scrollTo({ top });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -187,11 +190,11 @@ export default Vue.extend({
|
|||
this.hoverIndex--;
|
||||
|
||||
const searchOffset = this.filterable ? SEARCH_BAR_HEIGHT_PX : 0;
|
||||
const items = this.$refs[`item-${this.hoverIndex}`] as HTMLElement[];
|
||||
if (container && Array.isArray(items) && items.length === 1) {
|
||||
const item = items[0];
|
||||
if (item.offsetTop <= container.scrollTop + searchOffset) {
|
||||
container.scrollTo({ top: item.offsetTop - searchOffset });
|
||||
const itemRefs = this.$refs[`item-${this.hoverIndex}`] as HTMLElement[] | undefined;
|
||||
if (containerRef && Array.isArray(itemRefs) && itemRefs.length === 1) {
|
||||
const item = itemRefs[0];
|
||||
if (item.offsetTop <= containerRef.scrollTop + searchOffset) {
|
||||
containerRef.scrollTo({ top: item.offsetTop - searchOffset });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -225,9 +228,10 @@ export default Vue.extend({
|
|||
return;
|
||||
}
|
||||
|
||||
const container = this.$refs.resultsContainer as HTMLElement;
|
||||
if (container) {
|
||||
const diff = container.offsetHeight - (container.scrollHeight - container.scrollTop);
|
||||
const containerRef = this.$refs.resultsContainer as HTMLElement | undefined;
|
||||
if (containerRef) {
|
||||
const diff =
|
||||
containerRef.offsetHeight - (containerRef.scrollHeight - containerRef.scrollTop);
|
||||
if (diff > -SCROLL_MARGIN_PX && diff < SCROLL_MARGIN_PX) {
|
||||
this.$emit('loadMore');
|
||||
}
|
||||
|
|
|
@ -1146,9 +1146,9 @@ export default mixins(externalHooks, genericHelpers, nodeHelpers, pinData).exten
|
|||
const previous = this.displayMode;
|
||||
this.ndvStore.setPanelDisplayMode({ pane: this.paneType, mode: displayMode });
|
||||
|
||||
const dataContainer = this.$refs.dataContainer;
|
||||
if (dataContainer) {
|
||||
const dataDisplay = (dataContainer as Element).children[0];
|
||||
const dataContainerRef = this.$refs.dataContainer as Element | undefined;
|
||||
if (dataContainerRef) {
|
||||
const dataDisplay = dataContainerRef.children[0];
|
||||
|
||||
if (dataDisplay) {
|
||||
dataDisplay.scrollTo(0, 0);
|
||||
|
|
|
@ -178,6 +178,8 @@ import { getMappedExpression } from '@/utils/mappingUtils';
|
|||
|
||||
const MAX_COLUMNS_LIMIT = 40;
|
||||
|
||||
type DraggableRef = InstanceType<typeof Draggable>;
|
||||
|
||||
export default mixins(externalHooks).extend({
|
||||
name: 'run-data-table',
|
||||
components: { Draggable, MappingPill },
|
||||
|
@ -225,7 +227,7 @@ export default mixins(externalHooks).extend({
|
|||
},
|
||||
mounted() {
|
||||
if (this.tableData && this.tableData.columns && this.$refs.draggable) {
|
||||
const tbody = (this.$refs.draggable as Vue).$refs.wrapper as HTMLElement;
|
||||
const tbody = (this.$refs.draggable as DraggableRef).$refs.wrapper;
|
||||
if (tbody) {
|
||||
this.$emit('mounted', {
|
||||
avgRowHeight: tbody.offsetHeight / this.tableData.data.length,
|
||||
|
|
|
@ -66,6 +66,11 @@ import { useUIStore } from '@/stores/ui';
|
|||
import { useTagsStore } from '@/stores/tags';
|
||||
import { EventBus } from '@/event-bus';
|
||||
import { PropType } from 'vue';
|
||||
import { N8nOption, N8nSelect } from 'n8n-design-system';
|
||||
|
||||
type SelectRef = InstanceType<typeof N8nSelect>;
|
||||
type TagRef = InstanceType<typeof N8nOption>;
|
||||
type CreateRef = InstanceType<typeof N8nOption>;
|
||||
|
||||
const MANAGE_KEY = '__manage';
|
||||
const CREATE_KEY = '__create';
|
||||
|
@ -74,7 +79,10 @@ export default mixins(showMessage).extend({
|
|||
name: 'TagsDropdown',
|
||||
props: {
|
||||
placeholder: {},
|
||||
currentTagIds: {},
|
||||
currentTagIds: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => [],
|
||||
},
|
||||
createEnabled: {},
|
||||
eventBus: {
|
||||
type: Object as PropType<EventBus>,
|
||||
|
@ -90,10 +98,8 @@ export default mixins(showMessage).extend({
|
|||
};
|
||||
},
|
||||
mounted() {
|
||||
// @ts-ignore
|
||||
const select = (this.$refs.select &&
|
||||
this.$refs.select.$refs &&
|
||||
this.$refs.select.$refs.innerSelect) as Vue | undefined;
|
||||
const selectRef = this.$refs.select as SelectRef | undefined;
|
||||
const select = selectRef?.$refs?.innerSelect;
|
||||
if (select) {
|
||||
const input = select.$refs.input as Element | undefined;
|
||||
if (input) {
|
||||
|
@ -107,10 +113,8 @@ export default mixins(showMessage).extend({
|
|||
this.$data.preventUpdate = true;
|
||||
this.$emit('blur');
|
||||
|
||||
// @ts-ignore
|
||||
if (this.$refs.select && typeof this.$refs.select.blur === 'function') {
|
||||
// @ts-ignore
|
||||
this.$refs.select.blur();
|
||||
if (typeof selectRef?.blur === 'function') {
|
||||
selectRef.blur();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -183,31 +187,27 @@ export default mixins(showMessage).extend({
|
|||
}
|
||||
},
|
||||
focusOnTopOption() {
|
||||
const tags = this.$refs.tag as Vue[] | undefined;
|
||||
const create = this.$refs.create as Vue | undefined;
|
||||
//@ts-ignore // focus on create option
|
||||
if (create && create.hoverItem) {
|
||||
// @ts-ignore
|
||||
create.hoverItem();
|
||||
const tagRefs = this.$refs.tag as TagRef[] | undefined;
|
||||
const createRef = this.$refs.create as CreateRef | undefined;
|
||||
// focus on create option
|
||||
if (createRef && createRef.hoverItem) {
|
||||
createRef.hoverItem();
|
||||
}
|
||||
//@ts-ignore // focus on top option after filter
|
||||
else if (tags && tags[0] && tags[0].hoverItem) {
|
||||
// @ts-ignore
|
||||
tags[0].hoverItem();
|
||||
// focus on top option after filter
|
||||
else if (tagRefs && tagRefs[0] && tagRefs[0].hoverItem) {
|
||||
tagRefs[0].hoverItem();
|
||||
}
|
||||
},
|
||||
focusOnTag(tagId: string) {
|
||||
const tagOptions = (this.$refs.tag as Vue[]) || [];
|
||||
const tagOptions = (this.$refs.tag as TagRef[]) || [];
|
||||
if (tagOptions && tagOptions.length) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const added = tagOptions.find((ref: any) => ref.value === tagId);
|
||||
const added = tagOptions.find((ref) => ref.value === tagId);
|
||||
}
|
||||
},
|
||||
focusOnInput() {
|
||||
const select = this.$refs.select as Vue | undefined;
|
||||
if (select) {
|
||||
// @ts-ignore
|
||||
select.focusOnInput();
|
||||
const selectRef = this.$refs.select as SelectRef | undefined;
|
||||
if (selectRef) {
|
||||
selectRef.focusOnInput();
|
||||
this.focused = true;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -107,9 +107,14 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Table as ElTable } from 'element-ui';
|
||||
import { MAX_TAG_NAME_LENGTH } from '@/constants';
|
||||
import { ITagRow } from '@/Interface';
|
||||
import Vue from 'vue';
|
||||
import { N8nInput } from 'n8n-design-system';
|
||||
|
||||
type TableRef = InstanceType<typeof ElTable>;
|
||||
type N8nInputRef = InstanceType<typeof N8nInput>;
|
||||
|
||||
const INPUT_TRANSITION_TIMEOUT = 350;
|
||||
const DELETE_TRANSITION_TIMEOUT = 100;
|
||||
|
@ -173,26 +178,28 @@ export default Vue.extend({
|
|||
|
||||
focusOnInput(): void {
|
||||
setTimeout(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const input = this.$refs.nameInput as any;
|
||||
if (input && input.focus) {
|
||||
input.focus();
|
||||
const inputRef = this.$refs.nameInput as N8nInputRef | undefined;
|
||||
if (inputRef && inputRef.focus) {
|
||||
inputRef.focus();
|
||||
}
|
||||
}, INPUT_TRANSITION_TIMEOUT);
|
||||
},
|
||||
|
||||
focusOnDelete(): void {
|
||||
setTimeout(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const input = this.$refs.deleteHiddenInput as any;
|
||||
if (input && input.focus) {
|
||||
input.focus();
|
||||
const inputRef = this.$refs.deleteHiddenInput as N8nInputRef | undefined;
|
||||
if (inputRef && inputRef.focus) {
|
||||
inputRef.focus();
|
||||
}
|
||||
}, DELETE_TRANSITION_TIMEOUT);
|
||||
},
|
||||
|
||||
focusOnCreate(): void {
|
||||
((this.$refs.table as Vue).$refs.bodyWrapper as Element).scrollTop = 0;
|
||||
const bodyWrapperRef = (this.$refs.table as TableRef).$refs.bodyWrapper as HTMLElement;
|
||||
if (bodyWrapperRef) {
|
||||
bodyWrapperRef.scrollTop = 0;
|
||||
}
|
||||
|
||||
this.focusOnInput();
|
||||
},
|
||||
},
|
||||
|
|
|
@ -76,12 +76,12 @@ export default mixins(genericHelpers).extend({
|
|||
},
|
||||
methods: {
|
||||
onScroll() {
|
||||
const el = this.$refs.loader;
|
||||
if (!el || this.loading) {
|
||||
const loaderRef = this.$refs.loader as HTMLElement | undefined;
|
||||
if (!loaderRef || this.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rect = (el as Element).getBoundingClientRect();
|
||||
const rect = loaderRef.getBoundingClientRect();
|
||||
const inView =
|
||||
rect.top >= 0 &&
|
||||
rect.left >= 0 &&
|
||||
|
|
|
@ -113,6 +113,9 @@ import { useUIStore } from '@/stores/ui';
|
|||
import { useWorkflowsStore } from '@/stores/workflows';
|
||||
import { useNDVStore } from '@/stores/ndv';
|
||||
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||
import { N8nInfoAccordion } from 'n8n-design-system';
|
||||
|
||||
type HelpRef = InstanceType<typeof N8nInfoAccordion>;
|
||||
|
||||
export default mixins(workflowHelpers, copyPaste, showMessage).extend({
|
||||
name: 'TriggerPanel',
|
||||
|
@ -355,7 +358,7 @@ export default mixins(workflowHelpers, copyPaste, showMessage).extend({
|
|||
methods: {
|
||||
expandExecutionHelp() {
|
||||
if (this.$refs.help) {
|
||||
(this.$refs.help as Vue).$emit('expand');
|
||||
(this.$refs.help as HelpRef).$emit('expand');
|
||||
}
|
||||
},
|
||||
onLinkClick(e: MouseEvent) {
|
||||
|
|
|
@ -82,6 +82,8 @@ import { useSettingsStore } from '@/stores/settings';
|
|||
import { useUsersStore } from '@/stores/users';
|
||||
import { useWorkflowsStore } from '@/stores/workflows';
|
||||
|
||||
type ActivatorRef = InstanceType<typeof WorkflowActivator>;
|
||||
|
||||
export const WORKFLOW_LIST_ITEM_ACTIONS = {
|
||||
OPEN: 'open',
|
||||
SHARE: 'share',
|
||||
|
@ -165,7 +167,7 @@ export default mixins(showMessage, restApi).extend({
|
|||
methods: {
|
||||
async onClick(event?: PointerEvent) {
|
||||
if (event) {
|
||||
if ((this.$refs.activator as Vue)?.$el.contains(event.target as HTMLElement)) {
|
||||
if ((this.$refs.activator as ActivatorRef)?.$el.contains(event.target as HTMLElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -96,9 +96,9 @@ export default mixins(showMessage).extend({
|
|||
throw new Error(this.$locale.baseText('workflowPreview.showError.arrayEmpty'));
|
||||
}
|
||||
|
||||
const iframe = this.$refs.preview_iframe as HTMLIFrameElement;
|
||||
if (iframe.contentWindow) {
|
||||
iframe.contentWindow.postMessage(
|
||||
const iframeRef = this.$refs.preview_iframe as HTMLIFrameElement | undefined;
|
||||
if (iframeRef?.contentWindow) {
|
||||
iframeRef.contentWindow.postMessage(
|
||||
JSON.stringify({
|
||||
command: 'openWorkflow',
|
||||
workflow: this.workflow,
|
||||
|
@ -119,9 +119,9 @@ export default mixins(showMessage).extend({
|
|||
if (!this.executionId) {
|
||||
throw new Error(this.$locale.baseText('workflowPreview.showError.missingExecution'));
|
||||
}
|
||||
const iframe = this.$refs.preview_iframe as HTMLIFrameElement;
|
||||
if (iframe.contentWindow) {
|
||||
iframe.contentWindow.postMessage(
|
||||
const iframeRef = this.$refs.preview_iframe as HTMLIFrameElement | undefined;
|
||||
if (iframeRef?.contentWindow) {
|
||||
iframeRef.contentWindow.postMessage(
|
||||
JSON.stringify({
|
||||
command: 'openExecution',
|
||||
executionId: this.executionId,
|
||||
|
|
|
@ -196,7 +196,8 @@ import ResourceFiltersDropdown from '@/components/forms/ResourceFiltersDropdown.
|
|||
import { mapStores } from 'pinia';
|
||||
import { useSettingsStore } from '@/stores/settings';
|
||||
import { useUsersStore } from '@/stores/users';
|
||||
import { DatatableColumn } from 'n8n-design-system';
|
||||
import { N8nInput } from 'n8n-design-system';
|
||||
import type { DatatableColumn } from 'n8n-design-system';
|
||||
|
||||
export interface IResource {
|
||||
id: string;
|
||||
|
@ -216,6 +217,7 @@ interface IFilters {
|
|||
}
|
||||
|
||||
type IResourceKeyType = 'credentials' | 'workflows';
|
||||
type SearchRef = InstanceType<typeof N8nInput>;
|
||||
|
||||
const filterKeys = ['ownedBy', 'sharedWith'];
|
||||
|
||||
|
@ -405,7 +407,7 @@ export default mixins(showMessage, debounceHelper).extend({
|
|||
},
|
||||
focusSearchInput() {
|
||||
if (this.$refs.search) {
|
||||
(this.$refs.search as Vue & { focus: () => void }).focus();
|
||||
(this.$refs.search as SearchRef).focus();
|
||||
}
|
||||
},
|
||||
setOwnerSubview(active: boolean) {
|
||||
|
|
|
@ -1,39 +1,43 @@
|
|||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import Vue from 'vue';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
function broadcast(componentName: string, eventName: string, params: any) {
|
||||
// @ts-ignore
|
||||
(this as Vue).$children.forEach((child) => {
|
||||
function broadcast(
|
||||
this: InstanceType<typeof EmitterMixin>,
|
||||
componentName: string,
|
||||
eventName: string,
|
||||
params: any,
|
||||
) {
|
||||
this.$children.forEach((child) => {
|
||||
const name = child.$options.name;
|
||||
|
||||
if (name === componentName) {
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line prefer-spread
|
||||
child.$emit.apply(child, [eventName].concat(params));
|
||||
child.$emit.apply(child, [eventName].concat(params) as Parameters<typeof child.$emit>);
|
||||
} else {
|
||||
// @ts-ignore
|
||||
broadcast.apply(child, [componentName, eventName].concat([params]));
|
||||
broadcast.apply(
|
||||
child as InstanceType<typeof EmitterMixin>,
|
||||
[componentName, eventName].concat([params]) as Parameters<typeof broadcast>,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default Vue.extend({
|
||||
const EmitterMixin = defineComponent({
|
||||
methods: {
|
||||
$dispatch(componentName: string, eventName: string, params: any) {
|
||||
let parent = this.$parent || this.$root;
|
||||
let name = parent.$options.name;
|
||||
|
||||
while (parent && (!name || name !== componentName)) {
|
||||
parent = parent.$parent;
|
||||
parent = parent.$parent as InstanceType<typeof EmitterMixin>;
|
||||
|
||||
if (parent) {
|
||||
name = parent.$options.name;
|
||||
}
|
||||
}
|
||||
if (parent) {
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line prefer-spread
|
||||
parent.$emit.apply(parent, [eventName].concat(params));
|
||||
parent.$emit.apply(parent, [eventName].concat(params) as Parameters<typeof parent.$emit>);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -42,3 +46,5 @@ export default Vue.extend({
|
|||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default EmitterMixin;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// @ts-nocheck
|
||||
|
||||
import Vue from 'vue';
|
||||
import Fragment from 'vue-fragment';
|
||||
import VueAgile from 'vue-agile';
|
||||
|
@ -8,7 +6,7 @@ import 'regenerator-runtime/runtime';
|
|||
|
||||
import ElementUI from 'element-ui';
|
||||
import { Loading, MessageBox, Notification } from 'element-ui';
|
||||
import { designSystemComponents } from 'n8n-design-system';
|
||||
import { N8nPlugin } from 'n8n-design-system';
|
||||
import EnterpriseEdition from '@/components/EnterpriseEdition.ee.vue';
|
||||
import { useMessage } from '@/composables/useMessage';
|
||||
|
||||
|
@ -16,7 +14,7 @@ Vue.use(Fragment.Plugin);
|
|||
Vue.use(VueAgile);
|
||||
|
||||
Vue.use(ElementUI);
|
||||
Vue.use(designSystemComponents);
|
||||
Vue.use(N8nPlugin);
|
||||
|
||||
Vue.component('enterprise-edition', EnterpriseEdition);
|
||||
|
||||
|
|
|
@ -402,9 +402,9 @@ export default mixins(
|
|||
this.canvasStore.setRecenteredCanvasAddButtonPosition(this.getNodeViewOffsetPosition);
|
||||
},
|
||||
nodeViewScale(newScale) {
|
||||
const element = this.$refs.nodeView as HTMLDivElement;
|
||||
if (element) {
|
||||
element.style.transform = `scale(${newScale})`;
|
||||
const elementRef = this.$refs.nodeView as HTMLDivElement | undefined;
|
||||
if (elementRef) {
|
||||
elementRef.style.transform = `scale(${newScale})`;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
@ -170,6 +170,9 @@ import { useSettingsStore } from '@/stores/settings';
|
|||
import { getLdapSynchronizations } from '@/api/ldap';
|
||||
import { N8N_CONTACT_EMAIL, N8N_SALES_EMAIL } from '@/constants';
|
||||
import { createEventBus } from '@/event-bus';
|
||||
import { N8nFormInputs } from 'n8n-design-system';
|
||||
|
||||
type N8nFormInputsRef = InstanceType<typeof N8nFormInputs>;
|
||||
|
||||
type FormValues = {
|
||||
loginEnabled: boolean;
|
||||
|
@ -295,32 +298,33 @@ export default mixins(showMessage).extend({
|
|||
async onSubmit(): Promise<void> {
|
||||
// We want to save all form values (incl. the hidden onces), so we are using
|
||||
// `values` data prop of the `FormInputs` child component since they are all preserved there
|
||||
const formInputs = this.$refs.ldapConfigForm as (Vue & { values: FormValues }) | undefined;
|
||||
if (!this.hasAnyChanges || !formInputs) {
|
||||
const formInputsRef = this.$refs.ldapConfigForm as N8nFormInputsRef | undefined;
|
||||
if (!this.hasAnyChanges || !formInputsRef) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newConfiguration: ILdapConfig = {
|
||||
loginEnabled: formInputs.values.loginEnabled,
|
||||
loginLabel: formInputs.values.loginLabel,
|
||||
connectionUrl: formInputs.values.serverAddress,
|
||||
allowUnauthorizedCerts: formInputs.values.allowUnauthorizedCerts,
|
||||
connectionPort: +formInputs.values.port,
|
||||
connectionSecurity: formInputs.values.connectionSecurity,
|
||||
baseDn: formInputs.values.baseDn,
|
||||
bindingAdminDn: formInputs.values.bindingType === 'admin' ? formInputs.values.adminDn : '',
|
||||
loginEnabled: formInputsRef.values.loginEnabled,
|
||||
loginLabel: formInputsRef.values.loginLabel,
|
||||
connectionUrl: formInputsRef.values.serverAddress,
|
||||
allowUnauthorizedCerts: formInputsRef.values.allowUnauthorizedCerts,
|
||||
connectionPort: +formInputsRef.values.port,
|
||||
connectionSecurity: formInputsRef.values.connectionSecurity,
|
||||
baseDn: formInputsRef.values.baseDn,
|
||||
bindingAdminDn:
|
||||
formInputsRef.values.bindingType === 'admin' ? formInputsRef.values.adminDn : '',
|
||||
bindingAdminPassword:
|
||||
formInputs.values.bindingType === 'admin' ? formInputs.values.adminPassword : '',
|
||||
emailAttribute: formInputs.values.email,
|
||||
firstNameAttribute: formInputs.values.firstName,
|
||||
lastNameAttribute: formInputs.values.lastName,
|
||||
loginIdAttribute: formInputs.values.loginId,
|
||||
ldapIdAttribute: formInputs.values.ldapId,
|
||||
userFilter: formInputs.values.userFilter,
|
||||
synchronizationEnabled: formInputs.values.synchronizationEnabled,
|
||||
synchronizationInterval: +formInputs.values.synchronizationInterval,
|
||||
searchPageSize: +formInputs.values.pageSize,
|
||||
searchTimeout: +formInputs.values.searchTimeout,
|
||||
formInputsRef.values.bindingType === 'admin' ? formInputsRef.values.adminPassword : '',
|
||||
emailAttribute: formInputsRef.values.email,
|
||||
firstNameAttribute: formInputsRef.values.firstName,
|
||||
lastNameAttribute: formInputsRef.values.lastName,
|
||||
loginIdAttribute: formInputsRef.values.loginId,
|
||||
ldapIdAttribute: formInputsRef.values.ldapId,
|
||||
userFilter: formInputsRef.values.userFilter,
|
||||
synchronizationEnabled: formInputsRef.values.synchronizationEnabled,
|
||||
synchronizationInterval: +formInputsRef.values.synchronizationInterval,
|
||||
searchPageSize: +formInputsRef.values.pageSize,
|
||||
searchTimeout: +formInputsRef.values.searchTimeout,
|
||||
};
|
||||
|
||||
let saveForm = true;
|
||||
|
|
Loading…
Reference in a new issue