feat: Replace new Vue() with custom event bus (no-changelog) (#5780)

* refactor: replace new Vue() with custom event bus (no-changelog)

* fix: export types from design system main

* fix: update component types

* fix: update form inputs event bus
This commit is contained in:
Alex Grozav
2023-04-06 16:32:45 +03:00
committed by GitHub
parent 89c12fc1a7
commit 5651a52364
67 changed files with 347 additions and 210 deletions

View File

@@ -7,7 +7,8 @@
"name": "Mutasem Aldmour", "name": "Mutasem Aldmour",
"email": "mutasem@n8n.io" "email": "mutasem@n8n.io"
}, },
"main": "src/main.js", "main": "src/main.ts",
"import": "src/main.ts",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/n8n-io/n8n.git" "url": "git+https://github.com/n8n-io/n8n.git"

View File

@@ -43,6 +43,7 @@ import N8nFormInputs from '../N8nFormInputs';
import N8nHeading from '../N8nHeading'; import N8nHeading from '../N8nHeading';
import N8nLink from '../N8nLink'; import N8nLink from '../N8nLink';
import N8nButton from '../N8nButton'; import N8nButton from '../N8nButton';
import { createEventBus } from '../../utils';
export default Vue.extend({ export default Vue.extend({
name: 'n8n-form-box', name: 'n8n-form-box',
@@ -81,7 +82,7 @@ export default Vue.extend({
}, },
data() { data() {
return { return {
formBus: new Vue(), formBus: createEventBus(),
}; };
}, },
methods: { methods: {
@@ -92,7 +93,7 @@ export default Vue.extend({
this.$emit('submit', e); this.$emit('submit', e);
}, },
onButtonClick() { onButtonClick() {
this.formBus.$emit('submit'); this.formBus.emit('submit');
}, },
onSecondaryButtonClick(event: Event) { onSecondaryButtonClick(event: Event) {
this.$emit('secondaryClick', event); this.$emit('secondaryClick', event);

View File

@@ -37,10 +37,11 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue, { PropType } from 'vue';
import N8nFormInput from '../N8nFormInput'; import N8nFormInput from '../N8nFormInput';
import type { IFormInput } from '../../types'; import type { IFormInput } from '../../types';
import ResizeObserver from '../ResizeObserver'; import ResizeObserver from '../ResizeObserver';
import { EventBus } from '@/utils';
export default Vue.extend({ export default Vue.extend({
name: 'n8n-form-inputs', name: 'n8n-form-inputs',
@@ -56,7 +57,7 @@ export default Vue.extend({
}, },
}, },
eventBus: { eventBus: {
type: Vue, type: Object as PropType<EventBus>,
}, },
columnView: { columnView: {
type: Boolean, type: Boolean,
@@ -83,7 +84,7 @@ export default Vue.extend({
}); });
if (this.eventBus) { if (this.eventBus) {
this.eventBus.$on('submit', this.onSubmit); // eslint-disable-line @typescript-eslint/unbound-method this.eventBus.on('submit', this.onSubmit); // eslint-disable-line @typescript-eslint/unbound-method
} }
}, },
computed: { computed: {

View File

@@ -52,7 +52,7 @@ export default Vue.extend({
applied.push(this.bold ? 'bold' : 'regular'); applied.push(this.bold ? 'bold' : 'regular');
return applied.map((c) => (this.$style as { [key: string]: string })[c]); return applied.map((c) => this.$style[c]);
}, },
}, },
}); });

View File

@@ -6,7 +6,6 @@
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
export default Vue.extend({ export default Vue.extend({
name: 'n8n-text', name: 'n8n-text',
props: { props: {
@@ -67,7 +66,7 @@ export default Vue.extend({
applied.push(this.bold ? 'bold' : 'regular'); applied.push(this.bold ? 'bold' : 'regular');
return applied.map((c) => (this.$style as { [key: string]: string })[c]); return applied.map((c) => this.$style[c]);
}, },
}, },
}); });

View File

@@ -1,18 +0,0 @@
import Vue from 'vue';
import * as locale from './locale';
declare module 'vue/types/vue' {
interface Vue {
$style: Record<string, string>;
t: (key: string, options?: object) => string;
}
}
declare module 'n8n-design-system' {
export * from './components';
export { N8nUsersList, N8nUserSelect } from './components';
export { locale };
}
export * from './types';
export { locale } from './locale';

View File

@@ -1,4 +1,6 @@
import * as locale from './locale'; import * as locale from './locale';
import designSystemComponents from './plugins/n8nComponents'; import designSystemComponents from './plugins/n8nComponents';
export * from './types';
export * from './utils';
export { locale, designSystemComponents }; export { locale, designSystemComponents };

View File

@@ -0,0 +1,7 @@
import * as Vue from 'vue';
declare module 'vue/types/vue' {
interface Vue {
$style: Record<string, string>;
}
}

View File

@@ -1,4 +1,4 @@
export * from './button';
export * from './form'; export * from './form';
export * from './user'; export * from './user';
export * from './menu'; export * from './menu';
export * from './button';

View File

@@ -0,0 +1,62 @@
import { createEventBus } from '../event-bus';
describe('createEventBus()', () => {
const eventBus = createEventBus();
describe('on()', () => {
it('should register event handler', () => {
const handler = vi.fn();
const eventName = 'test';
eventBus.on(eventName, handler);
eventBus.emit(eventName, {});
expect(handler).toHaveBeenCalled();
});
it('should return unregister fn', () => {
const handler = vi.fn();
const eventName = 'test';
const unregister = eventBus.on(eventName, handler);
unregister();
eventBus.emit(eventName, {});
expect(handler).not.toHaveBeenCalled();
});
});
describe('off()', () => {
it('should register event handler', () => {
const handler = vi.fn();
const eventName = 'test';
eventBus.on(eventName, handler);
eventBus.off(eventName, handler);
eventBus.emit(eventName, {});
expect(handler).not.toHaveBeenCalled();
});
});
describe('emit()', () => {
it('should call handlers with given event', () => {
const handlerA = vi.fn();
const handlerB = vi.fn();
const eventName = 'test';
const event = new Event(eventName);
eventBus.on(eventName, handlerA);
eventBus.on(eventName, handlerB);
eventBus.emit(eventName, event);
expect(handlerA).toHaveBeenCalledWith(event);
expect(handlerB).toHaveBeenCalledWith(event);
});
});
});

View File

@@ -0,0 +1,47 @@
// eslint-disable-next-line @typescript-eslint/ban-types
export type CallbackFn = Function;
export type UnregisterFn = () => void;
export function createEventBus() {
const handlers = new Map<string, CallbackFn[]>();
function off(eventName: string, fn: CallbackFn) {
const eventFns = handlers.get(eventName);
if (eventFns) {
eventFns.splice(eventFns.indexOf(fn) >>> 0, 1);
}
}
function on(eventName: string, fn: CallbackFn): UnregisterFn {
let eventFns = handlers.get(eventName);
if (!eventFns) {
eventFns = [fn];
} else {
eventFns.push(fn);
}
handlers.set(eventName, eventFns);
return () => off(eventName, fn);
}
function emit<T = Event>(eventName: string, event?: T) {
const eventFns = handlers.get(eventName);
if (eventFns) {
eventFns.slice().forEach(async (handler) => {
await handler(event);
});
}
}
return {
on,
off,
emit,
};
}
export type EventBus = ReturnType<typeof createEventBus>;

View File

@@ -1,3 +1,4 @@
export * from './event-bus';
export * from './markdown'; export * from './markdown';
export * from './uid'; export * from './uid';
export * from './valueByPath'; export * from './valueByPath';

View File

@@ -16,7 +16,7 @@ export default mergeConfig(
}, },
build: { build: {
lib: { lib: {
entry: resolve(__dirname, 'src', 'main.js'), entry: resolve(__dirname, 'src', 'main.ts'),
name: 'N8nDesignSystem', name: 'N8nDesignSystem',
fileName: (format) => `n8n-design-system.${format}.js`, fileName: (format) => `n8n-design-system.${format}.js`,
}, },

View File

@@ -60,6 +60,7 @@ import { ABOUT_MODAL_KEY } from '../constants';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
import { useRootStore } from '@/stores/n8nRootStore'; import { useRootStore } from '@/stores/n8nRootStore';
import { createEventBus } from '@/event-bus';
export default Vue.extend({ export default Vue.extend({
name: 'About', name: 'About',
@@ -69,7 +70,7 @@ export default Vue.extend({
data() { data() {
return { return {
ABOUT_MODAL_KEY, ABOUT_MODAL_KEY,
modalBus: new Vue(), modalBus: createEventBus(),
}; };
}, },
computed: { computed: {
@@ -77,7 +78,7 @@ export default Vue.extend({
}, },
methods: { methods: {
closeDialog() { closeDialog() {
this.modalBus.$emit('close'); this.modalBus.emit('close');
}, },
}, },
}); });

View File

@@ -49,6 +49,7 @@ import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
import { useWorkflowsStore } from '@/stores/workflows'; import { useWorkflowsStore } from '@/stores/workflows';
import { useNodeTypesStore } from '@/stores/nodeTypes'; import { useNodeTypesStore } from '@/stores/nodeTypes';
import { createEventBus } from '@/event-bus';
export default Vue.extend({ export default Vue.extend({
name: 'ActivationModal', name: 'ActivationModal',
@@ -60,7 +61,7 @@ export default Vue.extend({
return { return {
WORKFLOW_ACTIVE_MODAL_KEY, WORKFLOW_ACTIVE_MODAL_KEY,
checked: false, checked: false,
modalBus: new Vue(), modalBus: createEventBus(),
}; };
}, },
methods: { methods: {

View File

@@ -33,11 +33,11 @@ import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage'; import { showMessage } from '@/mixins/showMessage';
import Modal from './Modal.vue'; import Modal from './Modal.vue';
import Vue from 'vue';
import { IFormInputs } from '@/Interface'; import { IFormInputs } from '@/Interface';
import { CHANGE_PASSWORD_MODAL_KEY } from '../constants'; import { CHANGE_PASSWORD_MODAL_KEY } from '../constants';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useUsersStore } from '@/stores/users'; import { useUsersStore } from '@/stores/users';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage).extend({ export default mixins(showMessage).extend({
components: { Modal }, components: { Modal },
@@ -50,8 +50,8 @@ export default mixins(showMessage).extend({
data() { data() {
return { return {
config: null as null | IFormInputs, config: null as null | IFormInputs,
formBus: new Vue(), formBus: createEventBus(),
modalBus: new Vue(), modalBus: createEventBus(),
password: '', password: '',
loading: false, loading: false,
CHANGE_PASSWORD_MODAL_KEY, CHANGE_PASSWORD_MODAL_KEY,
@@ -133,14 +133,14 @@ export default mixins(showMessage).extend({
message: this.$locale.baseText('auth.changePassword.passwordUpdatedMessage'), message: this.$locale.baseText('auth.changePassword.passwordUpdatedMessage'),
}); });
this.modalBus.$emit('close'); this.modalBus.emit('close');
} catch (error) { } catch (error) {
this.$showError(error, this.$locale.baseText('auth.changePassword.error')); this.$showError(error, this.$locale.baseText('auth.changePassword.error'));
} }
this.loading = false; this.loading = false;
}, },
onSubmitClick() { onSubmitClick() {
this.formBus.$emit('submit'); this.formBus.emit('submit');
}, },
}, },
}); });

View File

@@ -14,7 +14,7 @@ import { linterExtension } from './linter';
import { completerExtension } from './completer'; import { completerExtension } from './completer';
import { CODE_NODE_EDITOR_THEME } from './theme'; import { CODE_NODE_EDITOR_THEME } from './theme';
import { workflowHelpers } from '@/mixins/workflowHelpers'; // for json field completions import { workflowHelpers } from '@/mixins/workflowHelpers'; // for json field completions
import { codeNodeEditorEventBus } from '@/event-bus/code-node-editor-event-bus'; import { codeNodeEditorEventBus } from '@/event-bus';
import { CODE_NODE_TYPE } from '@/constants'; import { CODE_NODE_TYPE } from '@/constants';
import { ALL_ITEMS_PLACEHOLDER, EACH_ITEM_PLACEHOLDER } from './constants'; import { ALL_ITEMS_PLACEHOLDER, EACH_ITEM_PLACEHOLDER } from './constants';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
@@ -133,10 +133,10 @@ export default mixins(linterExtension, completerExtension, workflowHelpers).exte
}, },
}, },
destroyed() { destroyed() {
codeNodeEditorEventBus.$off('error-line-number', this.highlightLine); codeNodeEditorEventBus.off('error-line-number', this.highlightLine);
}, },
mounted() { mounted() {
codeNodeEditorEventBus.$on('error-line-number', this.highlightLine); codeNodeEditorEventBus.on('error-line-number', this.highlightLine);
const stateBasedExtensions = [ const stateBasedExtensions = [
this.linterCompartment.of(this.linterExtension()), this.linterCompartment.of(this.linterExtension()),

View File

@@ -88,7 +88,6 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue';
import Modal from './Modal.vue'; import Modal from './Modal.vue';
import { import {
COMMUNITY_PACKAGE_INSTALL_MODAL_KEY, COMMUNITY_PACKAGE_INSTALL_MODAL_KEY,
@@ -100,6 +99,7 @@ import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage'; import { showMessage } from '@/mixins/showMessage';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useCommunityNodesStore } from '@/stores/communityNodes'; import { useCommunityNodesStore } from '@/stores/communityNodes';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage).extend({ export default mixins(showMessage).extend({
name: 'CommunityPackageInstallModal', name: 'CommunityPackageInstallModal',
@@ -111,7 +111,7 @@ export default mixins(showMessage).extend({
loading: false, loading: false,
packageName: '', packageName: '',
userAgreed: false, userAgreed: false,
modalBus: new Vue(), modalBus: createEventBus(),
checkboxWarning: false, checkboxWarning: false,
infoTextErrorMessage: '', infoTextErrorMessage: '',
COMMUNITY_PACKAGE_INSTALL_MODAL_KEY, COMMUNITY_PACKAGE_INSTALL_MODAL_KEY,
@@ -143,7 +143,7 @@ export default mixins(showMessage).extend({
// TODO: We need to fetch a fresh list of installed packages until proper response is implemented on the back-end // TODO: We need to fetch a fresh list of installed packages until proper response is implemented on the back-end
await this.communityNodesStore.fetchInstalledPackages(); await this.communityNodesStore.fetchInstalledPackages();
this.loading = false; this.loading = false;
this.modalBus.$emit('close'); this.modalBus.emit('close');
this.$showMessage({ this.$showMessage({
title: this.$locale.baseText('settings.communityNodes.messages.install.success'), title: this.$locale.baseText('settings.communityNodes.messages.install.success'),
type: 'success', type: 'success',

View File

@@ -35,7 +35,6 @@
</template> </template>
<script> <script>
import Vue from 'vue';
import mixins from 'vue-typed-mixins'; import mixins from 'vue-typed-mixins';
import Modal from './Modal.vue'; import Modal from './Modal.vue';
import { import {
@@ -45,6 +44,7 @@ import {
import { showMessage } from '@/mixins/showMessage'; import { showMessage } from '@/mixins/showMessage';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useCommunityNodesStore } from '@/stores/communityNodes'; import { useCommunityNodesStore } from '@/stores/communityNodes';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage).extend({ export default mixins(showMessage).extend({
name: 'CommunityPackageManageConfirmModal', name: 'CommunityPackageManageConfirmModal',
@@ -67,7 +67,7 @@ export default mixins(showMessage).extend({
data() { data() {
return { return {
loading: false, loading: false,
modalBus: new Vue(), modalBus: createEventBus(),
COMMUNITY_PACKAGE_CONFIRM_MODAL_KEY, COMMUNITY_PACKAGE_CONFIRM_MODAL_KEY,
COMMUNITY_PACKAGE_MANAGE_ACTIONS, COMMUNITY_PACKAGE_MANAGE_ACTIONS,
}; };
@@ -151,7 +151,7 @@ export default mixins(showMessage).extend({
); );
} finally { } finally {
this.loading = false; this.loading = false;
this.modalBus.$emit('close'); this.modalBus.emit('close');
} }
}, },
async onUpdate() { async onUpdate() {
@@ -187,7 +187,7 @@ export default mixins(showMessage).extend({
); );
} finally { } finally {
this.loading = false; this.loading = false;
this.modalBus.$emit('close'); this.modalBus.emit('close');
} }
}, },
}, },

View File

@@ -33,7 +33,6 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue';
import mixins from 'vue-typed-mixins'; import mixins from 'vue-typed-mixins';
import { IN8nPromptResponse } from '@/Interface'; import { IN8nPromptResponse } from '@/Interface';
@@ -43,6 +42,7 @@ import Modal from './Modal.vue';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
import { useRootStore } from '@/stores/n8nRootStore'; import { useRootStore } from '@/stores/n8nRootStore';
import { createEventBus } from '@/event-bus';
export default mixins(workflowHelpers).extend({ export default mixins(workflowHelpers).extend({
components: { Modal }, components: { Modal },
@@ -51,7 +51,7 @@ export default mixins(workflowHelpers).extend({
data() { data() {
return { return {
email: '', email: '',
modalBus: new Vue(), modalBus: createEventBus(),
}; };
}, },
computed: { computed: {
@@ -100,7 +100,7 @@ export default mixins(workflowHelpers).extend({
type: 'success', type: 'success',
}); });
} }
this.modalBus.$emit('close'); this.modalBus.emit('close');
} }
}, },
}, },

View File

@@ -143,7 +143,7 @@ import { CREDENTIAL_EDIT_MODAL_KEY, EnterpriseEditionFeature } from '@/constants
import { IDataObject } from 'n8n-workflow'; import { IDataObject } from 'n8n-workflow';
import FeatureComingSoon from '../FeatureComingSoon.vue'; import FeatureComingSoon from '../FeatureComingSoon.vue';
import { getCredentialPermissions, IPermissions } from '@/permissions'; import { getCredentialPermissions, IPermissions } from '@/permissions';
import { IMenuItem } from 'n8n-design-system'; import { createEventBus, IMenuItem } from 'n8n-design-system';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
@@ -195,7 +195,7 @@ export default mixins(showMessage, nodeHelpers).extend({
credentialId: '', credentialId: '',
credentialName: '', credentialName: '',
credentialData: {} as ICredentialDataDecryptedObject, credentialData: {} as ICredentialDataDecryptedObject,
modalBus: new Vue(), modalBus: createEventBus(),
nodeAccess: {} as NodeAccessMap, nodeAccess: {} as NodeAccessMap,
isDeleting: false, isDeleting: false,
isSaving: false, isSaving: false,
@@ -645,7 +645,7 @@ export default mixins(showMessage, nodeHelpers).extend({
}; };
}, },
closeDialog() { closeDialog() {
this.modalBus.$emit('close'); this.modalBus.emit('close');
}, },
getParentTypes(name: string): string[] { getParentTypes(name: string): string[] {

View File

@@ -178,7 +178,7 @@ export default mixins(showMessage).extend({
}, },
goToUsersSettings() { goToUsersSettings() {
this.$router.push({ name: VIEWS.USERS_SETTINGS }); this.$router.push({ name: VIEWS.USERS_SETTINGS });
this.modalBus.$emit('close'); this.modalBus.emit('close');
}, },
goToUpgrade() { goToUpgrade() {
const linkUrlTranslationKey = this.uiStore.contextBasedTranslationKeys const linkUrlTranslationKey = this.uiStore.contextBasedTranslationKeys

View File

@@ -58,7 +58,6 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue';
import mixins from 'vue-typed-mixins'; import mixins from 'vue-typed-mixins';
import Modal from './Modal.vue'; import Modal from './Modal.vue';
import { CREDENTIAL_SELECT_MODAL_KEY } from '../constants'; import { CREDENTIAL_SELECT_MODAL_KEY } from '../constants';
@@ -67,6 +66,7 @@ import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
import { useWorkflowsStore } from '@/stores/workflows'; import { useWorkflowsStore } from '@/stores/workflows';
import { useCredentialsStore } from '@/stores/credentials'; import { useCredentialsStore } from '@/stores/credentials';
import { createEventBus } from '@/event-bus';
export default mixins(externalHooks).extend({ export default mixins(externalHooks).extend({
name: 'CredentialsSelectModal', name: 'CredentialsSelectModal',
@@ -88,7 +88,7 @@ export default mixins(externalHooks).extend({
}, },
data() { data() {
return { return {
modalBus: new Vue(), modalBus: createEventBus(),
selected: '', selected: '',
loading: true, loading: true,
CREDENTIAL_SELECT_MODAL_KEY, CREDENTIAL_SELECT_MODAL_KEY,
@@ -102,7 +102,7 @@ export default mixins(externalHooks).extend({
this.selected = type; this.selected = type;
}, },
openCredentialType() { openCredentialType() {
this.modalBus.$emit('close'); this.modalBus.emit('close');
this.uiStore.openNewCredential(this.selected); this.uiStore.openNewCredential(this.selected);
const telemetryPayload = { const telemetryPayload = {

View File

@@ -74,10 +74,10 @@ import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage'; import { showMessage } from '@/mixins/showMessage';
import Modal from './Modal.vue'; import Modal from './Modal.vue';
import Vue from 'vue';
import { IUser } from '../Interface'; import { IUser } from '../Interface';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useUsersStore } from '@/stores/users'; import { useUsersStore } from '@/stores/users';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage).extend({ export default mixins(showMessage).extend({
components: { components: {
@@ -94,7 +94,7 @@ export default mixins(showMessage).extend({
}, },
data() { data() {
return { return {
modalBus: new Vue(), modalBus: createEventBus(),
loading: false, loading: false,
operation: '', operation: '',
deleteConfirmText: '', deleteConfirmText: '',
@@ -175,7 +175,7 @@ export default mixins(showMessage).extend({
message, message,
}); });
this.modalBus.$emit('close'); this.modalBus.emit('close');
} catch (error) { } catch (error) {
this.$showError(error, this.$locale.baseText('settings.users.userDeletedError')); this.$showError(error, this.$locale.baseText('settings.users.userDeletedError'));
} }

View File

@@ -49,7 +49,6 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue';
import mixins from 'vue-typed-mixins'; import mixins from 'vue-typed-mixins';
import { MAX_WORKFLOW_NAME_LENGTH, PLACEHOLDER_EMPTY_WORKFLOW_ID } from '@/constants'; import { MAX_WORKFLOW_NAME_LENGTH, PLACEHOLDER_EMPTY_WORKFLOW_ID } from '@/constants';
@@ -64,6 +63,7 @@ import { useWorkflowsStore } from '@/stores/workflows';
import { IWorkflowDataUpdate } from '@/Interface'; import { IWorkflowDataUpdate } from '@/Interface';
import { getWorkflowPermissions, IPermissions } from '@/permissions'; import { getWorkflowPermissions, IPermissions } from '@/permissions';
import { useUsersStore } from '@/stores/users'; import { useUsersStore } from '@/stores/users';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage, workflowHelpers, restApi).extend({ export default mixins(showMessage, workflowHelpers, restApi).extend({
components: { TagsDropdown, Modal }, components: { TagsDropdown, Modal },
@@ -76,8 +76,8 @@ export default mixins(showMessage, workflowHelpers, restApi).extend({
name: '', name: '',
currentTagIds, currentTagIds,
isSaving: false, isSaving: false,
modalBus: new Vue(), modalBus: createEventBus(),
dropdownBus: new Vue(), dropdownBus: createEventBus(),
MAX_WORKFLOW_NAME_LENGTH, MAX_WORKFLOW_NAME_LENGTH,
prevTagIds: currentTagIds, prevTagIds: currentTagIds,
}; };
@@ -112,7 +112,7 @@ export default mixins(showMessage, workflowHelpers, restApi).extend({
}, },
methods: { methods: {
focusOnSelect() { focusOnSelect() {
this.dropdownBus.$emit('focus'); this.dropdownBus.emit('focus');
}, },
focusOnNameInput() { focusOnNameInput() {
const input = this.$refs.nameInput as HTMLElement; const input = this.$refs.nameInput as HTMLElement;
@@ -195,7 +195,7 @@ export default mixins(showMessage, workflowHelpers, restApi).extend({
} }
}, },
closeDialog(): void { closeDialog(): void {
this.modalBus.$emit('close'); this.modalBus.emit('close');
}, },
}, },
}); });

View File

@@ -11,6 +11,7 @@ import Vue from 'vue';
import ExecutionsList from '@/components/ExecutionsList.vue'; import ExecutionsList from '@/components/ExecutionsList.vue';
import Modal from '@/components/Modal.vue'; import Modal from '@/components/Modal.vue';
import { EXECUTIONS_MODAL_KEY } from '@/constants'; import { EXECUTIONS_MODAL_KEY } from '@/constants';
import { createEventBus } from '@/event-bus';
export default Vue.extend({ export default Vue.extend({
name: 'ExecutionsModal', name: 'ExecutionsModal',
@@ -20,13 +21,13 @@ export default Vue.extend({
}, },
data() { data() {
return { return {
modalBus: new Vue(), modalBus: createEventBus(),
EXECUTIONS_MODAL_KEY, EXECUTIONS_MODAL_KEY,
}; };
}, },
methods: { methods: {
onCloseModal() { onCloseModal() {
this.modalBus.$emit('close'); this.modalBus.emit('close');
}, },
}, },
}); });

View File

@@ -16,13 +16,22 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue, { PropType } from 'vue';
import ExpandableInputBase from './ExpandableInputBase.vue'; import ExpandableInputBase from './ExpandableInputBase.vue';
import { EventBus } from '@/event-bus';
export default Vue.extend({ export default Vue.extend({
components: { ExpandableInputBase }, components: { ExpandableInputBase },
name: 'ExpandableInputEdit', name: 'ExpandableInputEdit',
props: ['value', 'placeholder', 'maxlength', 'autofocus', 'eventBus'], props: {
value: {},
placeholder: {},
maxlength: {},
autofocus: {},
eventBus: {
type: Object as PropType<EventBus>,
},
},
mounted() { mounted() {
// autofocus on input element is not reliable // autofocus on input element is not reliable
if (this.$props.autofocus && this.$refs.input) { if (this.$props.autofocus && this.$refs.input) {
@@ -30,7 +39,7 @@ export default Vue.extend({
} }
if (this.$props.eventBus) { if (this.$props.eventBus) {
this.$props.eventBus.$on('focus', () => { this.$props.eventBus.on('focus', () => {
this.focus(); this.focus();
}); });
} }

View File

@@ -32,7 +32,7 @@ import {
import { n8nCompletionSources } from '@/plugins/codemirror/completions/addCompletions'; import { n8nCompletionSources } from '@/plugins/codemirror/completions/addCompletions';
import { expressionInputHandler } from '@/plugins/codemirror/inputHandlers/expression.inputHandler'; import { expressionInputHandler } from '@/plugins/codemirror/inputHandlers/expression.inputHandler';
import { highlighter } from '@/plugins/codemirror/resolvableHighlighter'; import { highlighter } from '@/plugins/codemirror/resolvableHighlighter';
import { htmlEditorEventBus } from '@/event-bus/html-editor-event-bus'; import { htmlEditorEventBus } from '@/event-bus';
import { expressionManager } from '@/mixins/expressionManager'; import { expressionManager } from '@/mixins/expressionManager';
import { theme } from './theme'; import { theme } from './theme';
import { nonTakenRanges } from './utils'; import { nonTakenRanges } from './utils';
@@ -256,7 +256,7 @@ export default mixins(expressionManager).extend({
}, },
mounted() { mounted() {
htmlEditorEventBus.$on('format-html', this.format); htmlEditorEventBus.on('format-html', this.format);
let doc = this.html; let doc = this.html;
@@ -272,7 +272,7 @@ export default mixins(expressionManager).extend({
}, },
destroyed() { destroyed() {
htmlEditorEventBus.$off('format-html', this.format); htmlEditorEventBus.off('format-html', this.format);
}, },
}); });
</script> </script>

View File

@@ -40,7 +40,6 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue';
import Modal from './Modal.vue'; import Modal from './Modal.vue';
import { import {
IMPORT_CURL_MODAL_KEY, IMPORT_CURL_MODAL_KEY,
@@ -53,6 +52,7 @@ import { INodeUi } from '@/Interface';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
import { useNDVStore } from '@/stores/ndv'; import { useNDVStore } from '@/stores/ndv';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage).extend({ export default mixins(showMessage).extend({
name: 'ImportCurlModal', name: 'ImportCurlModal',
@@ -63,7 +63,7 @@ export default mixins(showMessage).extend({
return { return {
IMPORT_CURL_MODAL_KEY, IMPORT_CURL_MODAL_KEY,
curlCommand: '', curlCommand: '',
modalBus: new Vue(), modalBus: createEventBus(),
}; };
}, },
computed: { computed: {
@@ -74,7 +74,7 @@ export default mixins(showMessage).extend({
}, },
methods: { methods: {
closeDialog(): void { closeDialog(): void {
this.modalBus.$emit('close'); this.modalBus.emit('close');
}, },
onInput(value: string): void { onInput(value: string): void {
this.curlCommand = value; this.curlCommand = value;

View File

@@ -24,6 +24,7 @@
import Vue from 'vue'; import Vue from 'vue';
import ExpandableInputEdit from '@/components/ExpandableInput/ExpandableInputEdit.vue'; import ExpandableInputEdit from '@/components/ExpandableInput/ExpandableInputEdit.vue';
import ExpandableInputPreview from '@/components/ExpandableInput/ExpandableInputPreview.vue'; import ExpandableInputPreview from '@/components/ExpandableInput/ExpandableInputPreview.vue';
import { createEventBus } from '@/event-bus';
export default Vue.extend({ export default Vue.extend({
name: 'InlineTextEdit', name: 'InlineTextEdit',
@@ -34,7 +35,7 @@ export default Vue.extend({
newValue: '', newValue: '',
escPressed: false, escPressed: false,
disabled: false, disabled: false,
inputBus: new Vue(), inputBus: createEventBus(),
}; };
}, },
methods: { methods: {
@@ -72,7 +73,7 @@ export default Vue.extend({
this.$data.disabled = false; this.$data.disabled = false;
if (!updated) { if (!updated) {
this.$data.inputBus.$emit('focus'); this.$data.inputBus.emit('focus');
} }
}; };

View File

@@ -69,13 +69,13 @@ import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage'; import { showMessage } from '@/mixins/showMessage';
import { copyPaste } from '@/mixins/copyPaste'; import { copyPaste } from '@/mixins/copyPaste';
import Modal from './Modal.vue'; import Modal from './Modal.vue';
import Vue from 'vue';
import { IFormInputs, IInviteResponse, IUser } from '@/Interface'; import { IFormInputs, IInviteResponse, IUser } from '@/Interface';
import { VALID_EMAIL_REGEX, INVITE_USER_MODAL_KEY } from '@/constants'; import { VALID_EMAIL_REGEX, INVITE_USER_MODAL_KEY } from '@/constants';
import { ROLE } from '@/utils'; import { ROLE } from '@/utils';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useUsersStore } from '@/stores/users'; import { useUsersStore } from '@/stores/users';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
import { createEventBus } from '@/event-bus';
const NAME_EMAIL_FORMAT_REGEX = /^.* <(.*)>$/; const NAME_EMAIL_FORMAT_REGEX = /^.* <(.*)>$/;
@@ -101,8 +101,8 @@ export default mixins(showMessage, copyPaste).extend({
data() { data() {
return { return {
config: null as IFormInputs | null, config: null as IFormInputs | null,
formBus: new Vue(), formBus: createEventBus(),
modalBus: new Vue(), modalBus: createEventBus(),
emails: '', emails: '',
showInviteUrls: null as IInviteResponse[] | null, showInviteUrls: null as IInviteResponse[] | null,
loading: false, loading: false,
@@ -279,7 +279,7 @@ export default mixins(showMessage, copyPaste).extend({
if (successfulUrlInvites.length > 1) { if (successfulUrlInvites.length > 1) {
this.showInviteUrls = successfulUrlInvites; this.showInviteUrls = successfulUrlInvites;
} else { } else {
this.modalBus.$emit('close'); this.modalBus.emit('close');
} }
} catch (error) { } catch (error) {
this.$showError(error, this.$locale.baseText('settings.users.usersInvitedError')); this.$showError(error, this.$locale.baseText('settings.users.usersInvitedError'));
@@ -307,7 +307,7 @@ export default mixins(showMessage, copyPaste).extend({
}); });
}, },
onSubmitClick() { onSubmitClick() {
this.formBus.$emit('submit'); this.formBus.emit('submit');
}, },
onCopyInviteLink(user: IUser) { onCopyInviteLink(user: IUser) {
if (user.inviteAcceptUrl && this.showInviteUrls) { if (user.inviteAcceptUrl && this.showInviteUrls) {

View File

@@ -138,7 +138,7 @@ export default mixins(pushConnection, workflowHelpers).extend({
} else { } else {
this.$router.push({ name: VIEWS.EXECUTION_HOME, params: { name: routeWorkflowId } }); this.$router.push({ name: VIEWS.EXECUTION_HOME, params: { name: routeWorkflowId } });
} }
// this.modalBus.$emit('closeAll'); // this.modalBus.emit('closeAll');
this.activeHeaderTab = MAIN_HEADER_TABS.EXECUTIONS; this.activeHeaderTab = MAIN_HEADER_TABS.EXECUTIONS;
break; break;
default: default:

View File

@@ -160,6 +160,7 @@ import { getWorkflowPermissions, IPermissions } from '@/permissions';
import { useUsersStore } from '@/stores/users'; import { useUsersStore } from '@/stores/users';
import { useUsageStore } from '@/stores/usage'; import { useUsageStore } from '@/stores/usage';
import { BaseTextKey } from '@/plugins/i18n'; import { BaseTextKey } from '@/plugins/i18n';
import { createEventBus } from '@/event-bus';
const hasChanged = (prev: string[], curr: string[]) => { const hasChanged = (prev: string[], curr: string[]) => {
if (prev.length !== curr.length) { if (prev.length !== curr.length) {
@@ -187,7 +188,7 @@ export default mixins(workflowHelpers, titleChange).extend({
isTagsEditEnabled: false, isTagsEditEnabled: false,
isNameEditEnabled: false, isNameEditEnabled: false,
appliedTagIds: [], appliedTagIds: [],
tagsEditBus: new Vue(), tagsEditBus: createEventBus(),
MAX_WORKFLOW_NAME_LENGTH, MAX_WORKFLOW_NAME_LENGTH,
tagsSaving: false, tagsSaving: false,
EnterpriseEditionFeature, EnterpriseEditionFeature,
@@ -328,7 +329,7 @@ export default mixins(workflowHelpers, titleChange).extend({
setTimeout(() => { setTimeout(() => {
// allow name update to occur before disabling name edit // allow name update to occur before disabling name edit
this.$data.isNameEditEnabled = false; this.$data.isNameEditEnabled = false;
this.$data.tagsEditBus.$emit('focus'); this.$data.tagsEditBus.emit('focus');
}, 0); }, 0);
}, },
async onTagsUpdate(tags: string[]) { async onTagsUpdate(tags: string[]) {

View File

@@ -43,9 +43,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue, { PropType } from 'vue';
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { EventBus } from '@/event-bus';
export default Vue.extend({ export default Vue.extend({
name: 'Modal', name: 'Modal',
@@ -60,7 +61,7 @@ export default Vue.extend({
type: String, type: String,
}, },
eventBus: { eventBus: {
type: Vue, type: Object as PropType<EventBus>,
}, },
showClose: { showClose: {
type: Boolean, type: Boolean,
@@ -121,11 +122,11 @@ export default Vue.extend({
window.addEventListener('keydown', this.onWindowKeydown); window.addEventListener('keydown', this.onWindowKeydown);
if (this.$props.eventBus) { if (this.$props.eventBus) {
this.$props.eventBus.$on('close', () => { this.$props.eventBus.on('close', () => {
this.closeDialog(); this.closeDialog();
}); });
this.$props.eventBus.$on('closeAll', () => { this.$props.eventBus.on('closeAll', () => {
this.uiStore.closeAllModals(); this.uiStore.closeAllModals();
}); });
} }

View File

@@ -21,7 +21,8 @@
<script lang="ts"> <script lang="ts">
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import Vue from 'vue'; import Vue, { PropType } from 'vue';
import { EventBus } from '@/event-bus';
export default Vue.extend({ export default Vue.extend({
name: 'ModalDrawer', name: 'ModalDrawer',
@@ -33,7 +34,7 @@ export default Vue.extend({
type: Function, type: Function,
}, },
eventBus: { eventBus: {
type: Vue, type: Object as PropType<EventBus>,
}, },
direction: { direction: {
type: String, type: String,
@@ -54,7 +55,7 @@ export default Vue.extend({
window.addEventListener('keydown', this.onWindowKeydown); window.addEventListener('keydown', this.onWindowKeydown);
if (this.$props.eventBus) { if (this.$props.eventBus) {
this.$props.eventBus.$on('close', () => { this.$props.eventBus.on('close', () => {
this.close(); this.close();
}); });
} }

View File

@@ -24,13 +24,14 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Vue, { onMounted, reactive, toRefs, onBeforeUnmount } from 'vue'; import { onMounted, reactive, toRefs, onBeforeUnmount } from 'vue';
import { externalHooks } from '@/mixins/externalHooks'; import { externalHooks } from '@/mixins/externalHooks';
import { EventBus } from '@/event-bus';
export interface Props { export interface Props {
placeholder: string; placeholder: string;
value: string; value: string;
eventBus?: Vue; eventBus?: EventBus;
} }
withDefaults(defineProps<Props>(), { withDefaults(defineProps<Props>(), {

View File

@@ -142,7 +142,6 @@ import NodeSettings from '@/components/NodeSettings.vue';
import NDVDraggablePanels from './NDVDraggablePanels.vue'; import NDVDraggablePanels from './NDVDraggablePanels.vue';
import mixins from 'vue-typed-mixins'; import mixins from 'vue-typed-mixins';
import Vue from 'vue';
import OutputPanel from './OutputPanel.vue'; import OutputPanel from './OutputPanel.vue';
import InputPanel from './InputPanel.vue'; import InputPanel from './InputPanel.vue';
import TriggerPanel from './TriggerPanel.vue'; import TriggerPanel from './TriggerPanel.vue';
@@ -155,7 +154,7 @@ import {
} from '@/constants'; } from '@/constants';
import { workflowActivate } from '@/mixins/workflowActivate'; import { workflowActivate } from '@/mixins/workflowActivate';
import { pinData } from '@/mixins/pinData'; import { pinData } from '@/mixins/pinData';
import { dataPinningEventBus } from '@/event-bus/data-pinning-event-bus'; import { createEventBus, dataPinningEventBus } from '@/event-bus';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useWorkflowsStore } from '@/stores/workflows'; import { useWorkflowsStore } from '@/stores/workflows';
import { useNDVStore } from '@/stores/ndv'; import { useNDVStore } from '@/stores/ndv';
@@ -198,7 +197,7 @@ export default mixins(
}, },
data() { data() {
return { return {
settingsEventBus: new Vue(), settingsEventBus: createEventBus(),
runInputIndex: -1, runInputIndex: -1,
runOutputIndex: -1, runOutputIndex: -1,
isLinkingEnabled: true, isLinkingEnabled: true,
@@ -212,7 +211,7 @@ export default mixins(
}; };
}, },
mounted() { mounted() {
dataPinningEventBus.$on( dataPinningEventBus.on(
'data-pinning-discovery', 'data-pinning-discovery',
({ isTooltipVisible }: { isTooltipVisible: boolean }) => { ({ isTooltipVisible }: { isTooltipVisible: boolean }) => {
this.pinDataDiscoveryTooltipVisible = isTooltipVisible; this.pinDataDiscoveryTooltipVisible = isTooltipVisible;
@@ -220,7 +219,7 @@ export default mixins(
); );
}, },
destroyed() { destroyed() {
dataPinningEventBus.$off('data-pinning-discovery'); dataPinningEventBus.off('data-pinning-discovery');
}, },
computed: { computed: {
...mapStores(useNodeTypesStore, useNDVStore, useUIStore, useWorkflowsStore, useSettingsStore), ...mapStores(useNodeTypesStore, useNDVStore, useUIStore, useWorkflowsStore, useSettingsStore),
@@ -596,7 +595,7 @@ export default mixins(
}, 1000); }, 1000);
}, },
openSettings() { openSettings() {
this.settingsEventBus.$emit('openSettings'); this.settingsEventBus.emit('openSettings');
}, },
valueChanged(parameterData: IUpdateInformation) { valueChanged(parameterData: IUpdateInformation) {
this.$emit('valueChanged', parameterData); this.$emit('valueChanged', parameterData);
@@ -622,7 +621,7 @@ export default mixins(
const { value } = this.outputPanelEditMode; const { value } = this.outputPanelEditMode;
if (!this.isValidPinDataSize(value)) { if (!this.isValidPinDataSize(value)) {
dataPinningEventBus.$emit('data-pinning-error', { dataPinningEventBus.emit('data-pinning-error', {
errorType: 'data-too-large', errorType: 'data-too-large',
source: 'on-ndv-close-modal', source: 'on-ndv-close-modal',
}); });
@@ -630,7 +629,7 @@ export default mixins(
} }
if (!this.isValidPinDataJSON(value)) { if (!this.isValidPinDataJSON(value)) {
dataPinningEventBus.$emit('data-pinning-error', { dataPinningEventBus.emit('data-pinning-error', {
errorType: 'invalid-json', errorType: 'invalid-json',
source: 'on-ndv-close-modal', source: 'on-ndv-close-modal',
}); });

View File

@@ -24,7 +24,7 @@ import { INodeTypeDescription } from 'n8n-workflow';
import mixins from 'vue-typed-mixins'; import mixins from 'vue-typed-mixins';
import { workflowRun } from '@/mixins/workflowRun'; import { workflowRun } from '@/mixins/workflowRun';
import { pinData } from '@/mixins/pinData'; import { pinData } from '@/mixins/pinData';
import { dataPinningEventBus } from '@/event-bus/data-pinning-event-bus'; import { dataPinningEventBus } from '@/event-bus';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useWorkflowsStore } from '@/stores/workflows'; import { useWorkflowsStore } from '@/stores/workflows';
import { useNDVStore } from '@/stores/ndv'; import { useNDVStore } from '@/stores/ndv';
@@ -195,7 +195,7 @@ export default mixins(workflowRun, pinData).extend({
); );
if (shouldUnpinAndExecute) { if (shouldUnpinAndExecute) {
dataPinningEventBus.$emit('data-unpinning', { source: 'unpin-and-execute-modal' }); dataPinningEventBus.emit('data-unpinning', { source: 'unpin-and-execute-modal' });
this.workflowsStore.unpinData({ node: this.node }); this.workflowsStore.unpinData({ node: this.node });
} }
} }

View File

@@ -205,6 +205,7 @@ import { useHistoryStore } from '@/stores/history';
import { RenameNodeCommand } from '@/models/history'; import { RenameNodeCommand } from '@/models/history';
import useWorkflowsEEStore from '@/stores/workflows.ee'; import useWorkflowsEEStore from '@/stores/workflows.ee';
import { useCredentialsStore } from '@/stores/credentials'; import { useCredentialsStore } from '@/stores/credentials';
import { EventBus } from '@/event-bus';
export default mixins(externalHooks, nodeHelpers).extend({ export default mixins(externalHooks, nodeHelpers).extend({
name: 'NodeSettings', name: 'NodeSettings',
@@ -322,7 +323,9 @@ export default mixins(externalHooks, nodeHelpers).extend({
}, },
}, },
props: { props: {
eventBus: {}, eventBus: {
type: Object as PropType<EventBus>,
},
dragging: { dragging: {
type: Boolean, type: Boolean,
}, },
@@ -897,7 +900,7 @@ export default mixins(externalHooks, nodeHelpers).extend({
this.populateHiddenIssuesSet(); this.populateHiddenIssuesSet();
this.setNodeValues(); this.setNodeValues();
if (this.eventBus) { if (this.eventBus) {
(this.eventBus as Vue).$on('openSettings', () => { this.eventBus.on('openSettings', () => {
this.openPanel = 'settings'; this.openPanel = 'settings';
}); });
} }

View File

@@ -48,8 +48,6 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue';
import { ONBOARDING_CALL_SIGNUP_MODAL_KEY, VALID_EMAIL_REGEX } from '@/constants'; import { ONBOARDING_CALL_SIGNUP_MODAL_KEY, VALID_EMAIL_REGEX } from '@/constants';
import Modal from './Modal.vue'; import Modal from './Modal.vue';
@@ -57,6 +55,7 @@ import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage'; import { showMessage } from '@/mixins/showMessage';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage).extend({ export default mixins(showMessage).extend({
components: { components: {
@@ -67,7 +66,7 @@ export default mixins(showMessage).extend({
data() { data() {
return { return {
email: '', email: '',
modalBus: new Vue(), modalBus: createEventBus(),
ONBOARDING_CALL_SIGNUP_MODAL_KEY, ONBOARDING_CALL_SIGNUP_MODAL_KEY,
showError: false, showError: false,
okToClose: false, okToClose: false,
@@ -98,7 +97,7 @@ export default mixins(showMessage).extend({
message: this.$locale.baseText('onboardingCallSignupSucess.message'), message: this.$locale.baseText('onboardingCallSignupSucess.message'),
}); });
this.okToClose = true; this.okToClose = true;
this.modalBus.$emit('close'); this.modalBus.emit('close');
} catch (e) { } catch (e) {
this.$showError( this.$showError(
e, e,
@@ -111,7 +110,7 @@ export default mixins(showMessage).extend({
}, },
async onCancel() { async onCancel() {
this.okToClose = true; this.okToClose = true;
this.modalBus.$emit('close'); this.modalBus.emit('close');
}, },
onModalClose() { onModalClose() {
return this.okToClose; return this.okToClose;

View File

@@ -373,7 +373,7 @@ import { useWorkflowsStore } from '@/stores/workflows';
import { useNDVStore } from '@/stores/ndv'; import { useNDVStore } from '@/stores/ndv';
import { useNodeTypesStore } from '@/stores/nodeTypes'; import { useNodeTypesStore } from '@/stores/nodeTypes';
import { useCredentialsStore } from '@/stores/credentials'; import { useCredentialsStore } from '@/stores/credentials';
import { htmlEditorEventBus } from '@/event-bus/html-editor-event-bus'; import { htmlEditorEventBus } from '@/event-bus';
export default mixins( export default mixins(
externalHooks, externalHooks,
@@ -1106,7 +1106,7 @@ export default mixins(
} }
this.loadRemoteParameterOptions(); this.loadRemoteParameterOptions();
} else if (command === 'formatHtml') { } else if (command === 'formatHtml') {
htmlEditorEventBus.$emit('format-html'); htmlEditorEventBus.emit('format-html');
} }
if (this.node && (command === 'addExpression' || command === 'removeExpression')) { if (this.node && (command === 'addExpression' || command === 'removeExpression')) {

View File

@@ -127,7 +127,6 @@ import { workflowHelpers } from '@/mixins/workflowHelpers';
import { showMessage } from '@/mixins/showMessage'; import { showMessage } from '@/mixins/showMessage';
import Modal from './Modal.vue'; import Modal from './Modal.vue';
import { IFormInputs, IPersonalizationLatestVersion, IUser } from '@/Interface'; import { IFormInputs, IPersonalizationLatestVersion, IUser } from '@/Interface';
import Vue from 'vue';
import { getAccountAge } from '@/utils'; import { getAccountAge } from '@/utils';
import { GenericValue } from 'n8n-workflow'; import { GenericValue } from 'n8n-workflow';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
@@ -135,6 +134,7 @@ import { useUIStore } from '@/stores/ui';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
import { useRootStore } from '@/stores/n8nRootStore'; import { useRootStore } from '@/stores/n8nRootStore';
import { useUsersStore } from '@/stores/users'; import { useUsersStore } from '@/stores/users';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage, workflowHelpers).extend({ export default mixins(showMessage, workflowHelpers).extend({
components: { Modal }, components: { Modal },
@@ -146,8 +146,8 @@ export default mixins(showMessage, workflowHelpers).extend({
otherWorkAreaFieldVisible: false, otherWorkAreaFieldVisible: false,
otherCompanyIndustryFieldVisible: false, otherCompanyIndustryFieldVisible: false,
showAllIndustryQuestions: true, showAllIndustryQuestions: true,
modalBus: new Vue(), modalBus: createEventBus(),
formBus: new Vue(), formBus: createEventBus(),
}; };
}, },
computed: { computed: {
@@ -605,10 +605,10 @@ export default mixins(showMessage, workflowHelpers).extend({
}, },
methods: { methods: {
closeDialog() { closeDialog() {
this.modalBus.$emit('close'); this.modalBus.emit('close');
}, },
onSave() { onSave() {
this.formBus.$emit('submit'); this.formBus.emit('submit');
}, },
async onSubmit(values: IPersonalizationLatestVersion): Promise<void> { async onSubmit(values: IPersonalizationLatestVersion): Promise<void> {
this.$data.isSaving = true; this.$data.isSaving = true;

View File

@@ -493,7 +493,7 @@ import { genericHelpers } from '@/mixins/genericHelpers';
import { nodeHelpers } from '@/mixins/nodeHelpers'; import { nodeHelpers } from '@/mixins/nodeHelpers';
import { pinData } from '@/mixins/pinData'; import { pinData } from '@/mixins/pinData';
import { CodeEditor } from '@/components/forms'; import { CodeEditor } from '@/components/forms';
import { dataPinningEventBus } from '@/event-bus/data-pinning-event-bus'; import { dataPinningEventBus } from '@/event-bus';
import { clearJsonKey, executionDataToJson, stringSizeInBytes } from '@/utils'; import { clearJsonKey, executionDataToJson, stringSizeInBytes } from '@/utils';
import { isEmpty } from '@/utils'; import { isEmpty } from '@/utils';
import { useWorkflowsStore } from '@/stores/workflows'; import { useWorkflowsStore } from '@/stores/workflows';
@@ -595,8 +595,8 @@ export default mixins(externalHooks, genericHelpers, nodeHelpers, pinData).exten
this.init(); this.init();
if (!this.isPaneTypeInput) { if (!this.isPaneTypeInput) {
this.eventBus.$on('data-pinning-error', this.onDataPinningError); this.eventBus.on('data-pinning-error', this.onDataPinningError);
this.eventBus.$on('data-unpinning', this.onDataUnpinning); this.eventBus.on('data-unpinning', this.onDataUnpinning);
this.showPinDataDiscoveryTooltip(this.jsonData); this.showPinDataDiscoveryTooltip(this.jsonData);
} }
@@ -609,8 +609,8 @@ export default mixins(externalHooks, genericHelpers, nodeHelpers, pinData).exten
}, },
destroyed() { destroyed() {
this.hidePinDataDiscoveryTooltip(); this.hidePinDataDiscoveryTooltip();
this.eventBus.$off('data-pinning-error', this.onDataPinningError); this.eventBus.off('data-pinning-error', this.onDataPinningError);
this.eventBus.$off('data-unpinning', this.onDataUnpinning); this.eventBus.off('data-unpinning', this.onDataUnpinning);
}, },
computed: { computed: {
...mapStores(useNodeTypesStore, useNDVStore, useWorkflowsStore), ...mapStores(useNodeTypesStore, useNDVStore, useWorkflowsStore),
@@ -908,7 +908,7 @@ export default mixins(externalHooks, genericHelpers, nodeHelpers, pinData).exten
setTimeout(() => { setTimeout(() => {
this.isControlledPinDataTooltip = true; this.isControlledPinDataTooltip = true;
this.pinDataDiscoveryTooltipVisible = true; this.pinDataDiscoveryTooltipVisible = true;
this.eventBus.$emit('data-pinning-discovery', { isTooltipVisible: true }); this.eventBus.emit('data-pinning-discovery', { isTooltipVisible: true });
}, 500); // Wait for NDV to open }, 500); // Wait for NDV to open
} }
}, },
@@ -916,7 +916,7 @@ export default mixins(externalHooks, genericHelpers, nodeHelpers, pinData).exten
if (this.pinDataDiscoveryTooltipVisible) { if (this.pinDataDiscoveryTooltipVisible) {
this.isControlledPinDataTooltip = false; this.isControlledPinDataTooltip = false;
this.pinDataDiscoveryTooltipVisible = false; this.pinDataDiscoveryTooltipVisible = false;
this.eventBus.$emit('data-pinning-discovery', { isTooltipVisible: false }); this.eventBus.emit('data-pinning-discovery', { isTooltipVisible: false });
} }
}, },
pinDataDiscoveryComplete() { pinDataDiscoveryComplete() {

View File

@@ -51,7 +51,7 @@ import mixins from 'vue-typed-mixins';
import { EnterpriseEditionFeature } from '@/constants'; import { EnterpriseEditionFeature } from '@/constants';
import { showMessage } from '@/mixins/showMessage'; import { showMessage } from '@/mixins/showMessage';
import { useLogStreamingStore } from '../../stores/logStreamingStore'; import { useLogStreamingStore } from '../../stores/logStreamingStore';
import Vue from 'vue'; import Vue, { PropType } from 'vue';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { import {
deepCopy, deepCopy,
@@ -59,6 +59,7 @@ import {
MessageEventBusDestinationOptions, MessageEventBusDestinationOptions,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { BaseTextKey } from '../../plugins/i18n'; import { BaseTextKey } from '../../plugins/i18n';
import { EventBus } from '@/event-bus';
export const DESTINATION_LIST_ITEM_ACTIONS = { export const DESTINATION_LIST_ITEM_ACTIONS = {
OPEN: 'open', OPEN: 'open',
@@ -75,7 +76,7 @@ export default mixins(showMessage).extend({
components: {}, components: {},
props: { props: {
eventBus: { eventBus: {
type: Vue, type: Object as PropType<EventBus>,
}, },
destination: { destination: {
type: Object, type: Object,
@@ -91,7 +92,7 @@ export default mixins(showMessage).extend({
deepCopy(defaultMessageEventBusDestinationOptions), deepCopy(defaultMessageEventBusDestinationOptions),
this.destination, this.destination,
); );
this.eventBus.$on('destinationWasSaved', () => { this.eventBus.on('destinationWasSaved', () => {
const updatedDestination = this.logStreamingStore.getDestination(this.destination.id); const updatedDestination = this.logStreamingStore.getDestination(this.destination.id);
if (updatedDestination) { if (updatedDestination) {
this.nodeParameters = Object.assign( this.nodeParameters = Object.assign(

View File

@@ -193,7 +193,7 @@ import {
defaultMessageEventBusDestinationSyslogOptions, defaultMessageEventBusDestinationSyslogOptions,
defaultMessageEventBusDestinationSentryOptions, defaultMessageEventBusDestinationSentryOptions,
} from 'n8n-workflow'; } from 'n8n-workflow';
import Vue from 'vue'; import Vue, { PropType } from 'vue';
import { LOG_STREAM_MODAL_KEY } from '../../constants'; import { LOG_STREAM_MODAL_KEY } from '../../constants';
import Modal from '@/components/Modal.vue'; import Modal from '@/components/Modal.vue';
import { showMessage } from '@/mixins/showMessage'; import { showMessage } from '@/mixins/showMessage';
@@ -210,6 +210,7 @@ import InlineNameEdit from '../InlineNameEdit.vue';
import SaveButton from '../SaveButton.vue'; import SaveButton from '../SaveButton.vue';
import EventSelection from '@/components/SettingsLogStreaming/EventSelection.ee.vue'; import EventSelection from '@/components/SettingsLogStreaming/EventSelection.ee.vue';
import { Checkbox } from 'element-ui'; import { Checkbox } from 'element-ui';
import { createEventBus, EventBus } from '@/event-bus';
export default mixins(showMessage).extend({ export default mixins(showMessage).extend({
name: 'event-destination-settings-modal', name: 'event-destination-settings-modal',
@@ -221,7 +222,7 @@ export default mixins(showMessage).extend({
}, },
isNew: Boolean, isNew: Boolean,
eventBus: { eventBus: {
type: Vue, type: Object as PropType<EventBus>,
}, },
}, },
components: { components: {
@@ -248,7 +249,7 @@ export default mixins(showMessage).extend({
webhookDescription: webhookModalDescription, webhookDescription: webhookModalDescription,
sentryDescription: sentryModalDescription, sentryDescription: sentryModalDescription,
syslogDescription: syslogModalDescription, syslogDescription: syslogModalDescription,
modalBus: new Vue(), modalBus: createEventBus(),
headerLabel: this.$props.destination.label, headerLabel: this.$props.destination.label,
testMessageSent: false, testMessageSent: false,
testMessageResult: false, testMessageResult: false,
@@ -450,7 +451,7 @@ export default mixins(showMessage).extend({
if (deleteConfirmed === false) { if (deleteConfirmed === false) {
return; return;
} else { } else {
this.$props.eventBus.$emit('remove', this.destination.id); this.$props.eventBus.emit('remove', this.destination.id);
this.uiStore.closeModal(LOG_STREAM_MODAL_KEY); this.uiStore.closeModal(LOG_STREAM_MODAL_KEY);
this.uiStore.stateIsDirty = false; this.uiStore.stateIsDirty = false;
} }
@@ -461,7 +462,7 @@ export default mixins(showMessage).extend({
this.logStreamingStore.removeDestination(this.nodeParameters.id!); this.logStreamingStore.removeDestination(this.nodeParameters.id!);
} }
this.ndvStore.activeNodeName = null; this.ndvStore.activeNodeName = null;
this.$props.eventBus.$emit('closing', this.destination.id); this.$props.eventBus.emit('closing', this.destination.id);
this.uiStore.stateIsDirty = false; this.uiStore.stateIsDirty = false;
}, },
async saveDestination() { async saveDestination() {
@@ -473,7 +474,7 @@ export default mixins(showMessage).extend({
this.hasOnceBeenSaved = true; this.hasOnceBeenSaved = true;
this.testMessageSent = false; this.testMessageSent = false;
this.unchanged = true; this.unchanged = true;
this.$props.eventBus.$emit('destinationWasSaved', this.destination.id); this.$props.eventBus.emit('destinationWasSaved', this.destination.id);
this.uiStore.stateIsDirty = false; this.uiStore.stateIsDirty = false;
} }
}, },

View File

@@ -64,13 +64,22 @@ import { showMessage } from '@/mixins/showMessage';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
import { useTagsStore } from '@/stores/tags'; import { useTagsStore } from '@/stores/tags';
import { EventBus } from '@/event-bus';
import { PropType } from 'vue';
const MANAGE_KEY = '__manage'; const MANAGE_KEY = '__manage';
const CREATE_KEY = '__create'; const CREATE_KEY = '__create';
export default mixins(showMessage).extend({ export default mixins(showMessage).extend({
name: 'TagsDropdown', name: 'TagsDropdown',
props: ['placeholder', 'currentTagIds', 'createEnabled', 'eventBus'], props: {
placeholder: {},
currentTagIds: {},
createEnabled: {},
eventBus: {
type: Object as PropType<EventBus>,
},
},
data() { data() {
return { return {
filter: '', filter: '',
@@ -109,7 +118,7 @@ export default mixins(showMessage).extend({
} }
if (this.$props.eventBus) { if (this.$props.eventBus) {
this.$props.eventBus.$on('focus', () => { this.$props.eventBus.on('focus', () => {
this.focusOnInput(); this.focusOnInput();
this.focusOnTopOption(); this.focusOnTopOption();
}); });

View File

@@ -40,6 +40,7 @@ import Modal from '@/components/Modal.vue';
import { TAGS_MANAGER_MODAL_KEY } from '../../constants'; import { TAGS_MANAGER_MODAL_KEY } from '../../constants';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useTagsStore } from '@/stores/tags'; import { useTagsStore } from '@/stores/tags';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage).extend({ export default mixins(showMessage).extend({
name: 'TagsManager', name: 'TagsManager',
@@ -51,7 +52,7 @@ export default mixins(showMessage).extend({
return { return {
tagIds, tagIds,
isCreating: false, isCreating: false,
modalBus: new Vue(), modalBus: createEventBus(),
TAGS_MANAGER_MODAL_KEY, TAGS_MANAGER_MODAL_KEY,
}; };
}, },
@@ -176,7 +177,7 @@ export default mixins(showMessage).extend({
} else if (!this.hasTags) { } else if (!this.hasTags) {
this.onEnableCreate(); this.onEnableCreate();
} else { } else {
this.modalBus.$emit('close'); this.modalBus.emit('close');
} }
}, },
}, },

View File

@@ -63,10 +63,10 @@ import ModalDrawer from './ModalDrawer.vue';
import mixins from 'vue-typed-mixins'; import mixins from 'vue-typed-mixins';
import { workflowHelpers } from '@/mixins/workflowHelpers'; import { workflowHelpers } from '@/mixins/workflowHelpers';
import Vue from 'vue';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
import { useRootStore } from '@/stores/n8nRootStore'; import { useRootStore } from '@/stores/n8nRootStore';
import { createEventBus } from '@/event-bus';
const DEFAULT_TITLE = 'How likely are you to recommend n8n to a friend or colleague?'; const DEFAULT_TITLE = 'How likely are you to recommend n8n to a friend or colleague?';
const GREAT_FEEDBACK_TITLE = const GREAT_FEEDBACK_TITLE =
@@ -114,7 +114,7 @@ export default mixins(workflowHelpers).extend({
}, },
showButtons: true, showButtons: true,
VALUE_SURVEY_MODAL_KEY, VALUE_SURVEY_MODAL_KEY,
modalBus: new Vue(), modalBus: createEventBus(),
}; };
}, },
methods: { methods: {
@@ -178,7 +178,7 @@ export default mixins(workflowHelpers).extend({
this.form.email = ''; this.form.email = '';
this.showButtons = true; this.showButtons = true;
}, 1000); }, 1000);
this.modalBus.$emit('close'); this.modalBus.emit('close');
} }
}, },
}, },

View File

@@ -59,7 +59,6 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue';
import { IVariableSelectorOption, IVariableItemSelected } from '@/Interface'; import { IVariableSelectorOption, IVariableItemSelected } from '@/Interface';
import { externalHooks } from '@/mixins/externalHooks'; import { externalHooks } from '@/mixins/externalHooks';
import mixins from 'vue-typed-mixins'; import mixins from 'vue-typed-mixins';

View File

@@ -355,6 +355,7 @@ import { useSettingsStore } from '@/stores/settings';
import { useRootStore } from '@/stores/n8nRootStore'; import { useRootStore } from '@/stores/n8nRootStore';
import useWorkflowsEEStore from '@/stores/workflows.ee'; import useWorkflowsEEStore from '@/stores/workflows.ee';
import { useUsersStore } from '@/stores/users'; import { useUsersStore } from '@/stores/users';
import { createEventBus } from '@/event-bus';
export default mixins(externalHooks, genericHelpers, restApi, showMessage).extend({ export default mixins(externalHooks, genericHelpers, restApi, showMessage).extend({
name: 'WorkflowSettings', name: 'WorkflowSettings',
@@ -407,7 +408,7 @@ export default mixins(externalHooks, genericHelpers, restApi, showMessage).exten
executionTimeout: 0, executionTimeout: 0,
maxExecutionTimeout: 0, maxExecutionTimeout: 0,
timeoutHMS: { hours: 0, minutes: 0, seconds: 0 } as ITimeoutHMS, timeoutHMS: { hours: 0, minutes: 0, seconds: 0 } as ITimeoutHMS,
modalBus: new Vue(), modalBus: createEventBus(),
WORKFLOW_SETTINGS_MODAL_KEY, WORKFLOW_SETTINGS_MODAL_KEY,
}; };
}, },
@@ -528,7 +529,7 @@ export default mixins(externalHooks, genericHelpers, restApi, showMessage).exten
: str.replace(/[^0-9,\s]/g, ''); : str.replace(/[^0-9,\s]/g, '');
}, },
closeDialog() { closeDialog() {
this.modalBus.$emit('close'); this.modalBus.emit('close');
this.$externalHooks().run('workflowSettings.dialogVisibleChanged', { dialogVisible: false }); this.$externalHooks().run('workflowSettings.dialogVisibleChanged', { dialogVisible: false });
}, },
setTimeout(key: string, value: string) { setTimeout(key: string, value: string) {

View File

@@ -123,7 +123,6 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue';
import Modal from './Modal.vue'; import Modal from './Modal.vue';
import { import {
EnterpriseEditionFeature, EnterpriseEditionFeature,
@@ -135,7 +134,7 @@ import { IUser, IWorkflowDb, UIState } from '@/Interface';
import { getWorkflowPermissions, IPermissions } from '@/permissions'; import { getWorkflowPermissions, IPermissions } from '@/permissions';
import mixins from 'vue-typed-mixins'; import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage'; import { showMessage } from '@/mixins/showMessage';
import { nodeViewEventBus } from '@/event-bus/node-view-event-bus'; import { createEventBus, nodeViewEventBus } from '@/event-bus';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
@@ -168,7 +167,7 @@ export default mixins(showMessage).extend({
return { return {
WORKFLOW_SHARE_MODAL_KEY, WORKFLOW_SHARE_MODAL_KEY,
loading: true, loading: true,
modalBus: new Vue(), modalBus: createEventBus(),
sharedWith: [...(workflow.sharedWith || [])] as Array<Partial<IUser>>, sharedWith: [...(workflow.sharedWith || [])] as Array<Partial<IUser>>,
EnterpriseEditionFeature, EnterpriseEditionFeature,
}; };
@@ -262,7 +261,7 @@ export default mixins(showMessage).extend({
const saveWorkflowPromise = () => { const saveWorkflowPromise = () => {
return new Promise<string>((resolve) => { return new Promise<string>((resolve) => {
if (this.workflow.id === PLACEHOLDER_EMPTY_WORKFLOW_ID) { if (this.workflow.id === PLACEHOLDER_EMPTY_WORKFLOW_ID) {
nodeViewEventBus.$emit('saveWorkflow', () => { nodeViewEventBus.emit('saveWorkflow', () => {
resolve(this.workflow.id); resolve(this.workflow.id);
}); });
} else { } else {
@@ -299,7 +298,7 @@ export default mixins(showMessage).extend({
} catch (error) { } catch (error) {
this.$showError(error, this.$locale.baseText('workflows.shareModal.onSave.error.title')); this.$showError(error, this.$locale.baseText('workflows.shareModal.onSave.error.title'));
} finally { } finally {
this.modalBus.$emit('close'); this.modalBus.emit('close');
this.loading = false; this.loading = false;
} }
}, },
@@ -428,7 +427,7 @@ export default mixins(showMessage).extend({
console.error(failure); console.error(failure);
} }
}); });
this.modalBus.$emit('close'); this.modalBus.emit('close');
}, },
trackTelemetry(data: ITelemetryTrackProperties) { trackTelemetry(data: ITelemetryTrackProperties) {
this.$telemetry.track('User selected sharee to remove', { this.$telemetry.track('User selected sharee to remove', {

View File

@@ -1,3 +0,0 @@
import Vue from 'vue';
export const codeNodeEditorEventBus = new Vue();

View File

@@ -0,0 +1,3 @@
import { createEventBus } from '@/event-bus';
export const codeNodeEditorEventBus = createEventBus();

View File

@@ -1,3 +0,0 @@
import Vue from 'vue';
export const dataPinningEventBus = new Vue();

View File

@@ -0,0 +1,3 @@
import { createEventBus } from '@/event-bus';
export const dataPinningEventBus = createEventBus();

View File

@@ -1,3 +0,0 @@
import Vue from 'vue';
export const htmlEditorEventBus = new Vue();

View File

@@ -0,0 +1,3 @@
import { createEventBus } from '@/event-bus';
export const htmlEditorEventBus = createEventBus();

View File

@@ -0,0 +1,5 @@
export * from 'n8n-design-system/utils/event-bus';
export * from './code-node-editor';
export * from './data-pinning';
export * from './html-editor';
export * from './node-view';

View File

@@ -1,3 +0,0 @@
import Vue from 'vue';
export const nodeViewEventBus = new Vue();

View File

@@ -0,0 +1,3 @@
import { createEventBus } from '@/event-bus';
export const nodeViewEventBus = createEventBus();

View File

@@ -25,7 +25,7 @@ import {
import mixins from 'vue-typed-mixins'; import mixins from 'vue-typed-mixins';
import { WORKFLOW_SETTINGS_MODAL_KEY } from '@/constants'; import { WORKFLOW_SETTINGS_MODAL_KEY } from '@/constants';
import { getTriggerNodeServiceName } from '@/utils'; import { getTriggerNodeServiceName } from '@/utils';
import { codeNodeEditorEventBus } from '@/event-bus/code-node-editor-event-bus'; import { codeNodeEditorEventBus } from '@/event-bus';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
import { useWorkflowsStore } from '@/stores/workflows'; import { useWorkflowsStore } from '@/stores/workflows';
@@ -335,7 +335,7 @@ export const pushConnection = mixins(
runDataExecuted.data.resultData.error && runDataExecuted.data.resultData.error &&
runDataExecuted.data.resultData.error.lineNumber; runDataExecuted.data.resultData.error.lineNumber;
codeNodeEditorEventBus.$emit('error-line-number', lineNumber || 'final'); codeNodeEditorEventBus.emit('error-line-number', lineNumber || 'final');
const workflow = this.getCurrentWorkflow(); const workflow = this.getCurrentWorkflow();
if (runDataExecuted.waitTill !== undefined) { if (runDataExecuted.waitTill !== undefined) {

View File

@@ -1,7 +1,7 @@
import { INodeUi } from '@/Interface'; import { INodeUi } from '@/Interface';
import { IConnection } from 'n8n-workflow'; import { IConnection } from 'n8n-workflow';
import Vue from 'vue';
import { XYPosition } from '../Interface'; import { XYPosition } from '../Interface';
import { createEventBus } from '@/event-bus';
// Command names don't serve any particular purpose in the app // Command names don't serve any particular purpose in the app
// but they make it easier to identify each command on stack // but they make it easier to identify each command on stack
@@ -21,7 +21,7 @@ export enum COMMANDS {
// this timeout in between canvas actions // this timeout in between canvas actions
// (0 is usually enough but leaving this just in case) // (0 is usually enough but leaving this just in case)
const CANVAS_ACTION_TIMEOUT = 10; const CANVAS_ACTION_TIMEOUT = 10;
export const historyBus = new Vue(); export const historyBus = createEventBus();
export abstract class Undoable {} export abstract class Undoable {}
@@ -75,7 +75,7 @@ export class MoveNodeCommand extends Command {
async revert(): Promise<void> { async revert(): Promise<void> {
return new Promise<void>((resolve) => { return new Promise<void>((resolve) => {
historyBus.$emit('nodeMove', { historyBus.emit('nodeMove', {
nodeName: this.nodeName, nodeName: this.nodeName,
position: this.oldPosition, position: this.oldPosition,
}); });
@@ -102,7 +102,7 @@ export class AddNodeCommand extends Command {
async revert(): Promise<void> { async revert(): Promise<void> {
return new Promise<void>((resolve) => { return new Promise<void>((resolve) => {
historyBus.$emit('revertAddNode', { node: this.node }); historyBus.emit('revertAddNode', { node: this.node });
resolve(); resolve();
}); });
} }
@@ -126,7 +126,7 @@ export class RemoveNodeCommand extends Command {
async revert(): Promise<void> { async revert(): Promise<void> {
return new Promise<void>((resolve) => { return new Promise<void>((resolve) => {
historyBus.$emit('revertRemoveNode', { node: this.node }); historyBus.emit('revertRemoveNode', { node: this.node });
resolve(); resolve();
}); });
} }
@@ -156,7 +156,7 @@ export class AddConnectionCommand extends Command {
async revert(): Promise<void> { async revert(): Promise<void> {
return new Promise<void>((resolve) => { return new Promise<void>((resolve) => {
historyBus.$emit('revertAddConnection', { connection: this.connectionData }); historyBus.emit('revertAddConnection', { connection: this.connectionData });
resolve(); resolve();
}); });
} }
@@ -187,7 +187,7 @@ export class RemoveConnectionCommand extends Command {
async revert(): Promise<void> { async revert(): Promise<void> {
return new Promise<void>((resolve) => { return new Promise<void>((resolve) => {
setTimeout(() => { setTimeout(() => {
historyBus.$emit('revertRemoveConnection', { connection: this.connectionData }); historyBus.emit('revertRemoveConnection', { connection: this.connectionData });
resolve(); resolve();
}, CANVAS_ACTION_TIMEOUT); }, CANVAS_ACTION_TIMEOUT);
}); });
@@ -218,7 +218,7 @@ export class EnableNodeToggleCommand extends Command {
async revert(): Promise<void> { async revert(): Promise<void> {
return new Promise<void>((resolve) => { return new Promise<void>((resolve) => {
historyBus.$emit('enableNodeToggle', { historyBus.emit('enableNodeToggle', {
nodeName: this.nodeName, nodeName: this.nodeName,
isDisabled: this.oldState, isDisabled: this.oldState,
}); });
@@ -251,7 +251,7 @@ export class RenameNodeCommand extends Command {
async revert(): Promise<void> { async revert(): Promise<void> {
return new Promise<void>((resolve) => { return new Promise<void>((resolve) => {
historyBus.$emit('revertRenameNode', { historyBus.emit('revertRenameNode', {
currentName: this.currentName, currentName: this.currentName,
newName: this.newName, newName: this.newName,
}); });

View File

@@ -57,7 +57,7 @@ import {
getWorkflows, getWorkflows,
} from '@/api/workflows'; } from '@/api/workflows';
import { useUIStore } from './ui'; import { useUIStore } from './ui';
import { dataPinningEventBus } from '@/event-bus/data-pinning-event-bus'; import { dataPinningEventBus } from '@/event-bus';
import { import {
isJsonKeyObject, isJsonKeyObject,
getPairedItemsMapping, getPairedItemsMapping,
@@ -462,7 +462,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, {
setWorkflowPinData(pinData: IPinData): void { setWorkflowPinData(pinData: IPinData): void {
Vue.set(this.workflow, 'pinData', pinData || {}); Vue.set(this.workflow, 'pinData', pinData || {});
dataPinningEventBus.$emit('pin-data', pinData || {}); dataPinningEventBus.emit('pin-data', pinData || {});
}, },
setWorkflowTagIds(tags: string[]): void { setWorkflowTagIds(tags: string[]): void {
@@ -523,7 +523,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, {
const uiStore = useUIStore(); const uiStore = useUIStore();
uiStore.stateIsDirty = true; uiStore.stateIsDirty = true;
dataPinningEventBus.$emit('pin-data', { [payload.node.name]: storedPinData }); dataPinningEventBus.emit('pin-data', { [payload.node.name]: storedPinData });
}, },
unpinData(payload: { node: INodeUi }): void { unpinData(payload: { node: INodeUi }): void {
@@ -537,7 +537,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, {
const uiStore = useUIStore(); const uiStore = useUIStore();
uiStore.stateIsDirty = true; uiStore.stateIsDirty = true;
dataPinningEventBus.$emit('unpin-data', { [payload.node.name]: undefined }); dataPinningEventBus.emit('unpin-data', { [payload.node.name]: undefined });
}, },
addConnection(data: { connection: IConnection[] }): void { addConnection(data: { connection: IConnection[] }): void {

View File

@@ -266,7 +266,7 @@ import { useUIStore } from '@/stores/ui';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
import { useUsersStore } from '@/stores/users'; import { useUsersStore } from '@/stores/users';
import { Route, RawLocation } from 'vue-router'; import { Route, RawLocation } from 'vue-router';
import { nodeViewEventBus } from '@/event-bus/node-view-event-bus'; import { dataPinningEventBus, nodeViewEventBus } from '@/event-bus';
import { useWorkflowsStore } from '@/stores/workflows'; import { useWorkflowsStore } from '@/stores/workflows';
import { useRootStore } from '@/stores/n8nRootStore'; import { useRootStore } from '@/stores/n8nRootStore';
import { useNDVStore } from '@/stores/ndv'; import { useNDVStore } from '@/stores/ndv';
@@ -276,7 +276,6 @@ import { useNodeTypesStore } from '@/stores/nodeTypes';
import { useCredentialsStore } from '@/stores/credentials'; import { useCredentialsStore } from '@/stores/credentials';
import { useTagsStore } from '@/stores/tags'; import { useTagsStore } from '@/stores/tags';
import { useNodeCreatorStore } from '@/stores/nodeCreator'; import { useNodeCreatorStore } from '@/stores/nodeCreator';
import { dataPinningEventBus } from '@/event-bus/data-pinning-event-bus';
import { useCanvasStore } from '@/stores/canvas'; import { useCanvasStore } from '@/stores/canvas';
import useWorkflowsEEStore from '@/stores/workflows.ee'; import useWorkflowsEEStore from '@/stores/workflows.ee';
import * as NodeViewUtils from '@/utils/nodeViewUtils'; import * as NodeViewUtils from '@/utils/nodeViewUtils';
@@ -3976,17 +3975,17 @@ export default mixins(
this.$root.$on('newWorkflow', this.newWorkflow); this.$root.$on('newWorkflow', this.newWorkflow);
this.$root.$on('importWorkflowData', this.onImportWorkflowDataEvent); this.$root.$on('importWorkflowData', this.onImportWorkflowDataEvent);
this.$root.$on('importWorkflowUrl', this.onImportWorkflowUrlEvent); this.$root.$on('importWorkflowUrl', this.onImportWorkflowUrlEvent);
historyBus.$on('nodeMove', this.onMoveNode); historyBus.on('nodeMove', this.onMoveNode);
historyBus.$on('revertAddNode', this.onRevertAddNode); historyBus.on('revertAddNode', this.onRevertAddNode);
historyBus.$on('revertRemoveNode', this.onRevertRemoveNode); historyBus.on('revertRemoveNode', this.onRevertRemoveNode);
historyBus.$on('revertAddConnection', this.onRevertAddConnection); historyBus.on('revertAddConnection', this.onRevertAddConnection);
historyBus.$on('revertRemoveConnection', this.onRevertRemoveConnection); historyBus.on('revertRemoveConnection', this.onRevertRemoveConnection);
historyBus.$on('revertRenameNode', this.onRevertNameChange); historyBus.on('revertRenameNode', this.onRevertNameChange);
historyBus.$on('enableNodeToggle', this.onRevertEnableToggle); historyBus.on('enableNodeToggle', this.onRevertEnableToggle);
dataPinningEventBus.$on('pin-data', this.addPinDataConnections); dataPinningEventBus.on('pin-data', this.addPinDataConnections);
dataPinningEventBus.$on('unpin-data', this.removePinDataConnections); dataPinningEventBus.on('unpin-data', this.removePinDataConnections);
nodeViewEventBus.$on('saveWorkflow', this.saveCurrentWorkflowExternal); nodeViewEventBus.on('saveWorkflow', this.saveCurrentWorkflowExternal);
this.canvasStore.isDemo = this.isDemo; this.canvasStore.isDemo = this.isDemo;
}, },
@@ -3999,17 +3998,17 @@ export default mixins(
this.$root.$off('newWorkflow', this.newWorkflow); this.$root.$off('newWorkflow', this.newWorkflow);
this.$root.$off('importWorkflowData', this.onImportWorkflowDataEvent); this.$root.$off('importWorkflowData', this.onImportWorkflowDataEvent);
this.$root.$off('importWorkflowUrl', this.onImportWorkflowUrlEvent); this.$root.$off('importWorkflowUrl', this.onImportWorkflowUrlEvent);
historyBus.$off('nodeMove', this.onMoveNode); historyBus.off('nodeMove', this.onMoveNode);
historyBus.$off('revertAddNode', this.onRevertAddNode); historyBus.off('revertAddNode', this.onRevertAddNode);
historyBus.$off('revertRemoveNode', this.onRevertRemoveNode); historyBus.off('revertRemoveNode', this.onRevertRemoveNode);
historyBus.$off('revertAddConnection', this.onRevertAddConnection); historyBus.off('revertAddConnection', this.onRevertAddConnection);
historyBus.$off('revertRemoveConnection', this.onRevertRemoveConnection); historyBus.off('revertRemoveConnection', this.onRevertRemoveConnection);
historyBus.$off('revertRenameNode', this.onRevertNameChange); historyBus.off('revertRenameNode', this.onRevertNameChange);
historyBus.$off('enableNodeToggle', this.onRevertEnableToggle); historyBus.off('enableNodeToggle', this.onRevertEnableToggle);
dataPinningEventBus.$off('pin-data', this.addPinDataConnections); dataPinningEventBus.off('pin-data', this.addPinDataConnections);
dataPinningEventBus.$off('unpin-data', this.removePinDataConnections); dataPinningEventBus.off('unpin-data', this.removePinDataConnections);
nodeViewEventBus.$off('saveWorkflow', this.saveCurrentWorkflowExternal); nodeViewEventBus.off('saveWorkflow', this.saveCurrentWorkflowExternal);
}, },
destroyed() { destroyed() {
this.resetWorkspace(); this.resetWorkspace();

View File

@@ -169,6 +169,7 @@ import { useUsersStore } from '@/stores/users';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
import { getLdapSynchronizations } from '@/api/ldap'; import { getLdapSynchronizations } from '@/api/ldap';
import { N8N_CONTACT_EMAIL, N8N_SALES_EMAIL } from '@/constants'; import { N8N_CONTACT_EMAIL, N8N_SALES_EMAIL } from '@/constants';
import { createEventBus } from '@/event-bus';
type FormValues = { type FormValues = {
loginEnabled: boolean; loginEnabled: boolean;
@@ -221,7 +222,7 @@ export default mixins(showMessage).extend({
loadingTable: false, loadingTable: false,
hasAnyChanges: false, hasAnyChanges: false,
formInputs: null as null | IFormInputs, formInputs: null as null | IFormInputs,
formBus: new Vue(), formBus: createEventBus(),
readyToSubmit: false, readyToSubmit: false,
page: 0, page: 0,
loginEnabled: false, loginEnabled: false,
@@ -354,7 +355,7 @@ export default mixins(showMessage).extend({
} }
}, },
onSaveClick() { onSaveClick() {
this.formBus.$emit('submit'); this.formBus.emit('submit');
}, },
async onTestConnectionClick() { async onTestConnectionClick() {
this.loadingTestConnection = true; this.loadingTestConnection = true;

View File

@@ -89,7 +89,6 @@ import { useLogStreamingStore } from '../stores/logStreamingStore';
import { useSettingsStore } from '../stores/settings'; import { useSettingsStore } from '../stores/settings';
import { useUIStore } from '../stores/ui'; import { useUIStore } from '../stores/ui';
import { LOG_STREAM_MODAL_KEY, EnterpriseEditionFeature } from '../constants'; import { LOG_STREAM_MODAL_KEY, EnterpriseEditionFeature } from '../constants';
import Vue from 'vue';
import { import {
deepCopy, deepCopy,
defaultMessageEventBusDestinationOptions, defaultMessageEventBusDestinationOptions,
@@ -97,6 +96,7 @@ import {
} from 'n8n-workflow'; } from 'n8n-workflow';
import PageViewLayout from '@/components/layouts/PageViewLayout.vue'; import PageViewLayout from '@/components/layouts/PageViewLayout.vue';
import EventDestinationCard from '@/components/SettingsLogStreaming/EventDestinationCard.ee.vue'; import EventDestinationCard from '@/components/SettingsLogStreaming/EventDestinationCard.ee.vue';
import { createEventBus } from '@/event-bus';
export default mixins().extend({ export default mixins().extend({
name: 'SettingsLogStreamingView', name: 'SettingsLogStreamingView',
@@ -107,7 +107,7 @@ export default mixins().extend({
}, },
data() { data() {
return { return {
eventBus: new Vue(), eventBus: createEventBus(),
destinations: Array<MessageEventBusDestinationOptions>, destinations: Array<MessageEventBusDestinationOptions>,
disableLicense: false, disableLicense: false,
allDestinations: [] as MessageEventBusDestinationOptions[], allDestinations: [] as MessageEventBusDestinationOptions[],
@@ -135,15 +135,15 @@ export default mixins().extend({
} }
}); });
// refresh when a modal closes // refresh when a modal closes
this.eventBus.$on('destinationWasSaved', async () => { this.eventBus.on('destinationWasSaved', async () => {
this.$forceUpdate(); this.$forceUpdate();
}); });
// listen to remove emission // listen to remove emission
this.eventBus.$on('remove', async (destinationId: string) => { this.eventBus.on('remove', async (destinationId: string) => {
await this.onRemove(destinationId); await this.onRemove(destinationId);
}); });
// listen to modal closing and remove nodes from store // listen to modal closing and remove nodes from store
this.eventBus.$on('closing', async (destinationId: string) => { this.eventBus.on('closing', async (destinationId: string) => {
this.workflowsStore.removeAllNodes({ setStateDirty: false, removePinData: true }); this.workflowsStore.removeAllNodes({ setStateDirty: false, removePinData: true });
this.uiStore.stateIsDirty = false; this.uiStore.stateIsDirty = false;
}); });

View File

@@ -65,8 +65,8 @@ import { useUIStore } from '@/stores/ui';
import { useUsersStore } from '@/stores/users'; import { useUsersStore } from '@/stores/users';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import Vue from 'vue';
import mixins from 'vue-typed-mixins'; import mixins from 'vue-typed-mixins';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage).extend({ export default mixins(showMessage).extend({
name: 'SettingsPersonalView', name: 'SettingsPersonalView',
@@ -74,7 +74,7 @@ export default mixins(showMessage).extend({
return { return {
hasAnyChanges: false, hasAnyChanges: false,
formInputs: null as null | IFormInputs, formInputs: null as null | IFormInputs,
formBus: new Vue(), formBus: createEventBus(),
readyToSubmit: false, readyToSubmit: false,
}; };
}, },
@@ -160,7 +160,7 @@ export default mixins(showMessage).extend({
} }
}, },
onSaveClick() { onSaveClick() {
this.formBus.$emit('submit'); this.formBus.emit('submit');
}, },
openPasswordModal() { openPasswordModal() {
this.uiStore.openModal(CHANGE_PASSWORD_MODAL_KEY); this.uiStore.openModal(CHANGE_PASSWORD_MODAL_KEY);