refactor(editor): Turn showMessage mixin to composable (#6081)

* refactor(editor): move $getExecutionError from showMessages mixin to pushConnection (it is used there only)

* refactor(editor): resolve showMessage mixin methods

* fix(editor): use composable instead of mixin

* fix(editor): resolve conflicts

* fix(editor): replace clearAllStickyNotifications

* fix(editor): replace confirmMessage

* fix(editor): replace confirmMessage

* fix(editor): replace confirmMessage

* fix(editor): remove last confirmMessage usage

* fix(editor): remove $prompt usage

* fix(editor): remove $show methods

* fix(editor): lint fix

* fix(editor): lint fix

* fix(editor): fixes after review
This commit is contained in:
Csaba Tuncsik 2023-05-12 10:13:42 +02:00 committed by GitHub
parent 0666377ef8
commit b95fcd7323
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
75 changed files with 990 additions and 862 deletions

View file

@ -27,29 +27,28 @@
</template>
<script lang="ts">
import Modals from './components/Modals.vue';
import LoadingView from './views/LoadingView.vue';
import Telemetry from './components/Telemetry.vue';
import { HIRING_BANNER, LOCAL_STORAGE_THEME, VIEWS } from './constants';
import Modals from '@/components/Modals.vue';
import LoadingView from '@/views/LoadingView.vue';
import Telemetry from '@/components/Telemetry.vue';
import { HIRING_BANNER, LOCAL_STORAGE_THEME, VIEWS } from '@/constants';
import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage';
import { userHelpers } from '@/mixins/userHelpers';
import { loadLanguage } from './plugins/i18n';
import useGlobalLinkActions from '@/composables/useGlobalLinkActions';
import { loadLanguage } from '@/plugins/i18n';
import { useGlobalLinkActions, useToast } from '@/composables';
import { mapStores } from 'pinia';
import { useUIStore } from './stores/ui.store';
import { useSettingsStore } from './stores/settings.store';
import { useUsersStore } from './stores/users.store';
import { useRootStore } from './stores/n8nRoot.store';
import { useTemplatesStore } from './stores/templates.store';
import { useNodeTypesStore } from './stores/nodeTypes.store';
import { useUIStore } from '@/stores/ui.store';
import { useSettingsStore } from '@/stores/settings.store';
import { useUsersStore } from '@/stores/users.store';
import { useRootStore } from '@/stores/n8nRoot.store';
import { useTemplatesStore } from '@/stores/templates.store';
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
import { useHistoryHelper } from '@/composables/useHistoryHelper';
import { newVersions } from '@/mixins/newVersions';
import { useRoute } from 'vue-router/composables';
import { useVersionControlStore } from '@/stores/versionControl.store';
export default mixins(newVersions, showMessage, userHelpers).extend({
export default mixins(newVersions, userHelpers).extend({
name: 'App',
components: {
LoadingView,
@ -60,6 +59,7 @@ export default mixins(newVersions, showMessage, userHelpers).extend({
return {
...useGlobalLinkActions(),
...useHistoryHelper(useRoute()),
...useToast(),
};
},
computed: {
@ -86,7 +86,7 @@ export default mixins(newVersions, showMessage, userHelpers).extend({
try {
await this.settingsStore.getSettings();
} catch (e) {
this.$showToast({
this.showToast({
title: this.$locale.baseText('startupError'),
message: this.$locale.baseText('startupError.message'),
type: 'error',

View file

@ -29,17 +29,17 @@
</template>
<script lang="ts">
import mixins from 'vue-typed-mixins';
import { defineComponent } from 'vue';
import { showMessage } from '@/mixins/showMessage';
import Modal from './Modal.vue';
import { useToast } from '@/composables';
import Modal from '@/components/Modal.vue';
import type { IFormInputs } from '@/Interface';
import { CHANGE_PASSWORD_MODAL_KEY } from '../constants';
import { CHANGE_PASSWORD_MODAL_KEY } from '@/constants';
import { mapStores } from 'pinia';
import { useUsersStore } from '@/stores/users.store';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage).extend({
export default defineComponent({
components: { Modal },
name: 'ChangePasswordModal',
props: {
@ -47,6 +47,11 @@ export default mixins(showMessage).extend({
type: String,
},
},
setup() {
return {
...useToast(),
};
},
data() {
return {
config: null as null | IFormInputs,
@ -127,7 +132,7 @@ export default mixins(showMessage).extend({
this.loading = true;
await this.usersStore.updateCurrentUserPassword(values);
this.$showMessage({
this.showMessage({
type: 'success',
title: this.$locale.baseText('auth.changePassword.passwordUpdated'),
message: this.$locale.baseText('auth.changePassword.passwordUpdatedMessage'),
@ -135,7 +140,7 @@ export default mixins(showMessage).extend({
this.modalBus.emit('close');
} catch (error) {
this.$showError(error, this.$locale.baseText('auth.changePassword.error'));
this.showError(error, this.$locale.baseText('auth.changePassword.error'));
}
this.loading = false;
},

View file

@ -65,11 +65,10 @@
import { useUIStore } from '@/stores/ui.store';
import type { PublicInstalledPackage } from 'n8n-workflow';
import { mapStores } from 'pinia';
import mixins from 'vue-typed-mixins';
import { NPM_PACKAGE_DOCS_BASE_URL, COMMUNITY_PACKAGE_MANAGE_ACTIONS } from '../constants';
import { showMessage } from '@/mixins/showMessage';
import { defineComponent } from 'vue';
import { NPM_PACKAGE_DOCS_BASE_URL, COMMUNITY_PACKAGE_MANAGE_ACTIONS } from '@/constants';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'CommunityPackageCard',
props: {
communityPackage: {

View file

@ -88,24 +88,29 @@
</template>
<script lang="ts">
import Modal from './Modal.vue';
import Modal from '@/components/Modal.vue';
import {
COMMUNITY_PACKAGE_INSTALL_MODAL_KEY,
NPM_KEYWORD_SEARCH_URL,
COMMUNITY_NODES_INSTALLATION_DOCS_URL,
COMMUNITY_NODES_RISKS_DOCS_URL,
} from '../constants';
import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage';
} from '@/constants';
import { defineComponent } from 'vue';
import { useToast } from '@/composables';
import { mapStores } from 'pinia';
import { useCommunityNodesStore } from '@/stores/communityNodes.store';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'CommunityPackageInstallModal',
components: {
Modal,
},
setup() {
return {
...useToast(),
};
},
data() {
return {
loading: false,
@ -144,7 +149,7 @@ export default mixins(showMessage).extend({
await this.communityNodesStore.fetchInstalledPackages();
this.loading = false;
this.modalBus.emit('close');
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('settings.communityNodes.messages.install.success'),
type: 'success',
});
@ -152,7 +157,7 @@ export default mixins(showMessage).extend({
if (error.httpStatusCode && error.httpStatusCode === 400) {
this.infoTextErrorMessage = error.message;
} else {
this.$showError(
this.showError(
error,
this.$locale.baseText('settings.communityNodes.messages.install.error'),
);

View file

@ -35,18 +35,15 @@
</template>
<script>
import mixins from 'vue-typed-mixins';
import Modal from './Modal.vue';
import {
COMMUNITY_PACKAGE_CONFIRM_MODAL_KEY,
COMMUNITY_PACKAGE_MANAGE_ACTIONS,
} from '../constants';
import { showMessage } from '@/mixins/showMessage';
import { defineComponent } from 'vue';
import Modal from '@/components/Modal.vue';
import { COMMUNITY_PACKAGE_CONFIRM_MODAL_KEY, COMMUNITY_PACKAGE_MANAGE_ACTIONS } from '@/constants';
import { useToast } from '@/composables';
import { mapStores } from 'pinia';
import { useCommunityNodesStore } from '@/stores/communityNodes.store';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'CommunityPackageManageConfirmModal',
components: {
Modal,
@ -64,6 +61,11 @@ export default mixins(showMessage).extend({
type: String,
},
},
setup() {
return {
...useToast(),
};
},
data() {
return {
loading: false,
@ -140,12 +142,12 @@ export default mixins(showMessage).extend({
});
this.loading = true;
await this.communityNodesStore.uninstallPackage(this.activePackageName);
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('settings.communityNodes.messages.uninstall.success.title'),
type: 'success',
});
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('settings.communityNodes.messages.uninstall.error'),
);
@ -167,7 +169,7 @@ export default mixins(showMessage).extend({
this.loading = true;
const updatedVersion = this.activePackage.updateAvailable;
await this.communityNodesStore.updatePackage(this.activePackageName);
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('settings.communityNodes.messages.update.success.title'),
message: this.$locale.baseText(
'settings.communityNodes.messages.update.success.message',
@ -181,7 +183,7 @@ export default mixins(showMessage).extend({
type: 'success',
});
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('settings.communityNodes.messages.update.error.title'),
);

View file

@ -38,16 +38,22 @@ import mixins from 'vue-typed-mixins';
import type { IN8nPromptResponse } from '@/Interface';
import { VALID_EMAIL_REGEX } from '@/constants';
import { workflowHelpers } from '@/mixins/workflowHelpers';
import Modal from './Modal.vue';
import Modal from '@/components/Modal.vue';
import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/settings.store';
import { useRootStore } from '@/stores/n8nRoot.store';
import { createEventBus } from '@/event-bus';
import { useToast } from '@/composables';
export default mixins(workflowHelpers).extend({
components: { Modal },
name: 'ContactPromptModal',
props: ['modalName'],
setup() {
return {
...useToast(),
};
},
data() {
return {
email: '',
@ -94,7 +100,7 @@ export default mixins(workflowHelpers).extend({
instance_id: this.rootStore.instanceId,
email: this.email,
});
this.$showMessage({
this.showMessage({
title: 'Thanks!',
message: "It's people like you that help make n8n better",
type: 'success',

View file

@ -19,9 +19,9 @@
<script lang="ts">
import mixins from 'vue-typed-mixins';
import { copyPaste } from '@/mixins/copyPaste';
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
export default mixins(copyPaste, showMessage).extend({
export default mixins(copyPaste).extend({
props: {
label: {
type: String,
@ -56,12 +56,17 @@ export default mixins(copyPaste, showMessage).extend({
default: 'large',
},
},
setup() {
return {
...useToast(),
};
},
methods: {
copy(): void {
this.$emit('copy');
this.copyToClipboard(this.value);
this.$showMessage({
this.showMessage({
title: this.toastTitle,
message: this.toastMessage,
type: 'success',

View file

@ -31,11 +31,11 @@
</template>
<script lang="ts">
import mixins from 'vue-typed-mixins';
import { defineComponent } from 'vue';
import type { ICredentialsResponse, IUser } from '@/Interface';
import type { ICredentialType } from 'n8n-workflow';
import { EnterpriseEditionFeature } from '@/constants';
import { showMessage } from '@/mixins/showMessage';
import { EnterpriseEditionFeature, MODAL_CONFIRM } from '@/constants';
import { useMessage } from '@/composables';
import CredentialIcon from '@/components/CredentialIcon.vue';
import type { IPermissions } from '@/permissions';
import { getCredentialPermissions } from '@/permissions';
@ -50,12 +50,17 @@ export const CREDENTIAL_LIST_ITEM_ACTIONS = {
DELETE: 'delete',
};
export default mixins(showMessage).extend({
export default defineComponent({
data() {
return {
EnterpriseEditionFeature,
};
},
setup() {
return {
...useMessage(),
};
},
components: {
CredentialIcon,
},
@ -128,7 +133,7 @@ export default mixins(showMessage).extend({
if (action === CREDENTIAL_LIST_ITEM_ACTIONS.OPEN) {
await this.onClick();
} else if (action === CREDENTIAL_LIST_ITEM_ACTIONS.DELETE) {
const deleteConfirmed = await this.confirmMessage(
const deleteConfirmed = await this.confirm(
this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.deleteCredential.message',
{
@ -138,13 +143,14 @@ export default mixins(showMessage).extend({
this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.deleteCredential.headline',
),
null,
this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.deleteCredential.confirmButtonText',
),
{
confirmButtonText: this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.deleteCredential.confirmButtonText',
),
},
);
if (deleteConfirmed) {
if (deleteConfirmed === MODAL_CONFIRM) {
await this.credentialsStore.deleteCredential({ id: this.data.id });
}
}

View file

@ -127,21 +127,21 @@ import type {
ITelemetryTrackProperties,
} from 'n8n-workflow';
import { NodeHelpers } from 'n8n-workflow';
import CredentialIcon from '../CredentialIcon.vue';
import CredentialIcon from '@/components/CredentialIcon.vue';
import mixins from 'vue-typed-mixins';
import { nodeHelpers } from '@/mixins/nodeHelpers';
import { showMessage } from '@/mixins/showMessage';
import { useToast, useMessage } from '@/composables';
import CredentialConfig from './CredentialConfig.vue';
import CredentialInfo from './CredentialInfo.vue';
import CredentialSharing from './CredentialSharing.ee.vue';
import SaveButton from '../SaveButton.vue';
import Modal from '../Modal.vue';
import InlineNameEdit from '../InlineNameEdit.vue';
import { CREDENTIAL_EDIT_MODAL_KEY, EnterpriseEditionFeature } from '@/constants';
import CredentialConfig from '@/components/CredentialEdit/CredentialConfig.vue';
import CredentialInfo from '@/components/CredentialEdit/CredentialInfo.vue';
import CredentialSharing from '@/components/CredentialEdit/CredentialSharing.ee.vue';
import SaveButton from '@/components/SaveButton.vue';
import Modal from '@/components/Modal.vue';
import InlineNameEdit from '@/components/InlineNameEdit.vue';
import { CREDENTIAL_EDIT_MODAL_KEY, EnterpriseEditionFeature, MODAL_CONFIRM } from '@/constants';
import type { IDataObject } from 'n8n-workflow';
import FeatureComingSoon from '../FeatureComingSoon.vue';
import FeatureComingSoon from '@/components/FeatureComingSoon.vue';
import type { IPermissions } from '@/permissions';
import { getCredentialPermissions } from '@/permissions';
import type { IMenuItem } from 'n8n-design-system';
@ -165,7 +165,7 @@ interface NodeAccessMap {
[nodeType: string]: ICredentialNodeAccess | null;
}
export default mixins(showMessage, nodeHelpers).extend({
export default mixins(nodeHelpers).extend({
name: 'CredentialEdit',
components: {
CredentialSharing,
@ -190,6 +190,12 @@ export default mixins(showMessage, nodeHelpers).extend({
type: String,
},
},
setup() {
return {
...useToast(),
...useMessage(),
};
},
data() {
return {
activeTab: 'connection',
@ -486,7 +492,7 @@ export default mixins(showMessage, nodeHelpers).extend({
if (this.hasUnsavedChanges) {
const displayName = this.credentialType ? this.credentialType.displayName : '';
keepEditing = await this.confirmMessage(
const confirmAction = await this.confirm(
this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.beforeClose1.message',
{ interpolate: { credentialDisplayName: displayName } },
@ -494,30 +500,34 @@ export default mixins(showMessage, nodeHelpers).extend({
this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.beforeClose1.headline',
),
null,
this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.beforeClose1.cancelButtonText',
),
this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.beforeClose1.confirmButtonText',
),
{
cancelButtonText: this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.beforeClose1.cancelButtonText',
),
confirmButtonText: this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.beforeClose1.confirmButtonText',
),
},
);
keepEditing = confirmAction === MODAL_CONFIRM;
} else if (this.credentialPermissions.isOwner && this.isOAuthType && !this.isOAuthConnected) {
keepEditing = await this.confirmMessage(
const confirmAction = await this.confirm(
this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.beforeClose2.message',
),
this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.beforeClose2.headline',
),
null,
this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.beforeClose2.cancelButtonText',
),
this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.beforeClose2.confirmButtonText',
),
{
cancelButtonText: this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.beforeClose2.cancelButtonText',
),
confirmButtonText: this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.beforeClose2.confirmButtonText',
),
},
);
keepEditing = confirmAction === MODAL_CONFIRM;
}
if (!keepEditing) {
@ -596,7 +606,7 @@ export default mixins(showMessage, nodeHelpers).extend({
this.nodeAccess[access.nodeType] = access;
});
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('credentialEdit.credentialEdit.showError.loadCredential.title'),
);
@ -840,7 +850,7 @@ export default mixins(showMessage, nodeHelpers).extend({
credential = await this.credentialsStore.createNewCredential(credentialDetails);
this.hasUnsavedChanges = false;
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('credentialEdit.credentialEdit.showError.createCredential.title'),
);
@ -874,7 +884,7 @@ export default mixins(showMessage, nodeHelpers).extend({
});
this.hasUnsavedChanges = false;
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('credentialEdit.credentialEdit.showError.updateCredential.title'),
);
@ -902,7 +912,7 @@ export default mixins(showMessage, nodeHelpers).extend({
const savedCredentialName = this.currentCredential.name;
const deleteConfirmed = await this.confirmMessage(
const deleteConfirmed = await this.confirm(
this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.deleteCredential.message',
{ interpolate: { savedCredentialName } },
@ -910,13 +920,14 @@ export default mixins(showMessage, nodeHelpers).extend({
this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.deleteCredential.headline',
),
null,
this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.deleteCredential.confirmButtonText',
),
{
confirmButtonText: this.$locale.baseText(
'credentialEdit.credentialEdit.confirmMessage.deleteCredential.confirmButtonText',
),
},
);
if (deleteConfirmed === false) {
if (deleteConfirmed !== MODAL_CONFIRM) {
return;
}
@ -925,7 +936,7 @@ export default mixins(showMessage, nodeHelpers).extend({
await this.credentialsStore.deleteCredential({ id: this.credentialId });
this.hasUnsavedChanges = false;
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('credentialEdit.credentialEdit.showError.deleteCredential.title'),
);
@ -939,7 +950,7 @@ export default mixins(showMessage, nodeHelpers).extend({
this.updateNodesCredentialsIssues();
this.credentialData = {};
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('credentialEdit.credentialEdit.showMessage.title'),
type: 'success',
});
@ -968,7 +979,7 @@ export default mixins(showMessage, nodeHelpers).extend({
}
}
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText(
'credentialEdit.credentialEdit.showError.generateAuthorizationUrl.title',

View file

@ -81,17 +81,17 @@
<script lang="ts">
import type { IUser, IUserListAction } from '@/Interface';
import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage';
import { defineComponent } from 'vue';
import { useMessage } from '@/composables';
import { mapStores } from 'pinia';
import { useUsersStore } from '@/stores/users.store';
import { useSettingsStore } from '@/stores/settings.store';
import { useUIStore } from '@/stores/ui.store';
import { useCredentialsStore } from '@/stores/credentials.store';
import { useUsageStore } from '@/stores/usage.store';
import { EnterpriseEditionFeature, VIEWS } from '@/constants';
import { EnterpriseEditionFeature, MODAL_CONFIRM, VIEWS } from '@/constants';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'CredentialSharing',
props: [
'credential',
@ -101,6 +101,11 @@ export default mixins(showMessage).extend({
'credentialPermissions',
'modalBus',
],
setup() {
return {
...useMessage(),
};
},
computed: {
...mapStores(useCredentialsStore, useUsersStore, useUsageStore, useUIStore, useSettingsStore),
usersListActions(): IUserListAction[] {
@ -148,21 +153,22 @@ export default mixins(showMessage).extend({
const user = this.usersStore.getUserById(userId);
if (user) {
const confirm = await this.confirmMessage(
const confirm = await this.confirm(
this.$locale.baseText('credentialEdit.credentialSharing.list.delete.confirm.message', {
interpolate: { name: user.fullName || '' },
}),
this.$locale.baseText('credentialEdit.credentialSharing.list.delete.confirm.title'),
null,
this.$locale.baseText(
'credentialEdit.credentialSharing.list.delete.confirm.confirmButtonText',
),
this.$locale.baseText(
'credentialEdit.credentialSharing.list.delete.confirm.cancelButtonText',
),
{
confirmButtonText: this.$locale.baseText(
'credentialEdit.credentialSharing.list.delete.confirm.confirmButtonText',
),
cancelButtonText: this.$locale.baseText(
'credentialEdit.credentialSharing.list.delete.confirm.cancelButtonText',
),
},
);
if (confirm) {
if (confirm === MODAL_CONFIRM) {
this.$emit(
'change',
this.credentialData.sharedWith.filter((sharee: IUser) => {

View file

@ -70,16 +70,15 @@
</template>
<script lang="ts">
import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage';
import Modal from './Modal.vue';
import type { IUser } from '../Interface';
import { defineComponent } from 'vue';
import { useToast } from '@/composables';
import Modal from '@/components/Modal.vue';
import type { IUser } from '@/Interface';
import { mapStores } from 'pinia';
import { useUsersStore } from '@/stores/users.store';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage).extend({
export default defineComponent({
components: {
Modal,
},
@ -92,6 +91,11 @@ export default mixins(showMessage).extend({
type: String,
},
},
setup() {
return {
...useToast(),
};
},
data() {
return {
modalBus: createEventBus(),
@ -169,7 +173,7 @@ export default mixins(showMessage).extend({
}
}
this.$showMessage({
this.showMessage({
type: 'success',
title: this.$locale.baseText('settings.users.userDeleted'),
message,
@ -177,7 +181,7 @@ export default mixins(showMessage).extend({
this.modalBus.emit('close');
} catch (error) {
this.$showError(error, this.$locale.baseText('settings.users.userDeletedError'));
this.showError(error, this.$locale.baseText('settings.users.userDeletedError'));
}
this.loading = false;
},

View file

@ -53,9 +53,9 @@ import mixins from 'vue-typed-mixins';
import { MAX_WORKFLOW_NAME_LENGTH, PLACEHOLDER_EMPTY_WORKFLOW_ID } from '@/constants';
import { workflowHelpers } from '@/mixins/workflowHelpers';
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
import TagsDropdown from '@/components/TagsDropdown.vue';
import Modal from './Modal.vue';
import Modal from '@/components/Modal.vue';
import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/settings.store';
import { useWorkflowsStore } from '@/stores/workflows.store';
@ -66,10 +66,15 @@ import { useUsersStore } from '@/stores/users.store';
import { createEventBus } from '@/event-bus';
import { useCredentialsStore } from '@/stores';
export default mixins(showMessage, workflowHelpers).extend({
export default mixins(workflowHelpers).extend({
components: { TagsDropdown, Modal },
name: 'DuplicateWorkflow',
props: ['modalName', 'isActive', 'data'],
setup() {
return {
...useToast(),
};
},
data() {
const currentTagIds = this.data.tags;
@ -134,7 +139,7 @@ export default mixins(showMessage, workflowHelpers).extend({
async save(): Promise<void> {
const name = this.name.trim();
if (!name) {
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('duplicateWorkflowDialog.errors.missingName.title'),
message: this.$locale.baseText('duplicateWorkflowDialog.errors.missingName.message'),
type: 'error',
@ -181,12 +186,12 @@ export default mixins(showMessage, workflowHelpers).extend({
if (error.httpStatusCode === 403) {
error.message = this.$locale.baseText('duplicateWorkflowDialog.errors.forbidden.message');
this.$showError(
this.showError(
error,
this.$locale.baseText('duplicateWorkflowDialog.errors.forbidden.title'),
);
} else {
this.$showError(
this.showError(
error,
this.$locale.baseText('duplicateWorkflowDialog.errors.generic.title'),
);

View file

@ -118,10 +118,9 @@
</template>
<script lang="ts">
//@ts-ignore
import VueJsonPretty from 'vue-json-pretty';
import { copyPaste } from '@/mixins/copyPaste';
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
import mixins from 'vue-typed-mixins';
import { MAX_DISPLAY_DATA_SIZE } from '@/constants';
@ -131,12 +130,17 @@ import { mapStores } from 'pinia';
import { useNDVStore } from '@/stores/ndv.store';
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
export default mixins(copyPaste, showMessage).extend({
export default mixins(copyPaste).extend({
name: 'NodeErrorView',
props: ['error'],
components: {
VueJsonPretty,
},
setup() {
return {
...useToast(),
};
},
computed: {
...mapStores(useNodeTypesStore, useNDVStore),
displayCause(): boolean {
@ -251,7 +255,7 @@ export default mixins(copyPaste, showMessage).extend({
this.copySuccess();
},
copySuccess() {
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('nodeErrorView.showMessage.title'),
type: 'info',
});

View file

@ -285,10 +285,10 @@ import ExecutionTime from '@/components/ExecutionTime.vue';
import WorkflowActivator from '@/components/WorkflowActivator.vue';
import ExecutionFilter from '@/components/ExecutionFilter.vue';
import { externalHooks } from '@/mixins/externalHooks';
import { VIEWS, WAIT_TIME_UNLIMITED } from '@/constants';
import { MODAL_CONFIRM, VIEWS, WAIT_TIME_UNLIMITED } from '@/constants';
import { genericHelpers } from '@/mixins/genericHelpers';
import { executionHelpers } from '@/mixins/executionsHelpers';
import { showMessage } from '@/mixins/showMessage';
import { useToast, useMessage } from '@/composables';
import type {
IExecutionsCurrentSummaryExtended,
IExecutionDeleteFilter,
@ -306,13 +306,19 @@ import { useWorkflowsStore } from '@/stores/workflows.store';
import { isEmpty, setPageTitle } from '@/utils';
import { executionFilterToQueryFilter } from '@/utils/executionUtils';
export default mixins(externalHooks, genericHelpers, executionHelpers, showMessage).extend({
export default mixins(externalHooks, genericHelpers, executionHelpers).extend({
name: 'ExecutionsList',
components: {
ExecutionTime,
WorkflowActivator,
ExecutionFilter,
},
setup() {
return {
...useToast(),
...useMessage(),
};
},
data() {
return {
isMounting: true,
@ -444,17 +450,21 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, showMessa
Object.keys(this.selectedItems).length === this.finishedExecutionsCount;
},
async handleDeleteSelected() {
const deleteExecutions = await this.confirmMessage(
const deleteExecutions = await this.confirm(
this.$locale.baseText('executionsList.confirmMessage.message', {
interpolate: { numSelected: this.numSelected.toString() },
}),
this.$locale.baseText('executionsList.confirmMessage.headline'),
'warning',
this.$locale.baseText('executionsList.confirmMessage.confirmButtonText'),
this.$locale.baseText('executionsList.confirmMessage.cancelButtonText'),
{
type: 'warning',
confirmButtonText: this.$locale.baseText(
'executionsList.confirmMessage.confirmButtonText',
),
cancelButtonText: this.$locale.baseText('executionsList.confirmMessage.cancelButtonText'),
},
);
if (!deleteExecutions) {
if (deleteExecutions !== MODAL_CONFIRM) {
return;
}
@ -473,7 +483,7 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, showMessa
await this.workflowsStore.deleteExecutions(sendData);
} catch (error) {
this.isDataLoading = false;
this.$showError(
this.showError(
error,
this.$locale.baseText('executionsList.showError.handleDeleteSelected.title'),
);
@ -482,7 +492,7 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, showMessa
}
this.isDataLoading = false;
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('executionsList.showMessage.handleDeleteSelected.title'),
type: 'success',
});
@ -673,7 +683,7 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, showMessa
);
} catch (error) {
this.isDataLoading = false;
this.$showError(error, this.$locale.baseText('executionsList.showError.loadMore.title'));
this.showError(error, this.$locale.baseText('executionsList.showError.loadMore.title'));
return;
}
@ -713,7 +723,7 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, showMessa
Vue.set(this, 'workflows', workflows);
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('executionsList.showError.loadWorkflows.title'),
);
@ -729,12 +739,12 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, showMessa
);
if (retrySuccessful) {
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('executionsList.showMessage.retrySuccessfulTrue.title'),
type: 'success',
});
} else {
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('executionsList.showMessage.retrySuccessfulFalse.title'),
type: 'error',
});
@ -742,7 +752,7 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, showMessa
this.isDataLoading = false;
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('executionsList.showError.retryExecution.title'),
);
@ -756,7 +766,7 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, showMessa
try {
await Promise.all([this.loadActiveExecutions(), this.loadFinishedExecutions()]);
} catch (error) {
this.$showError(error, this.$locale.baseText('executionsList.showError.refreshData.title'));
this.showError(error, this.$locale.baseText('executionsList.showError.refreshData.title'));
}
this.isDataLoading = false;
@ -856,7 +866,7 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, showMessa
const index = this.stoppingExecutions.indexOf(activeExecutionId);
this.stoppingExecutions.splice(index, 1);
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('executionsList.showMessage.stopExecution.title'),
message: this.$locale.baseText('executionsList.showMessage.stopExecution.message', {
interpolate: { activeExecutionId },
@ -866,7 +876,7 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, showMessa
this.refreshData();
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('executionsList.showError.stopExecution.title'),
);
@ -892,7 +902,7 @@ export default mixins(externalHooks, genericHelpers, executionHelpers, showMessa
this.selectAllVisibleExecutions();
}
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('executionsList.showError.handleDeleteSelected.title'),
);

View file

@ -86,10 +86,9 @@ import mixins from 'vue-typed-mixins';
import type { IExecutionUIData } from '@/mixins/executionsHelpers';
import { executionHelpers } from '@/mixins/executionsHelpers';
import { VIEWS } from '@/constants';
import { showMessage } from '@/mixins/showMessage';
import ExecutionTime from '@/components/ExecutionTime.vue';
export default mixins(executionHelpers, showMessage).extend({
export default mixins(executionHelpers).extend({
name: 'execution-card',
components: {
ExecutionTime,

View file

@ -127,18 +127,18 @@
<script lang="ts">
import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage';
import { useMessage } from '@/composables';
import WorkflowPreview from '@/components/WorkflowPreview.vue';
import type { IExecutionUIData } from '@/mixins/executionsHelpers';
import { executionHelpers } from '@/mixins/executionsHelpers';
import { VIEWS } from '@/constants';
import { MODAL_CONFIRM, VIEWS } from '@/constants';
import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui.store';
import { Dropdown as ElDropdown } from 'element-ui';
type RetryDropdownRef = InstanceType<typeof ElDropdown> & { hide: () => void };
export default mixins(showMessage, executionHelpers).extend({
export default mixins(executionHelpers).extend({
name: 'execution-preview',
components: {
ElDropdown,
@ -149,6 +149,11 @@ export default mixins(showMessage, executionHelpers).extend({
VIEWS,
};
},
setup() {
return {
...useMessage(),
};
},
computed: {
...mapStores(useUIStore),
executionUIDetails(): IExecutionUIData | null {
@ -163,14 +168,18 @@ export default mixins(showMessage, executionHelpers).extend({
},
methods: {
async onDeleteExecution(): Promise<void> {
const deleteConfirmed = await this.confirmMessage(
const deleteConfirmed = await this.confirm(
this.$locale.baseText('executionDetails.confirmMessage.message'),
this.$locale.baseText('executionDetails.confirmMessage.headline'),
'warning',
this.$locale.baseText('executionDetails.confirmMessage.confirmButtonText'),
'',
{
type: 'warning',
confirmButtonText: this.$locale.baseText(
'executionDetails.confirmMessage.confirmButtonText',
),
cancelButtonText: '',
},
);
if (!deleteConfirmed) {
if (deleteConfirmed !== MODAL_CONFIRM) {
return;
}
this.$emit('deleteCurrentExecution');

View file

@ -27,7 +27,7 @@ import ExecutionsSidebar from '@/components/ExecutionsView/ExecutionsSidebar.vue
import {
MAIN_HEADER_TABS,
MODAL_CANCEL,
MODAL_CONFIRMED,
MODAL_CONFIRM,
PLACEHOLDER_EMPTY_WORKFLOW_ID,
VIEWS,
WEBHOOK_NODE_TYPE,
@ -49,7 +49,7 @@ import type {
} from 'n8n-workflow';
import { NodeHelpers } from 'n8n-workflow';
import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage';
import { useToast, useMessage } from '@/composables';
import { v4 as uuid } from 'uuid';
import type { Route } from 'vue-router';
import { executionHelpers } from '@/mixins/executionsHelpers';
@ -70,7 +70,7 @@ const MAX_LOADING_ATTEMPTS = 5;
// Number of executions fetched on each page
const LOAD_MORE_PAGE_SIZE = 100;
export default mixins(showMessage, executionHelpers, debounceHelper, workflowHelpers).extend({
export default mixins(executionHelpers, debounceHelper, workflowHelpers).extend({
name: 'executions-list',
components: {
ExecutionsSidebar,
@ -83,6 +83,12 @@ export default mixins(showMessage, executionHelpers, debounceHelper, workflowHel
temporaryExecution: null as IExecutionsSummary | null,
};
},
setup() {
return {
...useToast(),
...useMessage(),
};
},
computed: {
...mapStores(useTagsStore, useNodeTypesStore, useSettingsStore, useUIStore, useWorkflowsStore),
hidePreview(): boolean {
@ -132,16 +138,22 @@ export default mixins(showMessage, executionHelpers, debounceHelper, workflowHel
return;
}
if (this.uiStore.stateIsDirty) {
const confirmModal = await this.confirmModal(
const confirmModal = await this.confirm(
this.$locale.baseText('generic.unsavedWork.confirmMessage.message'),
this.$locale.baseText('generic.unsavedWork.confirmMessage.headline'),
'warning',
this.$locale.baseText('generic.unsavedWork.confirmMessage.confirmButtonText'),
this.$locale.baseText('generic.unsavedWork.confirmMessage.cancelButtonText'),
true,
{
title: this.$locale.baseText('generic.unsavedWork.confirmMessage.headline'),
type: 'warning',
confirmButtonText: this.$locale.baseText(
'generic.unsavedWork.confirmMessage.confirmButtonText',
),
cancelButtonText: this.$locale.baseText(
'generic.unsavedWork.confirmMessage.cancelButtonText',
),
showClose: true,
},
);
if (confirmModal === MODAL_CONFIRMED) {
if (confirmModal === MODAL_CONFIRM) {
const saved = await this.saveCurrentWorkflow({}, false);
if (saved) {
await this.settingsStore.fetchPromptsData();
@ -221,7 +233,7 @@ export default mixins(showMessage, executionHelpers, debounceHelper, workflowHel
data = await this.workflowsStore.getPastExecutions(this.requestFilter, limit, lastId);
} catch (error) {
this.loadingMore = false;
this.$showError(error, this.$locale.baseText('executionsList.showError.loadMore.title'));
this.showError(error, this.$locale.baseText('executionsList.showError.loadMore.title'));
return;
}
@ -276,7 +288,7 @@ export default mixins(showMessage, executionHelpers, debounceHelper, workflowHel
await this.setExecutions();
} catch (error) {
this.loading = false;
this.$showError(
this.showError(
error,
this.$locale.baseText('executionsList.showError.handleDeleteSelected.title'),
);
@ -284,7 +296,7 @@ export default mixins(showMessage, executionHelpers, debounceHelper, workflowHel
}
this.loading = false;
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('executionsList.showMessage.handleDeleteSelected.title'),
type: 'success',
});
@ -295,7 +307,7 @@ export default mixins(showMessage, executionHelpers, debounceHelper, workflowHel
try {
await this.workflowsStore.stopCurrentExecution(activeExecutionId);
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('executionsList.showMessage.stopExecution.title'),
message: this.$locale.baseText('executionsList.showMessage.stopExecution.message', {
interpolate: { activeExecutionId },
@ -305,7 +317,7 @@ export default mixins(showMessage, executionHelpers, debounceHelper, workflowHel
await this.loadAutoRefresh();
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('executionsList.showError.stopExecution.title'),
);
@ -399,7 +411,7 @@ export default mixins(showMessage, executionHelpers, debounceHelper, workflowHel
return await this.workflowsStore.loadCurrentWorkflowExecutions(this.requestFilter);
} catch (error) {
if (error.errorCode === NO_NETWORK_ERROR_CODE) {
this.$showMessage(
this.showMessage(
{
title: this.$locale.baseText('executionsList.showError.refreshData.title'),
message: error.message,
@ -409,7 +421,7 @@ export default mixins(showMessage, executionHelpers, debounceHelper, workflowHel
false,
);
} else {
this.$showError(
this.showError(
error,
this.$locale.baseText('executionsList.showError.refreshData.title'),
);
@ -449,7 +461,7 @@ export default mixins(showMessage, executionHelpers, debounceHelper, workflowHel
const existingExecution = await this.workflowsStore.fetchExecutionDataById(executionId);
if (!existingExecution) {
this.workflowsStore.activeWorkflowExecution = null;
this.$showError(
this.showError(
new Error(
this.$locale.baseText('executionView.notFound.message', {
interpolate: { executionId },
@ -493,7 +505,7 @@ export default mixins(showMessage, executionHelpers, debounceHelper, workflowHel
try {
data = await this.workflowsStore.fetchWorkflow(workflowId);
} catch (error) {
this.$showError(error, this.$locale.baseText('nodeView.showError.openWorkflow.title'));
this.showError(error, this.$locale.baseText('nodeView.showError.openWorkflow.title'));
return;
}
if (data === undefined) {
@ -642,7 +654,7 @@ export default mixins(showMessage, executionHelpers, debounceHelper, workflowHel
async onRetryExecution(payload: { execution: IExecutionsSummary; command: string }) {
const loadWorkflow = payload.command === 'current-workflow';
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('executionDetails.runningMessage'),
type: 'info',
duration: 2000,
@ -664,18 +676,18 @@ export default mixins(showMessage, executionHelpers, debounceHelper, workflowHel
);
if (retrySuccessful === true) {
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('executionsList.showMessage.retrySuccessfulTrue.title'),
type: 'success',
});
} else {
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('executionsList.showMessage.retrySuccessfulFalse.title'),
type: 'error',
});
}
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('executionsList.showError.retryExecution.title'),
);

View file

@ -40,25 +40,30 @@
</template>
<script lang="ts">
import Modal from './Modal.vue';
import Modal from '@/components/Modal.vue';
import {
IMPORT_CURL_MODAL_KEY,
CURL_IMPORT_NOT_SUPPORTED_PROTOCOLS,
CURL_IMPORT_NODES_PROTOCOLS,
} from '../constants';
import { showMessage } from '@/mixins/showMessage';
import mixins from 'vue-typed-mixins';
} from '@/constants';
import { useToast } from '@/composables';
import { defineComponent } from 'vue';
import type { INodeUi } from '@/Interface';
import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui.store';
import { useNDVStore } from '@/stores/ndv.store';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'ImportCurlModal',
components: {
Modal,
},
setup() {
return {
...useToast(),
};
},
data() {
return {
IMPORT_CURL_MODAL_KEY,
@ -122,7 +127,7 @@ export default mixins(showMessage).extend({
}
},
showProtocolErrorWithSupportedNode(protocol: string, node: string): void {
this.$showToast({
this.showToast({
title: this.$locale.baseText('importParameter.showError.invalidProtocol1.title', {
interpolate: {
node,
@ -138,7 +143,7 @@ export default mixins(showMessage).extend({
});
},
showProtocolError(protocol: string): void {
this.$showToast({
this.showToast({
title: this.$locale.baseText('importParameter.showError.invalidProtocol2.title'),
message: this.$locale.baseText('importParameter.showError.invalidProtocol.message', {
interpolate: {
@ -150,7 +155,7 @@ export default mixins(showMessage).extend({
});
},
showInvalidcURLCommandError(): void {
this.$showToast({
this.showToast({
title: this.$locale.baseText('importParameter.showError.invalidCurlCommand.title'),
message: this.$locale.baseText('importParameter.showError.invalidCurlCommand.message'),
type: 'error',

View file

@ -11,13 +11,12 @@
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { IMPORT_CURL_MODAL_KEY } from '@/constants';
import { useUIStore } from '@/stores/ui.store';
import { mapStores } from 'pinia';
import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'import-parameter',
props: {
isReadOnly: {

View file

@ -32,10 +32,10 @@
</template>
<script lang="ts">
import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage';
import { defineComponent } from 'vue';
import { useToast } from '@/composables';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'InlineNameEdit',
props: {
name: {
@ -52,6 +52,11 @@ export default mixins(showMessage).extend({
default: false,
},
},
setup() {
return {
...useToast(),
};
},
data() {
return {
isNameEdit: false,
@ -75,7 +80,7 @@ export default mixins(showMessage).extend({
if (!this.name) {
this.$emit('input', `Untitled ${this.type}`);
this.$showToast({
this.showToast({
title: 'Error',
message: `${this.type} name cannot be empty`,
type: 'warning',

View file

@ -66,7 +66,7 @@
<script lang="ts">
import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
import { copyPaste } from '@/mixins/copyPaste';
import Modal from './Modal.vue';
import type { IFormInputs, IInviteResponse, IUser } from '@/Interface';
@ -90,7 +90,7 @@ function getEmail(email: string): string {
return parsed;
}
export default mixins(showMessage, copyPaste).extend({
export default mixins(copyPaste).extend({
components: { Modal },
name: 'InviteUsersModal',
props: {
@ -98,6 +98,11 @@ export default mixins(showMessage, copyPaste).extend({
type: String,
},
},
setup() {
return {
...useToast(),
};
},
data() {
return {
config: null as IFormInputs | null,
@ -224,7 +229,7 @@ export default mixins(showMessage, copyPaste).extend({
);
if (successfulEmailInvites.length) {
this.$showMessage({
this.showMessage({
type: 'success',
title: this.$locale.baseText(
successfulEmailInvites.length > 1
@ -244,7 +249,7 @@ export default mixins(showMessage, copyPaste).extend({
this.copyToClipboard(successfulUrlInvites[0].user.inviteAcceptUrl);
}
this.$showMessage({
this.showMessage({
type: 'success',
title: this.$locale.baseText(
successfulUrlInvites.length > 1
@ -266,7 +271,7 @@ export default mixins(showMessage, copyPaste).extend({
if (erroredInvites.length) {
setTimeout(() => {
this.$showMessage({
this.showMessage({
type: 'error',
title: this.$locale.baseText('settings.users.usersEmailedError'),
message: this.$locale.baseText('settings.users.emailInvitesSentError', {
@ -282,12 +287,12 @@ export default mixins(showMessage, copyPaste).extend({
this.modalBus.emit('close');
}
} catch (error) {
this.$showError(error, this.$locale.baseText('settings.users.usersInvitedError'));
this.showError(error, this.$locale.baseText('settings.users.usersInvitedError'));
}
this.loading = false;
},
showCopyInviteLinkToast(successfulUrlInvites: IInviteResponse[]) {
this.$showMessage({
this.showMessage({
type: 'success',
title: this.$locale.baseText(
successfulUrlInvites.length > 1

View file

@ -128,6 +128,7 @@ import {
DUPLICATE_MODAL_KEY,
EnterpriseEditionFeature,
MAX_WORKFLOW_NAME_LENGTH,
MODAL_CONFIRM,
PLACEHOLDER_EMPTY_WORKFLOW_ID,
VIEWS,
WORKFLOW_MENU_ACTIONS,
@ -147,7 +148,7 @@ import BreakpointsObserver from '@/components/BreakpointsObserver.vue';
import type { IUser, IWorkflowDataUpdate, IWorkflowDb, IWorkflowToShare } from '@/Interface';
import { saveAs } from 'file-saver';
import { useTitleChange } from '@/composables/useTitleChange';
import { useTitleChange, useToast, useMessage } from '@/composables';
import type { MessageBoxInputData } from 'element-ui/types/message-box';
import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui.store';
@ -185,6 +186,8 @@ export default mixins(workflowHelpers).extend({
setup() {
return {
...useTitleChange(),
...useToast(),
...useMessage(),
};
},
data() {
@ -381,7 +384,7 @@ export default mixins(workflowHelpers).extend({
async onNameSubmit(name: string, cb: (saved: boolean) => void) {
const newName = name.trim();
if (!newName) {
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('workflowDetails.showMessage.title'),
message: this.$locale.baseText('workflowDetails.showMessage.message'),
type: 'error',
@ -413,7 +416,7 @@ export default mixins(workflowHelpers).extend({
try {
workflowData = JSON.parse(data as string);
} catch (error) {
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('mainSidebar.showMessage.handleFileImport.title'),
message: this.$locale.baseText('mainSidebar.showMessage.handleFileImport.message'),
type: 'error',
@ -470,7 +473,7 @@ export default mixins(workflowHelpers).extend({
}
case WORKFLOW_MENU_ACTIONS.IMPORT_FROM_URL: {
try {
const promptResponse = (await this.$prompt(
const promptResponse = (await this.prompt(
this.$locale.baseText('mainSidebar.prompt.workflowUrl') + ':',
this.$locale.baseText('mainSidebar.prompt.importWorkflowFromUrl') + ':',
{
@ -494,30 +497,36 @@ export default mixins(workflowHelpers).extend({
break;
}
case WORKFLOW_MENU_ACTIONS.DELETE: {
const deleteConfirmed = await this.confirmMessage(
const deleteConfirmed = await this.confirm(
this.$locale.baseText('mainSidebar.confirmMessage.workflowDelete.message', {
interpolate: { workflowName: this.workflowName },
}),
this.$locale.baseText('mainSidebar.confirmMessage.workflowDelete.headline'),
'warning',
this.$locale.baseText('mainSidebar.confirmMessage.workflowDelete.confirmButtonText'),
this.$locale.baseText('mainSidebar.confirmMessage.workflowDelete.cancelButtonText'),
{
type: 'warning',
confirmButtonText: this.$locale.baseText(
'mainSidebar.confirmMessage.workflowDelete.confirmButtonText',
),
cancelButtonText: this.$locale.baseText(
'mainSidebar.confirmMessage.workflowDelete.cancelButtonText',
),
},
);
if (deleteConfirmed === false) {
if (deleteConfirmed !== MODAL_CONFIRM) {
return;
}
try {
await this.workflowsStore.deleteWorkflow(this.currentWorkflowId);
} catch (error) {
this.$showError(error, this.$locale.baseText('generic.deleteWorkflowError'));
this.showError(error, this.$locale.baseText('generic.deleteWorkflowError'));
return;
}
this.uiStore.stateIsDirty = false;
// Reset tab title since workflow is deleted.
this.titleReset();
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('mainSidebar.showMessage.handleSelect1.title'),
type: 'success',
});

View file

@ -110,13 +110,13 @@
</template>
<script lang="ts">
import type { IExecutionResponse, IMenuItem, IVersion } from '../Interface';
import type { IExecutionResponse, IMenuItem, IVersion } from '@/Interface';
import type { MessageBoxInputData } from 'element-ui/types/message-box';
import GiftNotificationIcon from './GiftNotificationIcon.vue';
import WorkflowSettings from '@/components/WorkflowSettings.vue';
import { genericHelpers } from '@/mixins/genericHelpers';
import { showMessage } from '@/mixins/showMessage';
import { useMessage } from '@/composables';
import { workflowHelpers } from '@/mixins/workflowHelpers';
import { workflowRun } from '@/mixins/workflowRun';
@ -137,7 +137,6 @@ import { useVersionControlStore } from '@/stores/versionControl.store';
export default mixins(
genericHelpers,
showMessage,
workflowHelpers,
workflowRun,
userHelpers,
@ -148,6 +147,11 @@ export default mixins(
GiftNotificationIcon,
WorkflowSettings,
},
setup() {
return {
...useMessage(),
};
},
data() {
return {
// @ts-ignore
@ -483,7 +487,7 @@ export default mixins(
}
},
async sync() {
const prompt = await this.$prompt(
const prompt = (await this.prompt(
this.$locale.baseText('settings.versionControl.sync.prompt.description', {
interpolate: { branch: this.versionControlStore.state.currentBranch },
}),
@ -499,7 +503,7 @@ export default mixins(
inputPattern: /^.+$/,
inputErrorMessage: this.$locale.baseText('settings.versionControl.sync.prompt.error'),
},
);
)) as MessageBoxInputData;
if (prompt.value) {
await this.versionControlStore.sync({ commitMessage: prompt.value });

View file

@ -115,7 +115,7 @@ import type {
import { genericHelpers } from '@/mixins/genericHelpers';
import { nodeHelpers } from '@/mixins/nodeHelpers';
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
import TitledList from '@/components/TitledList.vue';
@ -141,7 +141,7 @@ interface CredentialDropdownOption extends ICredentialsResponse {
typeDisplayName: string;
}
export default mixins(genericHelpers, nodeHelpers, showMessage).extend({
export default mixins(genericHelpers, nodeHelpers).extend({
name: 'NodeCredentials',
props: {
readonly: {
@ -167,6 +167,11 @@ export default mixins(genericHelpers, nodeHelpers, showMessage).extend({
components: {
TitledList,
},
setup() {
return {
...useToast(),
};
},
data() {
return {
NEW_CREDENTIALS_TEXT: `- ${this.$locale.baseText('nodeCredentials.createNew')} -`,
@ -452,7 +457,7 @@ export default mixins(genericHelpers, nodeHelpers, showMessage).extend({
type: selectedCredentialsType,
});
this.updateNodesCredentialsIssues();
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('nodeCredentials.showMessage.title'),
message: this.$locale.baseText('nodeCredentials.showMessage.message', {
interpolate: {

View file

@ -150,6 +150,7 @@ import {
BASE_NODE_SURVEY_URL,
EnterpriseEditionFeature,
EXECUTABLE_TRIGGER_NODE_TYPES,
MODAL_CONFIRM,
START_NODE_TYPE,
STICKY_NODE_TYPE,
} from '@/constants';
@ -163,6 +164,7 @@ import { useNodeTypesStore } from '@/stores/nodeTypes.store';
import { useUIStore } from '@/stores/ui.store';
import { useSettingsStore } from '@/stores/settings.store';
import useDeviceSupport from '@/composables/useDeviceSupport';
import { useMessage } from '@/composables';
export default mixins(
externalHooks,
@ -194,6 +196,7 @@ export default mixins(
setup() {
return {
...useDeviceSupport(),
...useMessage(),
};
},
data() {
@ -608,15 +611,16 @@ export default mixins(
}
if (this.outputPanelEditMode.enabled) {
const shouldPinDataBeforeClosing = await this.confirmMessage(
const shouldPinDataBeforeClosing = await this.confirm(
'',
this.$locale.baseText('ndv.pinData.beforeClosing.title'),
null,
this.$locale.baseText('ndv.pinData.beforeClosing.confirm'),
this.$locale.baseText('ndv.pinData.beforeClosing.cancel'),
{
confirmButtonText: this.$locale.baseText('ndv.pinData.beforeClosing.confirm'),
cancelButtonText: this.$locale.baseText('ndv.pinData.beforeClosing.cancel'),
},
);
if (shouldPinDataBeforeClosing) {
if (shouldPinDataBeforeClosing === MODAL_CONFIRM) {
const { value } = this.outputPanelEditMode;
if (!this.isValidPinDataSize(value)) {

View file

@ -18,7 +18,7 @@
</template>
<script lang="ts">
import { WEBHOOK_NODE_TYPE, MANUAL_TRIGGER_NODE_TYPE } from '@/constants';
import { WEBHOOK_NODE_TYPE, MANUAL_TRIGGER_NODE_TYPE, MODAL_CONFIRM } from '@/constants';
import type { INodeUi } from '@/Interface';
import type { INodeTypeDescription } from 'n8n-workflow';
import mixins from 'vue-typed-mixins';
@ -29,6 +29,7 @@ import { mapStores } from 'pinia';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { useNDVStore } from '@/stores/ndv.store';
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
import { useToast, useMessage } from '@/composables';
export default mixins(workflowRun, pinData).extend({
props: {
@ -56,6 +57,12 @@ export default mixins(workflowRun, pinData).extend({
type: String,
},
},
setup() {
return {
...useToast(),
...useMessage(),
};
},
computed: {
...mapStores(useNodeTypesStore, useNDVStore, useWorkflowsStore),
node(): INodeUi | null {
@ -173,7 +180,7 @@ export default mixins(workflowRun, pinData).extend({
try {
await this.workflowsStore.removeTestWebhook(this.workflowsStore.workflowId);
} catch (error) {
this.$showError(error, this.$locale.baseText('ndv.execute.stopWaitingForWebhook.error'));
this.showError(error, this.$locale.baseText('ndv.execute.stopWaitingForWebhook.error'));
return;
}
},
@ -186,13 +193,15 @@ export default mixins(workflowRun, pinData).extend({
} else {
let shouldUnpinAndExecute = false;
if (this.hasPinData) {
shouldUnpinAndExecute = await this.confirmMessage(
const confirmResult = await this.confirm(
this.$locale.baseText('ndv.pinData.unpinAndExecute.description'),
this.$locale.baseText('ndv.pinData.unpinAndExecute.title'),
null,
this.$locale.baseText('ndv.pinData.unpinAndExecute.confirm'),
this.$locale.baseText('ndv.pinData.unpinAndExecute.cancel'),
{
confirmButtonText: this.$locale.baseText('ndv.pinData.unpinAndExecute.confirm'),
cancelButtonText: this.$locale.baseText('ndv.pinData.unpinAndExecute.cancel'),
},
);
shouldUnpinAndExecute = confirmResult === MODAL_CONFIRM;
if (shouldUnpinAndExecute) {
dataPinningEventBus.emit('data-unpinning', { source: 'unpin-and-execute-modal' });

View file

@ -62,17 +62,22 @@ import type { INodeTypeDescription, IWebhookDescription } from 'n8n-workflow';
import { WEBHOOK_NODE_TYPE } from '@/constants';
import { copyPaste } from '@/mixins/copyPaste';
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
import { workflowHelpers } from '@/mixins/workflowHelpers';
import mixins from 'vue-typed-mixins';
export default mixins(copyPaste, showMessage, workflowHelpers).extend({
export default mixins(copyPaste, workflowHelpers).extend({
name: 'NodeWebhooks',
props: [
'node', // NodeUi
'nodeType', // INodeTypeDescription
],
setup() {
return {
...useToast(),
};
},
data() {
return {
isMinimized: this.nodeType && this.nodeType.name !== WEBHOOK_NODE_TYPE,
@ -95,7 +100,7 @@ export default mixins(copyPaste, showMessage, workflowHelpers).extend({
const webhookUrl = this.getWebhookUrlDisplay(webhookData);
this.copyToClipboard(webhookUrl);
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('nodeWebhooks.showMessage.title'),
type: 'success',
});

View file

@ -51,18 +51,23 @@
import { ONBOARDING_CALL_SIGNUP_MODAL_KEY, VALID_EMAIL_REGEX } from '@/constants';
import Modal from './Modal.vue';
import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage';
import { defineComponent } from 'vue';
import { useToast } from '@/composables';
import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui.store';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage).extend({
export default defineComponent({
components: {
Modal,
},
name: 'OnboardingCallSignupModal',
props: ['modalName'],
setup() {
return {
...useToast(),
};
},
data() {
return {
email: '',
@ -91,7 +96,7 @@ export default mixins(showMessage).extend({
try {
await this.uiStore.applyForOnboardingCall(this.email);
this.$showMessage({
this.showMessage({
type: 'success',
title: this.$locale.baseText('onboardingCallSignupSucess.title'),
message: this.$locale.baseText('onboardingCallSignupSucess.message'),
@ -99,7 +104,7 @@ export default mixins(showMessage).extend({
this.okToClose = true;
this.modalBus.emit('close');
} catch (e) {
this.$showError(
this.showError(
e,
this.$locale.baseText('onboardingCallSignupFailed.title'),
this.$locale.baseText('onboardingCallSignupFailed.message'),

View file

@ -3,13 +3,12 @@
</template>
<script lang="ts">
import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage';
import type { ElMessageComponent } from 'element-ui/types/message';
import { defineComponent } from 'vue';
import type { ElNotificationComponent } from 'element-ui/types/notification';
import { sanitizeHtml } from '@/utils';
import { useToast } from '@/composables';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'PageAlert',
props: {
message: {
@ -20,19 +19,24 @@ export default mixins(showMessage).extend({
type: String,
},
},
setup() {
return {
...useToast(),
};
},
data() {
return {
alert: null as null | ElMessageComponent,
alert: null as null | ElNotificationComponent,
};
},
mounted() {
this.alert = this.$showAlert({
this.alert = this.showAlert({
title: '',
message: sanitizeHtml(this.message),
type: 'warning',
duration: 0,
showClose: true,
dangerouslyUseHTMLString: true,
// @ts-ignore
customClass: this.popupClass || '',
});
},

View file

@ -379,7 +379,6 @@ import HtmlEditor from '@/components/HtmlEditor/HtmlEditor.vue';
import SqlEditor from '@/components/SqlEditor/SqlEditor.vue';
import { externalHooks } from '@/mixins/externalHooks';
import { nodeHelpers } from '@/mixins/nodeHelpers';
import { showMessage } from '@/mixins/showMessage';
import { workflowHelpers } from '@/mixins/workflowHelpers';
import { hasExpressionMapping, isValueExpression, isResourceLocatorValue } from '@/utils';
@ -397,13 +396,7 @@ import Vue from 'vue';
type ResourceLocatorRef = InstanceType<typeof ResourceLocator>;
export default mixins(
externalHooks,
nodeHelpers,
showMessage,
workflowHelpers,
debounceHelper,
).extend({
export default mixins(externalHooks, nodeHelpers, workflowHelpers, debounceHelper).extend({
name: 'parameter-input',
components: {
CodeNodeEditor,

View file

@ -76,7 +76,7 @@ import type { IN8nButton, INodeUi, IRunDataDisplayMode, IUpdateInformation } fro
import ParameterOptions from '@/components/ParameterOptions.vue';
import DraggableTarget from '@/components/DraggableTarget.vue';
import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
import {
hasExpressionMapping,
isResourceLocatorValue,
@ -95,19 +95,24 @@ import { mapStores } from 'pinia';
import { useNDVStore } from '@/stores/ndv.store';
import { useSegment } from '@/stores/segment.store';
import { externalHooks } from '@/mixins/externalHooks';
import { getMappedResult } from '../utils/mappingUtils';
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({
export default mixins(externalHooks).extend({
name: 'parameter-input-full',
components: {
ParameterOptions,
DraggableTarget,
ParameterInputWrapper,
},
setup() {
return {
...useToast(),
};
},
data() {
return {
focused: false,
@ -292,7 +297,7 @@ export default mixins(showMessage, externalHooks).extend({
this.$emit('valueChanged', parameterData);
if (!this.ndvStore.isMappingOnboarded) {
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('dataMapping.success.title'),
message: this.$locale.baseText('dataMapping.success.moreInfo'),
type: 'success',

View file

@ -45,9 +45,8 @@
import type { PropType } from 'vue';
import ParameterInput from '@/components/ParameterInput.vue';
import InputHint from './ParameterInputHint.vue';
import InputHint from '@/components/ParameterInputHint.vue';
import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage';
import type {
INodeProperties,
INodePropertyMode,
@ -63,7 +62,7 @@ import { useNDVStore } from '@/stores/ndv.store';
type ParamRef = InstanceType<typeof ParameterInput>;
export default mixins(showMessage, workflowHelpers).extend({
export default mixins(workflowHelpers).extend({
name: 'parameter-input-wrapper',
components: {
ParameterInput,

View file

@ -125,8 +125,8 @@ import {
VIEWS,
} from '@/constants';
import { workflowHelpers } from '@/mixins/workflowHelpers';
import { showMessage } from '@/mixins/showMessage';
import Modal from './Modal.vue';
import { useToast } from '@/composables';
import Modal from '@/components/Modal.vue';
import type { IFormInputs, IPersonalizationLatestVersion, IUser } from '@/Interface';
import { getAccountAge } from '@/utils';
import type { GenericValue } from 'n8n-workflow';
@ -137,7 +137,7 @@ import { useRootStore } from '@/stores/n8nRoot.store';
import { useUsersStore } from '@/stores/users.store';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage, workflowHelpers).extend({
export default mixins(workflowHelpers).extend({
components: { Modal },
name: 'PersonalizationModal',
data() {
@ -151,6 +151,11 @@ export default mixins(showMessage, workflowHelpers).extend({
formBus: createEventBus(),
};
},
setup() {
return {
...useToast(),
};
},
computed: {
...mapStores(useRootStore, useSettingsStore, useUIStore, useUsersStore),
survey() {
@ -637,7 +642,7 @@ export default mixins(showMessage, workflowHelpers).extend({
await this.fetchOnboardingPrompt();
} catch (e) {
this.$showError(e, 'Error while submitting results');
this.showError(e, 'Error while submitting results');
}
this.$data.isSaving = false;
@ -654,7 +659,7 @@ export default mixins(showMessage, workflowHelpers).extend({
if (onboardingResponse.title && onboardingResponse.description) {
setTimeout(async () => {
this.$showToast({
this.showToast({
type: 'info',
title: onboardingResponse.title,
message: onboardingResponse.description,

View file

@ -508,12 +508,12 @@ import { nodeHelpers } from '@/mixins/nodeHelpers';
import { pinData } from '@/mixins/pinData';
import CodeNodeEditor from '@/components/CodeNodeEditor/CodeNodeEditor.vue';
import { dataPinningEventBus } from '@/event-bus';
import { clearJsonKey, executionDataToJson, stringSizeInBytes } from '@/utils';
import { isEmpty } from '@/utils';
import { clearJsonKey, executionDataToJson, stringSizeInBytes, isEmpty } from '@/utils';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { mapStores } from 'pinia';
import { useNDVStore } from '@/stores/ndv.store';
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
import { useToast } from '@/composables';
const RunDataTable = async () => import('@/components/RunDataTable.vue');
const RunDataJson = async () => import('@/components/RunDataJson.vue');
@ -585,6 +585,11 @@ export default mixins(externalHooks, genericHelpers, nodeHelpers, pinData).exten
default: false,
},
},
setup() {
return {
...useToast(),
};
},
data() {
return {
binaryDataPreviewActive: false,
@ -1072,7 +1077,7 @@ export default mixins(externalHooks, genericHelpers, nodeHelpers, pinData).exten
this.workflowsStore.pinData({ node: this.node, data: this.inputData });
if (this.maxRunIndex > 0) {
this.$showToast({
this.showToast({
title: this.$locale.baseText('ndv.pinData.pin.multipleRuns.title', {
interpolate: {
index: `${this.runIndex}`,

View file

@ -48,6 +48,7 @@ import { clearJsonKey, convertPath, executionDataToJson } from '@/utils';
import { mapStores } from 'pinia';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { useNDVStore } from '@/stores/ndv.store';
import { useToast } from '@/composables';
type JsonPathData = {
path: string;
@ -90,6 +91,11 @@ export default mixins(genericHelpers, nodeHelpers, pinData, copyPaste).extend({
required: true,
},
},
setup() {
return {
...useToast(),
};
},
computed: {
...mapStores(useNDVStore, useWorkflowsStore),
activeNode(): INodeUi | null {
@ -152,7 +158,7 @@ export default mixins(genericHelpers, nodeHelpers, pinData, copyPaste).extend({
if (commandData.command === 'value') {
value = this.getJsonValue();
this.$showToast({
this.showToast({
title: this.$locale.baseText('runData.copyValue.toast'),
message: '',
type: 'success',
@ -166,7 +172,7 @@ export default mixins(genericHelpers, nodeHelpers, pinData, copyPaste).extend({
startPath = jsonItemPath.startPath;
path = jsonItemPath.path;
this.$showToast({
this.showToast({
title: this.$locale.baseText('runData.copyItemPath.toast'),
message: '',
type: 'success',
@ -177,7 +183,7 @@ export default mixins(genericHelpers, nodeHelpers, pinData, copyPaste).extend({
startPath = jsonParameterPath.startPath;
path = jsonParameterPath.path;
this.$showToast({
this.showToast({
title: this.$locale.baseText('runData.copyParameterPath.toast'),
message: '',
type: 'success',

View file

@ -47,9 +47,9 @@
</template>
<script lang="ts">
import mixins from 'vue-typed-mixins';
import { EnterpriseEditionFeature } from '@/constants';
import { showMessage } from '@/mixins/showMessage';
import { defineComponent } from 'vue';
import { EnterpriseEditionFeature, MODAL_CONFIRM } from '@/constants';
import { useMessage } from '@/composables';
import { useLogStreamingStore } from '@/stores/logStreaming.store';
import type { PropType } from 'vue';
import { mapStores } from 'pinia';
@ -63,13 +63,18 @@ export const DESTINATION_LIST_ITEM_ACTIONS = {
DELETE: 'delete',
};
export default mixins(showMessage).extend({
export default defineComponent({
data() {
return {
EnterpriseEditionFeature,
nodeParameters: {} as MessageEventBusDestinationOptions,
};
},
setup() {
return {
...useMessage(),
};
},
components: {},
props: {
eventBus: {
@ -148,17 +153,23 @@ export default mixins(showMessage).extend({
if (action === DESTINATION_LIST_ITEM_ACTIONS.OPEN) {
this.$emit('edit', this.destination.id);
} else if (action === DESTINATION_LIST_ITEM_ACTIONS.DELETE) {
const deleteConfirmed = await this.confirmMessage(
const deleteConfirmed = await this.confirm(
this.$locale.baseText('settings.log-streaming.destinationDelete.message', {
interpolate: { destinationName: this.destination.label },
}),
this.$locale.baseText('settings.log-streaming.destinationDelete.headline'),
'warning',
this.$locale.baseText('settings.log-streaming.destinationDelete.confirmButtonText'),
this.$locale.baseText('settings.log-streaming.destinationDelete.cancelButtonText'),
{
type: 'warning',
confirmButtonText: this.$locale.baseText(
'settings.log-streaming.destinationDelete.confirmButtonText',
),
cancelButtonText: this.$locale.baseText(
'settings.log-streaming.destinationDelete.cancelButtonText',
),
},
);
if (deleteConfirmed === false) {
if (deleteConfirmed !== MODAL_CONFIRM) {
return;
}

View file

@ -174,13 +174,11 @@
<script lang="ts">
import { get, set, unset } from 'lodash-es';
import { mapStores } from 'pinia';
import mixins from 'vue-typed-mixins';
import { useLogStreamingStore } from '@/stores/logStreaming.store';
import { useNDVStore } from '@/stores/ndv.store';
import { useWorkflowsStore } from '@/stores/workflows.store';
import ParameterInputList from '@/components/ParameterInputList.vue';
import NodeCredentials from '@/components/NodeCredentials.vue';
import type { IMenuItem, INodeUi, ITab, IUpdateInformation } from '@/Interface';
import type { IMenuItem, INodeUi, IUpdateInformation } from '@/Interface';
import type {
IDataObject,
INodeCredentials,
@ -196,27 +194,26 @@ import {
defaultMessageEventBusDestinationSentryOptions,
} from 'n8n-workflow';
import type { PropType } from 'vue';
import Vue from 'vue';
import { LOG_STREAM_MODAL_KEY } from '@/constants';
import Vue, { defineComponent } from 'vue';
import { LOG_STREAM_MODAL_KEY, MODAL_CONFIRM } from '@/constants';
import Modal from '@/components/Modal.vue';
import { showMessage } from '@/mixins/showMessage';
import { useMessage } from '@/composables';
import { useUIStore } from '@/stores/ui.store';
import { useUsersStore } from '@/stores/users.store';
import { destinationToFakeINodeUi } from './Helpers.ee';
import { destinationToFakeINodeUi } from '@/components/SettingsLogStreaming/Helpers.ee';
import {
webhookModalDescription,
sentryModalDescription,
syslogModalDescription,
} from './descriptions.ee';
import type { BaseTextKey } from '@/plugins/i18n';
import InlineNameEdit from '../InlineNameEdit.vue';
import SaveButton from '../SaveButton.vue';
import InlineNameEdit from '@/components/InlineNameEdit.vue';
import SaveButton from '@/components/SaveButton.vue';
import EventSelection from '@/components/SettingsLogStreaming/EventSelection.ee.vue';
import { Checkbox } from 'element-ui';
import type { EventBus } from '@/event-bus';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'event-destination-settings-modal',
props: {
modalName: String,
@ -232,11 +229,14 @@ export default mixins(showMessage).extend({
components: {
Modal,
ParameterInputList,
NodeCredentials,
InlineNameEdit,
SaveButton,
EventSelection,
Checkbox,
},
setup() {
return {
...useMessage(),
};
},
data() {
return {
@ -311,18 +311,6 @@ export default mixins(showMessage).extend({
}
return items;
},
tabItems(): ITab[] {
return [
{
label: this.$locale.baseText('settings.log-streaming.tab.settings'),
value: 'settings',
},
{
label: this.$locale.baseText('settings.log-streaming.tab.events'),
value: 'events',
},
];
},
},
mounted() {
this.isInstanceOwner = this.usersStore.currentUser?.globalRole?.name === 'owner';
@ -442,17 +430,23 @@ export default mixins(showMessage).extend({
this.testMessageSent = true;
},
async removeThis() {
const deleteConfirmed = await this.confirmMessage(
const deleteConfirmed = await this.confirm(
this.$locale.baseText('settings.log-streaming.destinationDelete.message', {
interpolate: { destinationName: this.destination.label },
}),
this.$locale.baseText('settings.log-streaming.destinationDelete.headline'),
'warning',
this.$locale.baseText('settings.log-streaming.destinationDelete.confirmButtonText'),
this.$locale.baseText('settings.log-streaming.destinationDelete.cancelButtonText'),
{
type: 'warning',
confirmButtonText: this.$locale.baseText(
'settings.log-streaming.destinationDelete.confirmButtonText',
),
cancelButtonText: this.$locale.baseText(
'settings.log-streaming.destinationDelete.cancelButtonText',
),
},
);
if (deleteConfirmed === false) {
if (deleteConfirmed !== MODAL_CONFIRM) {
return;
} else {
this.eventBus.emit('remove', this.destination.id);

View file

@ -55,12 +55,12 @@
</template>
<script lang="ts">
import mixins from 'vue-typed-mixins';
import { defineComponent } from 'vue';
import type { ITag } from '@/Interface';
import { MAX_TAG_NAME_LENGTH, TAGS_MANAGER_MODAL_KEY } from '@/constants';
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui.store';
import { useTagsStore } from '@/stores/tags.store';
@ -75,7 +75,7 @@ type CreateRef = InstanceType<typeof N8nOption>;
const MANAGE_KEY = '__manage';
const CREATE_KEY = '__create';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'TagsDropdown',
props: {
placeholder: {},
@ -88,6 +88,11 @@ export default mixins(showMessage).extend({
type: Object as PropType<EventBus>,
},
},
setup() {
return {
...useToast(),
};
},
data() {
return {
filter: '',
@ -163,7 +168,7 @@ export default mixins(showMessage).extend({
this.$data.filter = '';
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('tagsDropdown.showError.title'),
this.$locale.baseText('tagsDropdown.showError.message', { interpolate: { name } }),

View file

@ -28,11 +28,11 @@
</template>
<script lang="ts">
import mixins from 'vue-typed-mixins';
import { defineComponent } from 'vue';
import type { ITag } from '@/Interface';
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
import TagsView from '@/components/TagsManager/TagsView/TagsView.vue';
import NoTagsView from '@/components/TagsManager/NoTagsView.vue';
import Modal from '@/components/Modal.vue';
@ -41,8 +41,13 @@ import { mapStores } from 'pinia';
import { useTagsStore } from '@/stores/tags.store';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'TagsManager',
setup() {
return {
...useToast(),
};
},
created() {
void this.tagsStore.fetchAll({ force: true, withUsageCount: true });
},
@ -94,7 +99,7 @@ export default mixins(showMessage).extend({
cb(newTag);
} catch (error) {
const escapedName = escape(name);
this.$showError(
this.showError(
error,
this.$locale.baseText('tagsManager.showError.onCreate.title'),
this.$locale.baseText('tagsManager.showError.onCreate.message', {
@ -122,13 +127,13 @@ export default mixins(showMessage).extend({
const updatedTag = await this.tagsStore.rename({ id, name });
cb(!!updatedTag);
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('tagsManager.showMessage.onUpdate.title'),
type: 'success',
});
} catch (error) {
const escapedName = escape(oldName);
this.$showError(
this.showError(
error,
this.$locale.baseText('tagsManager.showError.onUpdate.title'),
this.$locale.baseText('tagsManager.showError.onUpdate.message', {
@ -153,13 +158,13 @@ export default mixins(showMessage).extend({
cb(deleted);
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('tagsManager.showMessage.onDelete.title'),
type: 'success',
});
} catch (error) {
const escapedName = escape(name);
this.$showError(
this.showError(
error,
this.$locale.baseText('tagsManager.showError.onDelete.title'),
this.$locale.baseText('tagsManager.showError.onDelete.message', {

View file

@ -106,13 +106,12 @@ import { EXECUTIONS_MODAL_KEY, WEBHOOK_NODE_TYPE, WORKFLOW_SETTINGS_MODAL_KEY }
import type { INodeUi } from '@/Interface';
import type { INodeTypeDescription } from 'n8n-workflow';
import { getTriggerNodeServiceName } from '@/utils';
import NodeExecuteButton from './NodeExecuteButton.vue';
import NodeExecuteButton from '@/components/NodeExecuteButton.vue';
import { workflowHelpers } from '@/mixins/workflowHelpers';
import mixins from 'vue-typed-mixins';
import CopyInput from './CopyInput.vue';
import NodeIcon from './NodeIcon.vue';
import CopyInput from '@/components/CopyInput.vue';
import NodeIcon from '@/components/NodeIcon.vue';
import { copyPaste } from '@/mixins/copyPaste';
import { showMessage } from '@/mixins/showMessage';
import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui.store';
import { useWorkflowsStore } from '@/stores/workflows.store';
@ -122,7 +121,7 @@ import type { N8nInfoAccordion } from 'n8n-design-system';
type HelpRef = InstanceType<typeof N8nInfoAccordion>;
export default mixins(workflowHelpers, copyPaste, showMessage).extend({
export default mixins(workflowHelpers, copyPaste).extend({
name: 'TriggerPanel',
components: {
NodeExecuteButton,
@ -190,18 +189,6 @@ export default mixins(workflowHelpers, copyPaste, showMessage).extend({
return this.getWebhookUrl(this.nodeType.webhooks[0], this.node, 'test');
},
webhookProdUrl(): string | undefined {
if (
!this.node ||
!this.nodeType ||
!this.nodeType.webhooks ||
!this.nodeType.webhooks.length
) {
return undefined;
}
return this.getWebhookUrl(this.nodeType.webhooks[0], this.node, 'prod');
},
isWebhookBasedNode(): boolean {
return Boolean(this.nodeType && this.nodeType.webhooks && this.nodeType.webhooks.length);
},

View file

@ -59,7 +59,7 @@
import { VALID_EMAIL_REGEX, VALUE_SURVEY_MODAL_KEY } from '@/constants';
import type { IN8nPromptResponse } from '@/Interface';
import ModalDrawer from './ModalDrawer.vue';
import ModalDrawer from '@/components/ModalDrawer.vue';
import mixins from 'vue-typed-mixins';
import { workflowHelpers } from '@/mixins/workflowHelpers';
@ -67,6 +67,7 @@ import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/settings.store';
import { useRootStore } from '@/stores/n8nRoot.store';
import { createEventBus } from '@/event-bus';
import { useToast } from '@/composables';
const DEFAULT_TITLE = 'How likely are you to recommend n8n to a friend or colleague?';
const GREAT_FEEDBACK_TITLE =
@ -80,6 +81,11 @@ export default mixins(workflowHelpers).extend({
components: {
ModalDrawer,
},
setup() {
return {
...useToast(),
};
},
watch: {
isActive(isActive) {
if (isActive) {
@ -164,7 +170,7 @@ export default mixins(workflowHelpers).extend({
instance_id: this.rootStore.instanceId,
email: this.form.email,
});
this.$showMessage({
this.showMessage({
title: 'Thanks for your feedback',
message:
'If youd like to help even more, leave us a <a target="_blank" href="https://www.g2.com/products/n8n/reviews/start">review on G2</a>.',

View file

@ -50,7 +50,7 @@
</template>
<script lang="ts">
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
import { workflowActivate } from '@/mixins/workflowActivate';
import { useUIStore } from '@/stores/ui.store';
import { useWorkflowsStore } from '@/stores/workflows.store';
@ -58,14 +58,16 @@ import { mapStores } from 'pinia';
import mixins from 'vue-typed-mixins';
import { getActivatableTriggerNodes } from '@/utils';
export default mixins(showMessage, workflowActivate).extend({
export default mixins(workflowActivate).extend({
name: 'WorkflowActivator',
props: ['workflowActive', 'workflowId'],
setup() {
return {
...useToast(),
};
},
computed: {
...mapStores(useUIStore, useWorkflowsStore),
getStateIsDirty(): boolean {
return this.uiStore.stateIsDirty;
},
nodesIssuesExist(): boolean {
return this.workflowsStore.nodesIssuesExist;
},
@ -123,7 +125,7 @@ export default mixins(showMessage, workflowActivate).extend({
);
}
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('workflowActivator.showMessage.displayActivationError.title'),
message: errorMessage,
type: 'warning',

View file

@ -62,15 +62,16 @@
</template>
<script lang="ts">
import mixins from 'vue-typed-mixins';
import { defineComponent } from 'vue';
import type { IWorkflowDb, IUser, ITag } from '@/Interface';
import {
DUPLICATE_MODAL_KEY,
EnterpriseEditionFeature,
MODAL_CONFIRM,
VIEWS,
WORKFLOW_SHARE_MODAL_KEY,
} from '@/constants';
import { showMessage } from '@/mixins/showMessage';
import { useToast, useMessage } from '@/composables';
import type { IPermissions } from '@/permissions';
import { getWorkflowPermissions } from '@/permissions';
import dateformat from 'dateformat';
@ -90,12 +91,18 @@ export const WORKFLOW_LIST_ITEM_ACTIONS = {
DELETE: 'delete',
};
export default mixins(showMessage).extend({
export default defineComponent({
data() {
return {
EnterpriseEditionFeature,
};
},
setup() {
return {
...useToast(),
...useMessage(),
};
},
components: {
WorkflowActivator,
},
@ -218,29 +225,35 @@ export default mixins(showMessage).extend({
sub_view: this.$route.name === VIEWS.WORKFLOWS ? 'Workflows listing' : 'Workflow editor',
});
} else if (action === WORKFLOW_LIST_ITEM_ACTIONS.DELETE) {
const deleteConfirmed = await this.confirmMessage(
const deleteConfirmed = await this.confirm(
this.$locale.baseText('mainSidebar.confirmMessage.workflowDelete.message', {
interpolate: { workflowName: this.data.name },
}),
this.$locale.baseText('mainSidebar.confirmMessage.workflowDelete.headline'),
'warning',
this.$locale.baseText('mainSidebar.confirmMessage.workflowDelete.confirmButtonText'),
this.$locale.baseText('mainSidebar.confirmMessage.workflowDelete.cancelButtonText'),
{
type: 'warning',
confirmButtonText: this.$locale.baseText(
'mainSidebar.confirmMessage.workflowDelete.confirmButtonText',
),
cancelButtonText: this.$locale.baseText(
'mainSidebar.confirmMessage.workflowDelete.cancelButtonText',
),
},
);
if (deleteConfirmed === false) {
if (deleteConfirmed !== MODAL_CONFIRM) {
return;
}
try {
await this.workflowsStore.deleteWorkflow(this.data.id);
} catch (error) {
this.$showError(error, this.$locale.baseText('generic.deleteWorkflowError'));
this.showError(error, this.$locale.baseText('generic.deleteWorkflowError'));
return;
}
// Reset tab title since workflow is deleted.
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('mainSidebar.showMessage.handleSelect1.title'),
type: 'success',
});

View file

@ -22,13 +22,13 @@
</template>
<script lang="ts">
import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage';
import type { IWorkflowDb } from '../Interface';
import { defineComponent } from 'vue';
import { useToast } from '@/composables';
import type { IWorkflowDb } from '@/Interface';
import { mapStores } from 'pinia';
import { useRootStore } from '@/stores/n8nRoot.store';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'WorkflowPreview',
props: {
loading: {
@ -58,6 +58,11 @@ export default mixins(showMessage).extend({
validator: (value: string): boolean => ['image', 'spinner'].includes(value),
},
},
setup() {
return {
...useToast(),
};
},
data() {
return {
nodeViewDetailsOpened: false,
@ -107,7 +112,7 @@ export default mixins(showMessage).extend({
);
}
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('workflowPreview.showError.previewError.title'),
this.$locale.baseText('workflowPreview.showError.previewError.message'),
@ -131,7 +136,7 @@ export default mixins(showMessage).extend({
);
}
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('workflowPreview.showError.previewError.title'),
this.$locale.baseText('workflowPreview.executionMode.showError.previewError.message'),

View file

@ -328,7 +328,7 @@ import Vue from 'vue';
import { externalHooks } from '@/mixins/externalHooks';
import { genericHelpers } from '@/mixins/genericHelpers';
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
import type {
ITimeoutHMS,
IUser,
@ -337,12 +337,12 @@ import type {
IWorkflowSettings,
IWorkflowShortResponse,
} from '@/Interface';
import Modal from './Modal.vue';
import Modal from '@/components/Modal.vue';
import {
EnterpriseEditionFeature,
PLACEHOLDER_EMPTY_WORKFLOW_ID,
WORKFLOW_SETTINGS_MODAL_KEY,
} from '../constants';
} from '@/constants';
import mixins from 'vue-typed-mixins';
@ -356,11 +356,16 @@ import useWorkflowsEEStore from '@/stores/workflows.ee.store';
import { useUsersStore } from '@/stores/users.store';
import { createEventBus } from '@/event-bus';
export default mixins(externalHooks, genericHelpers, showMessage).extend({
export default mixins(externalHooks, genericHelpers).extend({
name: 'WorkflowSettings',
components: {
Modal,
},
setup() {
return {
...useToast(),
};
},
data() {
return {
isLoading: true,
@ -448,7 +453,7 @@ export default mixins(externalHooks, genericHelpers, showMessage).extend({
this.maxExecutionTimeout = this.rootStore.maxExecutionTimeout;
if (!this.workflowId || this.workflowId === PLACEHOLDER_EMPTY_WORKFLOW_ID) {
this.$showMessage({
this.showMessage({
title: 'No workflow active',
message: 'No workflow active to display settings of.',
type: 'error',
@ -477,7 +482,7 @@ export default mixins(externalHooks, genericHelpers, showMessage).extend({
try {
await Promise.all(promises);
} catch (error) {
this.$showError(
this.showError(
error,
'Problem loading settings',
'The following error occurred loading the data:',
@ -754,7 +759,7 @@ export default mixins(externalHooks, genericHelpers, showMessage).extend({
data.settings!.executionTimeout !== -1 ? hours * 3600 + minutes * 60 + seconds : -1;
if (data.settings!.executionTimeout === 0) {
this.$showError(
this.showError(
new Error(this.$locale.baseText('workflowSettings.showError.saveSettings1.errorMessage')),
this.$locale.baseText('workflowSettings.showError.saveSettings1.title'),
this.$locale.baseText('workflowSettings.showError.saveSettings1.message') + ':',
@ -767,7 +772,7 @@ export default mixins(externalHooks, genericHelpers, showMessage).extend({
const { hours, minutes, seconds } = this.convertToHMS(
this.workflowSettings.maxExecutionTimeout as number,
);
this.$showError(
this.showError(
new Error(
this.$locale.baseText('workflowSettings.showError.saveSettings2.errorMessage', {
interpolate: {
@ -791,7 +796,7 @@ export default mixins(externalHooks, genericHelpers, showMessage).extend({
const workflow = await this.workflowsStore.updateWorkflow(this.$route.params.name, data);
this.workflowsStore.setWorkflowVersionId(workflow.versionId);
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('workflowSettings.showError.saveSettings3.title'),
);
@ -813,7 +818,7 @@ export default mixins(externalHooks, genericHelpers, showMessage).extend({
this.isLoading = false;
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('workflowSettings.showMessage.saveSettings.title'),
type: 'success',
});

View file

@ -126,15 +126,16 @@
import Modal from './Modal.vue';
import {
EnterpriseEditionFeature,
MODAL_CONFIRM,
PLACEHOLDER_EMPTY_WORKFLOW_ID,
VIEWS,
WORKFLOW_SHARE_MODAL_KEY,
} from '../constants';
} from '@/constants';
import type { IUser, IWorkflowDb } from '@/Interface';
import type { IPermissions } from '@/permissions';
import { getWorkflowPermissions } from '@/permissions';
import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage';
import { defineComponent } from 'vue';
import { useToast, useMessage } from '@/composables';
import { createEventBus, nodeViewEventBus } from '@/event-bus';
import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/settings.store';
@ -147,7 +148,7 @@ import { useUsageStore } from '@/stores/usage.store';
import type { BaseTextKey } from '@/plugins/i18n';
import { isNavigationFailure } from 'vue-router';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'workflow-share-modal',
components: {
Modal,
@ -158,6 +159,12 @@ export default mixins(showMessage).extend({
default: () => ({}),
},
},
setup() {
return {
...useToast(),
...useMessage(),
};
},
data() {
const workflowsStore = useWorkflowsStore();
const workflow =
@ -188,11 +195,6 @@ export default mixins(showMessage).extend({
isSharingEnabled(): boolean {
return this.settingsStore.isEnterpriseFeatureEnabled(EnterpriseEditionFeature.Sharing);
},
fallbackLinkUrl(): string {
return `${this.$locale.baseText(
this.uiStore.contextBasedTranslationKeys.upgradeLinkUrl as BaseTextKey,
)}${true ? '&utm_campaign=upgrade-workflow-sharing' : ''}`;
},
modalTitle(): string {
return this.$locale.baseText(
this.isSharingEnabled
@ -292,12 +294,12 @@ export default mixins(showMessage).extend({
sharees_removed: shareesRemoved.length,
});
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('workflows.shareModal.onSave.success.title'),
type: 'success',
});
} 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 {
this.modalBus.emit('close');
this.loading = false;
@ -370,7 +372,7 @@ export default mixins(showMessage).extend({
let confirm = true;
if (!isNewSharee && isLastUserWithAccessToCredentials) {
confirm = await this.confirmMessage(
const confirmAction = await this.confirm(
this.$locale.baseText(
'workflows.shareModal.list.delete.confirm.lastUserWithAccessToCredentials.message',
{
@ -380,10 +382,17 @@ export default mixins(showMessage).extend({
this.$locale.baseText('workflows.shareModal.list.delete.confirm.title', {
interpolate: { name: user.fullName as string },
}),
null,
this.$locale.baseText('workflows.shareModal.list.delete.confirm.confirmButtonText'),
this.$locale.baseText('workflows.shareModal.list.delete.confirm.cancelButtonText'),
{
confirmButtonText: this.$locale.baseText(
'workflows.shareModal.list.delete.confirm.confirmButtonText',
),
cancelButtonText: this.$locale.baseText(
'workflows.shareModal.list.delete.confirm.cancelButtonText',
),
},
);
confirm = confirmAction === MODAL_CONFIRM;
}
if (confirm) {
@ -404,15 +413,21 @@ export default mixins(showMessage).extend({
},
async onCloseModal() {
if (this.isDirty) {
const shouldSave = await this.confirmMessage(
const shouldSave = await this.confirm(
this.$locale.baseText('workflows.shareModal.saveBeforeClose.message'),
this.$locale.baseText('workflows.shareModal.saveBeforeClose.title'),
'warning',
this.$locale.baseText('workflows.shareModal.saveBeforeClose.confirmButtonText'),
this.$locale.baseText('workflows.shareModal.saveBeforeClose.cancelButtonText'),
{
type: 'warning',
confirmButtonText: this.$locale.baseText(
'workflows.shareModal.saveBeforeClose.confirmButtonText',
),
cancelButtonText: this.$locale.baseText(
'workflows.shareModal.saveBeforeClose.cancelButtonText',
),
},
);
if (shouldSave) {
if (shouldSave === MODAL_CONFIRM) {
return this.onSave();
}
}

View file

@ -10,7 +10,6 @@ import ExecutionsList from '@/components/ExecutionsList.vue';
import { externalHooks } from '@/mixins/externalHooks';
import { genericHelpers } from '@/mixins/genericHelpers';
import { executionHelpers } from '@/mixins/executionsHelpers';
import { showMessage } from '@/mixins/showMessage';
import { i18nInstance } from '@/plugins/i18n';
import type { IWorkflowDb } from '@/Interface';
import type { IExecutionsSummary } from 'n8n-workflow';
@ -73,7 +72,7 @@ const renderOptions = {
}),
i18n: i18nInstance,
stubs: ['font-awesome-icon'],
mixins: [externalHooks, genericHelpers, executionHelpers, showMessage],
mixins: [externalHooks, genericHelpers, executionHelpers],
};
function TelemetryPlugin(vue: typeof Vue): void {

View file

@ -195,7 +195,6 @@
</template>
<script lang="ts">
import { showMessage } from '@/mixins/showMessage';
import type { IUser } from '@/Interface';
import mixins from 'vue-typed-mixins';
@ -237,9 +236,7 @@ interface IFilters {
type IResourceKeyType = 'credentials' | 'workflows';
type SearchRef = InstanceType<typeof N8nInput>;
const filterKeys = ['ownedBy', 'sharedWith'];
export default mixins(showMessage, debounceHelper).extend({
export default mixins(debounceHelper).extend({
name: 'resources-list-layout',
components: {
TemplateCard,

View file

@ -1,8 +1,13 @@
export { default as useCanvasMouseSelect } from './useCanvasMouseSelect';
export * from './useCopyToClipboard';
export * from './useDebounce';
export { default as useDeviceSupport } from './useDeviceSupport';
export * from './useExternalHooks';
export * from './useGlobalLinkActions';
export { default as useGlobalLinkActions } from './useGlobalLinkActions';
export * from './useHistoryHelper';
export * from './useI18n';
export * from './useMessage';
export * from './useTelemetry';
export * from './useTitleChange';
export * from './useToast';
export * from './useUpgradeLink';

View file

@ -3,7 +3,7 @@ import type { ElNotificationComponent, ElNotificationOptions } from 'element-ui/
import type { MessageType } from 'element-ui/types/message';
import { sanitizeHtml } from '@/utils';
import { useTelemetry } from '@/composables/useTelemetry';
import { useWorkflowsStore } from '@/stores';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { useI18n } from './useI18n';
import { useExternalHooks } from './useExternalHooks';
@ -39,6 +39,7 @@ export function useToast() {
telemetry.track('Instance FE emitted error', {
error_title: messageData.title,
error_message: messageData.message,
caused_by_credential: causedByCredential(messageData.message),
workflow_id: workflowsStore.workflowId,
});
}
@ -130,13 +131,36 @@ export function useToast() {
error_title: title,
error_description: message,
error_message: error.message,
caused_by_credential: causedByCredential(error.message),
workflow_id: workflowsStore.workflowId,
});
}
function showAlert(config: ElNotificationOptions): ElNotificationComponent {
return Notification(config);
}
function causedByCredential(message: string | undefined) {
if (!message) return false;
return message.includes('Credentials for') && message.includes('are not set');
}
function clearAllStickyNotifications() {
stickyNotificationQueue.forEach((notification) => {
if (notification) {
notification.close();
}
});
stickyNotificationQueue.length = 0;
}
return {
showMessage,
showToast,
showError,
showAlert,
clearAllStickyNotifications,
};
}

View file

@ -304,7 +304,7 @@ export const ROLE_OTHER = 'other';
export const MODAL_CANCEL = 'cancel';
export const MODAL_CLOSE = 'close';
export const MODAL_CONFIRMED = 'confirmed';
export const MODAL_CONFIRM = 'confirm';
export const VALID_EMAIL_REGEX =
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

View file

@ -1,10 +1,15 @@
import mixins from 'vue-typed-mixins';
import { defineComponent } from 'vue';
import dateformat from 'dateformat';
import { VIEWS } from '@/constants';
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
export const genericHelpers = mixins(showMessage).extend({
export const genericHelpers = defineComponent({
setup() {
return {
...useToast(),
};
},
data() {
return {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@ -46,7 +51,7 @@ export const genericHelpers = mixins(showMessage).extend({
},
editAllowedCheck(): boolean {
if (this.isReadOnly) {
this.$showMessage({
this.showMessage({
// title: 'Workflow can not be changed!',
title: this.$locale.baseText('genericHelpers.showMessage.title'),
message: this.$locale.baseText('genericHelpers.showMessage.message'),

View file

@ -1,11 +1,16 @@
import mixins from 'vue-typed-mixins';
import { showMessage } from './showMessage';
import { defineComponent } from 'vue';
import { useToast } from '@/composables';
import { VERSIONS_MODAL_KEY } from '@/constants';
import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui.store';
import { useVersionsStore } from '@/stores/versions.store';
export const newVersions = mixins(showMessage).extend({
export const newVersions = defineComponent({
setup() {
return {
...useToast(),
};
},
computed: {
...mapStores(useUIStore, useVersionsStore),
},
@ -28,7 +33,7 @@ export const newVersions = mixins(showMessage).extend({
}
message = `${message} <a class="primary-color">More info</a>`;
this.$showToast({
this.showToast({
title: 'Critical update available',
message,
onClick: () => {

View file

@ -5,6 +5,7 @@ import { stringSizeInBytes } from '@/utils';
import { MAX_WORKFLOW_PINNED_DATA_SIZE, PIN_DATA_NODE_TYPES_DENYLIST } from '@/constants';
import { mapStores } from 'pinia';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { useToast } from '@/composables';
export interface IPinDataContext {
node: INodeUi;
@ -13,6 +14,11 @@ export interface IPinDataContext {
}
export const pinData = (Vue as Vue.VueConstructor<Vue & IPinDataContext>).extend({
setup() {
return {
...useToast(),
};
},
computed: {
...mapStores(useWorkflowsStore),
pinData(): IPinData[string] | undefined {
@ -72,7 +78,7 @@ export const pinData = (Vue as Vue.VueConstructor<Vue & IPinDataContext>).extend
})} ${error.message}`;
}
this.$showError(error, title);
this.showError(error, title);
return false;
}
@ -84,7 +90,7 @@ export const pinData = (Vue as Vue.VueConstructor<Vue & IPinDataContext>).extend
this.workflowsStore.pinDataSize + stringSizeInBytes(data) >
MAX_WORKFLOW_PINNED_DATA_SIZE
) {
this.$showError(
this.showError(
new Error(this.$locale.baseText('ndv.pinData.error.tooLarge.description')),
this.$locale.baseText('ndv.pinData.error.tooLarge.title'),
);

View file

@ -7,8 +7,7 @@ import type {
import { externalHooks } from '@/mixins/externalHooks';
import { nodeHelpers } from '@/mixins/nodeHelpers';
import { showMessage } from '@/mixins/showMessage';
import { useTitleChange } from '@/composables/useTitleChange';
import { useTitleChange, useToast } from '@/composables';
import { workflowHelpers } from '@/mixins/workflowHelpers';
import type {
@ -19,6 +18,7 @@ import type {
IRunExecutionData,
IWorkflowBase,
SubworkflowOperationError,
IExecuteContextData,
} from 'n8n-workflow';
import { TelemetryHelpers } from 'n8n-workflow';
@ -35,15 +35,11 @@ import { useSettingsStore } from '@/stores/settings.store';
import { parse } from 'flatted';
import { useSegment } from '@/stores/segment.store';
export const pushConnection = mixins(
externalHooks,
nodeHelpers,
showMessage,
workflowHelpers,
).extend({
export const pushConnection = mixins(externalHooks, nodeHelpers, workflowHelpers).extend({
setup() {
return {
...useTitleChange(),
...useToast(),
};
},
data() {
@ -324,7 +320,7 @@ export const pushConnection = mixins(
const runDataExecuted = pushData.data;
let runDataExecutedErrorMessage = this.$getExecutionError(runDataExecuted.data);
let runDataExecutedErrorMessage = this.getExecutionError(runDataExecuted.data);
if (pushData.data.status === 'crashed') {
runDataExecutedErrorMessage = this.$locale.baseText(
@ -367,7 +363,7 @@ export const pushConnection = mixins(
// Workflow did start but had been put to wait
this.titleSet(workflow.name as string, 'IDLE');
this.$showToast({
this.showToast({
title: 'Workflow started waiting',
message: `${action} <a href="https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.wait/" target="_blank">More info</a>`,
type: 'success',
@ -422,7 +418,7 @@ export const pushConnection = mixins(
this.workflowsStore.subWorkflowExecutionError = error;
this.$showMessage({
this.showMessage({
title: error.message,
message: error.description,
type: 'error',
@ -436,7 +432,7 @@ export const pushConnection = mixins(
title = 'Problem executing workflow';
}
this.$showMessage({
this.showMessage({
title,
message: runDataExecutedErrorMessage,
type: 'error',
@ -459,7 +455,7 @@ export const pushConnection = mixins(
execution.data.resultData.runData &&
execution.data.resultData.runData[execution.executedNode];
if (nodeType && nodeType.polling && !nodeOutput) {
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('pushConnection.pollingNode.dataNotFound', {
interpolate: {
service: getTriggerNodeServiceName(nodeType),
@ -473,13 +469,13 @@ export const pushConnection = mixins(
type: 'success',
});
} else {
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('pushConnection.nodeExecutedSuccessfully'),
type: 'success',
});
}
} else {
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('pushConnection.workflowExecutedSuccessfully'),
type: 'success',
});
@ -582,5 +578,38 @@ export const pushConnection = mixins(
}
return true;
},
getExecutionError(data: IRunExecutionData | IExecuteContextData) {
const error = data.resultData.error;
let errorMessage: string;
if (data.resultData.lastNodeExecuted && error) {
errorMessage = error.message || error.description;
} else {
errorMessage = this.$locale.baseText('pushConnection.executionError', {
interpolate: { error: '!' },
});
if (error && error.message) {
let nodeName: string | undefined;
if ('node' in error) {
nodeName = typeof error.node === 'string' ? error.node : error.node!.name;
}
const receivedError = nodeName ? `${nodeName}: ${error.message}` : error.message;
errorMessage = this.$locale.baseText('pushConnection.executionError', {
interpolate: {
error: `.${this.$locale.baseText('pushConnection.executionError.details', {
interpolate: {
details: receivedError,
},
})}`,
},
});
}
}
return errorMessage;
},
},
});

View file

@ -1,235 +0,0 @@
// @ts-ignore
import type { ElNotificationComponent, ElNotificationOptions } from 'element-ui/types/notification';
import mixins from 'vue-typed-mixins';
import { externalHooks } from '@/mixins/externalHooks';
import type { IExecuteContextData, IRunExecutionData } from 'n8n-workflow';
import type { ElMessageBoxOptions } from 'element-ui/types/message-box';
import type { ElMessageComponent, ElMessageOptions, MessageType } from 'element-ui/types/message';
import { sanitizeHtml } from '@/utils';
import { mapStores } from 'pinia';
import { useWorkflowsStore } from '@/stores/workflows.store';
let stickyNotificationQueue: ElNotificationComponent[] = [];
export const showMessage = mixins(externalHooks).extend({
computed: {
...mapStores(useWorkflowsStore),
},
methods: {
$showMessage(
messageData: Omit<ElNotificationOptions, 'message'> & { message?: string },
track = true,
) {
messageData.dangerouslyUseHTMLString = true;
messageData.message = messageData.message
? sanitizeHtml(messageData.message)
: messageData.message;
if (messageData.position === undefined) {
messageData.position = 'bottom-right';
}
const notification = this.$notify(messageData as ElNotificationOptions);
if (messageData.duration === 0) {
stickyNotificationQueue.push(notification);
}
if (messageData.type === 'error' && track) {
this.$telemetry.track('Instance FE emitted error', {
error_title: messageData.title,
error_message: messageData.message,
caused_by_credential: this.causedByCredential(messageData.message),
workflow_id: this.workflowsStore.workflowId,
});
}
return notification;
},
$showToast(config: {
title: string;
message: string;
onClick?: () => void;
onClose?: () => void;
duration?: number;
customClass?: string;
closeOnClick?: boolean;
type?: MessageType;
}) {
// eslint-disable-next-line prefer-const
let notification: ElNotificationComponent;
if (config.closeOnClick) {
const cb = config.onClick;
config.onClick = () => {
if (notification) {
notification.close();
}
if (cb) {
cb();
}
};
}
notification = this.$showMessage({
title: config.title,
message: config.message,
onClick: config.onClick,
onClose: config.onClose,
duration: config.duration,
customClass: config.customClass,
type: config.type,
});
return notification;
},
$showAlert(config: ElMessageOptions): ElMessageComponent {
return this.$message(config);
},
$getExecutionError(data: IRunExecutionData | IExecuteContextData) {
const error = data.resultData.error;
let errorMessage: string;
if (data.resultData.lastNodeExecuted && error) {
errorMessage = error.message || error.description;
} else {
errorMessage = 'There was a problem executing the workflow!';
if (error && error.message) {
let nodeName: string | undefined;
if ('node' in error) {
nodeName = typeof error.node === 'string' ? error.node : error.node!.name;
}
const receivedError = nodeName ? `${nodeName}: ${error.message}` : error.message;
errorMessage = `There was a problem executing the workflow:<br /><strong>"${receivedError}"</strong>`;
}
}
return errorMessage;
},
$showError(e: Error | unknown, title: string, message?: string) {
const error = e as Error;
const messageLine = message ? `${message}<br/>` : '';
this.$showMessage(
{
title,
message: `
${messageLine}
<i>${error.message}</i>
${this.collapsableDetails(error)}`,
type: 'error',
duration: 0,
},
false,
);
void this.$externalHooks().run('showMessage.showError', {
title,
message,
errorMessage: error.message,
});
this.$telemetry.track('Instance FE emitted error', {
error_title: title,
error_description: message,
error_message: error.message,
caused_by_credential: this.causedByCredential(error.message),
workflow_id: this.workflowsStore.workflowId,
});
},
async confirmMessage(
message: string,
headline: string,
type: MessageType | null = 'warning',
confirmButtonText?: string,
cancelButtonText?: string,
): Promise<boolean> {
try {
const options: ElMessageBoxOptions = {
confirmButtonText: confirmButtonText || this.$locale.baseText('showMessage.ok'),
cancelButtonText: cancelButtonText || this.$locale.baseText('showMessage.cancel'),
dangerouslyUseHTMLString: true,
...(type && { type }),
};
const sanitizedMessage = sanitizeHtml(message);
await this.$confirm(sanitizedMessage, headline, options);
return true;
} catch (e) {
return false;
}
},
async confirmModal(
message: string,
headline: string,
type: MessageType | null = 'warning',
confirmButtonText?: string,
cancelButtonText?: string,
showClose = false,
): Promise<string> {
try {
const options: ElMessageBoxOptions = {
confirmButtonText: confirmButtonText || this.$locale.baseText('showMessage.ok'),
cancelButtonText: cancelButtonText || this.$locale.baseText('showMessage.cancel'),
dangerouslyUseHTMLString: true,
showClose,
...(type && { type }),
};
const sanitizedMessage = sanitizeHtml(message);
await this.$confirm(sanitizedMessage, headline, options);
return 'confirmed';
} catch (e) {
return e as string;
}
},
clearAllStickyNotifications() {
stickyNotificationQueue.map((notification: ElNotificationComponent) => {
if (notification) {
notification.close();
}
});
stickyNotificationQueue = [];
},
// @ts-ignore
collapsableDetails({ description, node }: Error) {
if (!description) return '';
const errorDescription =
description.length > 500 ? `${description.slice(0, 500)}...` : description;
return `
<br>
<br>
<details>
<summary
style="color: #ff6d5a; font-weight: bold; cursor: pointer;"
>
${this.$locale.baseText('showMessage.showDetails')}
</summary>
<p>${node.name}: ${errorDescription}</p>
</details>
`;
},
/**
* Whether a workflow execution error was caused by a credential issue, as reflected by the error message.
*/
causedByCredential(message: string | undefined) {
if (!message) return false;
return message.includes('Credentials for') && message.includes('are not set');
},
},
});

View file

@ -1,6 +1,6 @@
import { externalHooks } from '@/mixins/externalHooks';
import { workflowHelpers } from '@/mixins/workflowHelpers';
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
import mixins from 'vue-typed-mixins';
import {
@ -13,7 +13,12 @@ import { useUIStore } from '@/stores/ui.store';
import { useSettingsStore } from '@/stores/settings.store';
import { useWorkflowsStore } from '@/stores/workflows.store';
export const workflowActivate = mixins(externalHooks, workflowHelpers, showMessage).extend({
export const workflowActivate = mixins(externalHooks, workflowHelpers).extend({
setup() {
return {
...useToast(),
};
},
data() {
return {
updatingWorkflowActivation: false,
@ -60,7 +65,7 @@ export const workflowActivate = mixins(externalHooks, workflowHelpers, showMessa
try {
if (isWorkflowActive && newActiveState) {
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('workflowActivator.workflowIsActive'),
type: 'success',
});
@ -70,7 +75,7 @@ export const workflowActivate = mixins(externalHooks, workflowHelpers, showMessa
}
if (isCurrentWorkflow && nodesIssuesExist && newActiveState === true) {
this.$showMessage({
this.showMessage({
title: this.$locale.baseText(
'workflowActivator.showMessage.activeChangedNodesIssuesExistTrue.title',
),
@ -87,7 +92,7 @@ export const workflowActivate = mixins(externalHooks, workflowHelpers, showMessa
await this.updateWorkflow({ workflowId: currWorkflowId, active: newActiveState });
} catch (error) {
const newStateName = newActiveState === true ? 'activated' : 'deactivated';
this.$showError(
this.showError(
error,
this.$locale.baseText('workflowActivator.showError.title', {
interpolate: { newStateName },

View file

@ -4,6 +4,7 @@ import {
WEBHOOK_NODE_TYPE,
VIEWS,
EnterpriseEditionFeature,
MODAL_CONFIRM,
} from '@/constants';
import type {
@ -40,7 +41,7 @@ import type {
import { externalHooks } from '@/mixins/externalHooks';
import { nodeHelpers } from '@/mixins/nodeHelpers';
import { showMessage } from '@/mixins/showMessage';
import { useToast, useMessage } from '@/composables';
import { isEqual } from 'lodash-es';
@ -320,7 +321,13 @@ function executeData(
return executeData;
}
export const workflowHelpers = mixins(externalHooks, nodeHelpers, showMessage).extend({
export const workflowHelpers = mixins(externalHooks, nodeHelpers).extend({
setup() {
return {
...useToast(),
...useMessage(),
};
},
computed: {
...mapStores(
useNodeTypesStore,
@ -741,26 +748,31 @@ export const workflowHelpers = mixins(externalHooks, nodeHelpers, showMessage).e
params: { name: currentWorkflow },
}).href;
const overwrite = await this.confirmMessage(
const overwrite = await this.confirm(
this.$locale.baseText('workflows.concurrentChanges.confirmMessage.message', {
interpolate: {
url,
},
}),
this.$locale.baseText('workflows.concurrentChanges.confirmMessage.title'),
null,
this.$locale.baseText('workflows.concurrentChanges.confirmMessage.confirmButtonText'),
this.$locale.baseText('workflows.concurrentChanges.confirmMessage.cancelButtonText'),
{
confirmButtonText: this.$locale.baseText(
'workflows.concurrentChanges.confirmMessage.confirmButtonText',
),
cancelButtonText: this.$locale.baseText(
'workflows.concurrentChanges.confirmMessage.cancelButtonText',
),
},
);
if (overwrite) {
if (overwrite === MODAL_CONFIRM) {
return this.saveCurrentWorkflow({ id, name, tags }, redirect, true);
}
return false;
}
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('workflowHelpers.showMessage.title'),
message: error.message,
type: 'error',
@ -890,7 +902,7 @@ export const workflowHelpers = mixins(externalHooks, nodeHelpers, showMessage).e
} catch (e) {
this.uiStore.removeActiveAction('workflowSaving');
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('workflowHelpers.showMessage.title'),
message: (e as Error).message,
type: 'error',

View file

@ -5,7 +5,7 @@ import { NodeHelpers, TelemetryHelpers } from 'n8n-workflow';
import { externalHooks } from '@/mixins/externalHooks';
import { workflowHelpers } from '@/mixins/workflowHelpers';
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
import mixins from 'vue-typed-mixins';
import { useTitleChange } from '@/composables/useTitleChange';
@ -14,10 +14,11 @@ import { useUIStore } from '@/stores/ui.store';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { useRootStore } from '@/stores/n8nRoot.store';
export const workflowRun = mixins(externalHooks, workflowHelpers, showMessage).extend({
export const workflowRun = mixins(externalHooks, workflowHelpers).extend({
setup() {
return {
...useTitleChange(),
...useToast(),
};
},
computed: {
@ -106,7 +107,7 @@ export const workflowRun = mixins(externalHooks, workflowHelpers, showMessage).e
trackNodeIssues.push(trackNodeIssue);
}
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('workflowRun.showMessage.title'),
message: errorMessages.join('<br />'),
type: 'error',
@ -239,7 +240,7 @@ export const workflowRun = mixins(externalHooks, workflowHelpers, showMessage).e
return runWorkflowApiResponse;
} catch (error) {
this.titleSet(workflow.name as string, 'ERROR');
this.$showError(error, this.$locale.baseText('workflowRun.showError.title'));
this.showError(error, this.$locale.baseText('workflowRun.showError.title'));
return undefined;
}
},

View file

@ -1821,5 +1821,7 @@
"userActivationSurveyModal.sharedFeedback.success": "Thanks for your feedback",
"userActivationSurveyModal.sharedFeedback.error": "Problem sharing feedback, try again",
"sso.login.divider": "or",
"sso.login.button": "Continue with SSO"
"sso.login.button": "Continue with SSO",
"pushConnection.executionError": "There was a problem executing the workflow{error}",
"pushConnection.executionError.details": "<br /><strong>{details}</strong>"
}

View file

@ -9,20 +9,25 @@
</template>
<script lang="ts">
import AuthView from './AuthView.vue';
import { showMessage } from '@/mixins/showMessage';
import AuthView from '@/views/AuthView.vue';
import { useToast } from '@/composables';
import mixins from 'vue-typed-mixins';
import { defineComponent } from 'vue';
import type { IFormBoxConfig } from '@/Interface';
import { VIEWS } from '@/constants';
import { mapStores } from 'pinia';
import { useUsersStore } from '@/stores/users.store';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'ChangePasswordView',
components: {
AuthView,
},
setup() {
return {
...useToast(),
};
},
data() {
return {
password: '',
@ -88,7 +93,7 @@ export default mixins(showMessage).extend({
await this.usersStore.validatePasswordToken({ token, userId });
} catch (e) {
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('auth.changePassword.tokenValidationError'),
type: 'error',
});
@ -128,7 +133,7 @@ export default mixins(showMessage).extend({
if (token && userId) {
await this.usersStore.changePassword({ token, userId, password: this.password });
this.$showMessage({
this.showMessage({
type: 'success',
title: this.$locale.baseText('auth.changePassword.passwordUpdated'),
message: this.$locale.baseText('auth.changePassword.passwordUpdatedMessage'),
@ -136,13 +141,13 @@ export default mixins(showMessage).extend({
await this.$router.push({ name: VIEWS.SIGNIN });
} else {
this.$showError(
this.showError(
new Error(this.$locale.baseText('auth.validation.missingParameters')),
this.$locale.baseText('auth.changePassword.error'),
);
}
} catch (error) {
this.$showError(error, this.$locale.baseText('auth.changePassword.error'));
this.showError(error, this.$locale.baseText('auth.changePassword.error'));
}
this.loading = false;
},

View file

@ -44,20 +44,12 @@
</template>
<script lang="ts">
import { showMessage } from '@/mixins/showMessage';
import type { ICredentialsResponse, ICredentialTypeMap } from '@/Interface';
import mixins from 'vue-typed-mixins';
import { defineComponent } from 'vue';
import SettingsView from './SettingsView.vue';
import ResourcesListLayout from '@/components/layouts/ResourcesListLayout.vue';
import PageViewLayout from '@/components/layouts/PageViewLayout.vue';
import PageViewLayoutList from '@/components/layouts/PageViewLayoutList.vue';
import CredentialCard from '@/components/CredentialCard.vue';
import type { ICredentialType } from 'n8n-workflow';
import TemplateCard from '@/components/TemplateCard.vue';
import { debounceHelper } from '@/mixins/debounce';
import ResourceOwnershipSelect from '@/components/forms/ResourceOwnershipSelect.ee.vue';
import ResourceFiltersDropdown from '@/components/forms/ResourceFiltersDropdown.vue';
import { CREDENTIAL_SELECT_MODAL_KEY } from '@/constants';
import type Vue from 'vue';
import { mapStores } from 'pinia';
@ -68,17 +60,11 @@ import { useCredentialsStore } from '@/stores/credentials.store';
type IResourcesListLayoutInstance = Vue & { sendFiltersTelemetry: (source: string) => void };
export default mixins(showMessage, debounceHelper).extend({
export default defineComponent({
name: 'SettingsPersonalView',
components: {
ResourcesListLayout,
TemplateCard,
PageViewLayout,
PageViewLayoutList,
SettingsView,
CredentialCard,
ResourceOwnershipSelect,
ResourceFiltersDropdown,
},
data() {
return {

View file

@ -4,19 +4,24 @@
<script lang="ts">
import AuthView from './AuthView.vue';
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
import mixins from 'vue-typed-mixins';
import { defineComponent } from 'vue';
import type { IFormBoxConfig } from '@/Interface';
import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/settings.store';
import { useUsersStore } from '@/stores/users.store';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'ForgotMyPasswordView',
components: {
AuthView,
},
setup() {
return {
...useToast(),
};
},
data() {
return {
loading: false,
@ -74,7 +79,7 @@ export default mixins(showMessage).extend({
this.loading = true;
await this.usersStore.sendForgotPasswordEmail(values);
this.$showMessage({
this.showMessage({
type: 'success',
title: this.$locale.baseText('forgotPassword.recoveryEmailSent'),
message: this.$locale.baseText('forgotPassword.emailSentIfExists', {
@ -86,7 +91,7 @@ export default mixins(showMessage).extend({
if (error.httpStatusCode === 422) {
message = this.$locale.baseText(error.message);
}
this.$showMessage({
this.showMessage({
type: 'error',
title: this.$locale.baseText('forgotPassword.sendingEmailError'),
message,

View file

@ -186,7 +186,7 @@ import {
MAIN_HEADER_TABS,
MODAL_CANCEL,
MODAL_CLOSE,
MODAL_CONFIRMED,
MODAL_CONFIRM,
NODE_OUTPUT_DEFAULT_KEY,
ONBOARDING_CALL_SIGNUP_MODAL_KEY,
ONBOARDING_PROMPT_TIMEBOX,
@ -206,13 +206,15 @@ import { copyPaste } from '@/mixins/copyPaste';
import { externalHooks } from '@/mixins/externalHooks';
import { genericHelpers } from '@/mixins/genericHelpers';
import { moveNodeWorkflow } from '@/mixins/moveNodeWorkflow';
import useGlobalLinkActions from '@/composables/useGlobalLinkActions';
import useCanvasMouseSelect from '@/composables/useCanvasMouseSelect';
import { showMessage } from '@/mixins/showMessage';
import { useTitleChange } from '@/composables/useTitleChange';
import {
useGlobalLinkActions,
useCanvasMouseSelect,
useMessage,
useToast,
useTitleChange,
} from '@/composables';
import { useUniqueNodeName } from '@/composables/useUniqueNodeName';
import { useI18n } from '@/composables/useI18n';
import { workflowHelpers } from '@/mixins/workflowHelpers';
import { workflowRun } from '@/mixins/workflowRun';
@ -322,7 +324,6 @@ export default mixins(
externalHooks,
genericHelpers,
moveNodeWorkflow,
showMessage,
workflowHelpers,
workflowRun,
debounceHelper,
@ -343,6 +344,8 @@ export default mixins(
...useCanvasMouseSelect(),
...useGlobalLinkActions(),
...useTitleChange(),
...useToast(),
...useMessage(),
...useUniqueNodeName(),
...useI18n(),
};
@ -415,15 +418,21 @@ export default mixins(
return;
}
if (this.uiStore.stateIsDirty) {
const confirmModal = await this.confirmModal(
const confirmModal = await this.confirm(
this.$locale.baseText('generic.unsavedWork.confirmMessage.message'),
this.$locale.baseText('generic.unsavedWork.confirmMessage.headline'),
'warning',
this.$locale.baseText('generic.unsavedWork.confirmMessage.confirmButtonText'),
this.$locale.baseText('generic.unsavedWork.confirmMessage.cancelButtonText'),
true,
{
title: this.$locale.baseText('generic.unsavedWork.confirmMessage.headline'),
type: 'warning',
confirmButtonText: this.$locale.baseText(
'generic.unsavedWork.confirmMessage.confirmButtonText',
),
cancelButtonText: this.$locale.baseText(
'generic.unsavedWork.confirmMessage.cancelButtonText',
),
showClose: true,
},
);
if (confirmModal === MODAL_CONFIRMED) {
if (confirmModal === MODAL_CONFIRM) {
// Make sure workflow id is empty when leaving the editor
this.workflowsStore.setWorkflowId(PLACEHOLDER_EMPTY_WORKFLOW_ID);
const saved = await this.saveCurrentWorkflow({}, false);
@ -660,7 +669,7 @@ export default mixins(
this.registerCustomAction('showNodeCreator', () =>
this.showTriggerCreator(NODE_CREATOR_OPEN_SOURCES.NO_TRIGGER_EXECUTION_TOOLTIP),
);
const notice = this.$showMessage({
const notice = this.showMessage({
type: 'info',
title: this.$locale.baseText('nodeView.cantExecuteNoTrigger'),
message,
@ -688,7 +697,7 @@ export default mixins(
saved = true;
}
if (saved) {
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('generic.workflowSaved'),
type: 'success',
});
@ -708,7 +717,7 @@ export default mixins(
try {
data = await this.workflowsStore.getExecution(executionId);
} catch (error) {
this.$showError(error, this.$locale.baseText('nodeView.showError.openExecution.title'));
this.showError(error, this.$locale.baseText('nodeView.showError.openExecution.title'));
return;
}
if (data === undefined) {
@ -766,7 +775,7 @@ export default mixins(
}
}
if ((data as IExecutionsSummary).waitTill) {
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('nodeView.thisExecutionHasntFinishedYet'),
message: `<a data-action="reload">${this.$locale.baseText(
'nodeView.refresh',
@ -819,7 +828,7 @@ export default mixins(
);
}
} catch (error) {
this.$showError(error, this.$locale.baseText('nodeView.couldntImportWorkflow'));
this.showError(error, this.$locale.baseText('nodeView.couldntImportWorkflow'));
void this.$router.replace({ name: VIEWS.NEW_WORKFLOW });
return;
}
@ -1030,7 +1039,7 @@ export default mixins(
void this.$router.push({ name: VIEWS.NEW_WORKFLOW });
}
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('nodeView.showMessage.keyDown.title'),
type: 'success',
});
@ -1305,7 +1314,7 @@ export default mixins(
this.copyToClipboard(nodeData);
if (data.nodes.length > 0) {
if (!isCut) {
this.$showMessage({
this.showMessage({
title: 'Copied!',
message: '',
type: 'success',
@ -1327,7 +1336,7 @@ export default mixins(
try {
this.stopExecutionInProgress = true;
await this.workflowsStore.stopCurrentExecution(executionId);
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('nodeView.showMessage.stopExecutionTry.title'),
type: 'success',
});
@ -1346,7 +1355,7 @@ export default mixins(
this.uiStore.removeActiveAction('workflowRunning');
this.titleSet(this.workflowsStore.workflowName, 'IDLE');
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('nodeView.showMessage.stopExecutionCatch.unsaved.title'),
message: this.$locale.baseText(
'nodeView.showMessage.stopExecutionCatch.unsaved.message',
@ -1373,13 +1382,13 @@ export default mixins(
this.workflowsStore.executingNode = null;
this.workflowsStore.setWorkflowExecutionData(executedData as IExecutionResponse);
this.uiStore.removeActiveAction('workflowRunning');
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('nodeView.showMessage.stopExecutionCatch.title'),
message: this.$locale.baseText('nodeView.showMessage.stopExecutionCatch.message'),
type: 'success',
});
} else {
this.$showError(error, this.$locale.baseText('nodeView.showError.stopExecution.title'));
this.showError(error, this.$locale.baseText('nodeView.showError.stopExecution.title'));
}
}
this.stopExecutionInProgress = false;
@ -1401,7 +1410,7 @@ export default mixins(
try {
await this.workflowsStore.removeTestWebhook(this.workflowsStore.workflowId);
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('nodeView.showError.stopWaitingForWebhook.title'),
);
@ -1426,19 +1435,23 @@ export default mixins(
return;
}
const importConfirm = await this.confirmMessage(
const importConfirm = await this.confirm(
this.$locale.baseText('nodeView.confirmMessage.receivedCopyPasteData.message', {
interpolate: { plainTextData },
}),
this.$locale.baseText('nodeView.confirmMessage.receivedCopyPasteData.headline'),
'warning',
this.$locale.baseText(
'nodeView.confirmMessage.receivedCopyPasteData.confirmButtonText',
),
this.$locale.baseText('nodeView.confirmMessage.receivedCopyPasteData.cancelButtonText'),
{
type: 'warning',
confirmButtonText: this.$locale.baseText(
'nodeView.confirmMessage.receivedCopyPasteData.confirmButtonText',
),
cancelButtonText: this.$locale.baseText(
'nodeView.confirmMessage.receivedCopyPasteData.cancelButtonText',
),
},
);
if (!importConfirm) {
if (importConfirm !== MODAL_CONFIRM) {
return;
}
@ -1475,7 +1488,7 @@ export default mixins(
workflowData = await this.workflowsStore.getWorkflowFromUrl(url);
} catch (error) {
this.stopLoading();
this.$showError(
this.showError(
error,
this.$locale.baseText('nodeView.showError.getWorkflowDataFromUrl.title'),
);
@ -1593,10 +1606,7 @@ export default mixins(
this.workflowsStore.addWorkflowTagIds(tagIds);
}
} catch (error) {
this.$showError(
error,
this.$locale.baseText('nodeView.showError.importWorkflowData.title'),
);
this.showError(error, this.$locale.baseText('nodeView.showError.importWorkflowData.title'));
}
},
onDragOver(event: DragEvent) {
@ -1660,7 +1670,7 @@ export default mixins(
},
showMaxNodeTypeError(nodeTypeData: INodeTypeDescription) {
const maxNodes = nodeTypeData.maxNodes;
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('nodeView.showMessage.showMaxNodeTypeError.title'),
message: this.$locale.baseText('nodeView.showMessage.showMaxNodeTypeError.message', {
adjustToNumber: maxNodes,
@ -1770,7 +1780,7 @@ export default mixins(
this.nodeTypesStore.getNodeType(nodeTypeName);
if (nodeTypeData === null) {
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('nodeView.showMessage.addNodeButton.title'),
message: this.$locale.baseText('nodeView.showMessage.addNodeButton.message', {
interpolate: { nodeTypeName },
@ -2490,15 +2500,21 @@ export default mixins(
} else {
const result = this.uiStore.stateIsDirty;
if (result) {
const confirmModal = await this.confirmModal(
const confirmModal = await this.confirm(
this.$locale.baseText('generic.unsavedWork.confirmMessage.message'),
this.$locale.baseText('generic.unsavedWork.confirmMessage.headline'),
'warning',
this.$locale.baseText('generic.unsavedWork.confirmMessage.confirmButtonText'),
this.$locale.baseText('generic.unsavedWork.confirmMessage.cancelButtonText'),
true,
{
title: this.$locale.baseText('generic.unsavedWork.confirmMessage.headline'),
type: 'warning',
confirmButtonText: this.$locale.baseText(
'generic.unsavedWork.confirmMessage.confirmButtonText',
),
cancelButtonText: this.$locale.baseText(
'generic.unsavedWork.confirmMessage.cancelButtonText',
),
showClose: true,
},
);
if (confirmModal === MODAL_CONFIRMED) {
if (confirmModal === MODAL_CONFIRM) {
const saved = await this.saveCurrentWorkflow();
if (saved) await this.settingsStore.fetchPromptsData();
} else if (confirmModal === MODAL_CLOSE) {
@ -2515,7 +2531,7 @@ export default mixins(
try {
workflow = await this.workflowsStore.fetchWorkflow(workflowId);
} catch (error) {
this.$showError(error, this.$locale.baseText('openWorkflow.workflowNotFoundError'));
this.showError(error, this.$locale.baseText('openWorkflow.workflowNotFoundError'));
void this.$router.push({
name: VIEWS.NEW_WORKFLOW,
@ -2999,7 +3015,7 @@ export default mixins(
},
async renameNodePrompt(currentName: string) {
try {
const promptResponsePromise = this.$prompt(
const promptResponsePromise = this.prompt(
this.$locale.baseText('nodeView.prompt.newName') + ':',
this.$locale.baseText('nodeView.prompt.renameNode') + `: ${currentName}`,
{
@ -3557,7 +3573,7 @@ export default mixins(
'*',
);
}
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('openWorkflow.workflowImportError'),
message: (e as Error).message,
type: 'error',
@ -3581,7 +3597,7 @@ export default mixins(
'*',
);
}
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('nodeView.showError.openExecution.title'),
message: (e as Error).message,
type: 'error',
@ -3780,7 +3796,7 @@ export default mixins(
try {
await Promise.all(loadPromises);
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('nodeView.showError.mounted1.title'),
this.$locale.baseText('nodeView.showError.mounted1.message') + ':',
@ -3800,7 +3816,7 @@ export default mixins(
);
}
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('nodeView.showError.mounted2.title'),
this.$locale.baseText('nodeView.showError.mounted2.message') + ':',
@ -3831,7 +3847,7 @@ export default mixins(
if (onboardingResponse.title && onboardingResponse.description) {
setTimeout(async () => {
this.$showToast({
this.showToast({
type: 'info',
title: onboardingResponse.title,
message: onboardingResponse.description,

View file

@ -75,22 +75,28 @@
</template>
<script lang="ts">
import { showMessage } from '@/mixins/showMessage';
import { defineComponent } from 'vue';
import type { IUser } from '@/Interface';
import mixins from 'vue-typed-mixins';
import { useToast, useMessage } from '@/composables';
import CopyInput from '@/components/CopyInput.vue';
import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/settings.store';
import { useRootStore } from '@/stores/n8nRoot.store';
import { useUsersStore } from '@/stores/users.store';
import { DOCS_DOMAIN } from '@/constants';
import { DOCS_DOMAIN, MODAL_CONFIRM } from '@/constants';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'SettingsApiView',
components: {
CopyInput,
},
setup() {
return {
...useToast(),
...useMessage(),
};
},
data() {
return {
loading: false,
@ -118,14 +124,15 @@ export default mixins(showMessage).extend({
},
methods: {
async showDeleteModal() {
const confirmed = await this.confirmMessage(
const confirmed = await this.confirm(
this.$locale.baseText('settings.api.delete.description'),
this.$locale.baseText('settings.api.delete.title'),
null,
this.$locale.baseText('settings.api.delete.button'),
this.$locale.baseText('generic.cancel'),
{
confirmButtonText: this.$locale.baseText('settings.api.delete.button'),
cancelButtonText: this.$locale.baseText('generic.cancel'),
},
);
if (confirmed) {
if (confirmed === MODAL_CONFIRM) {
await this.deleteApiKey();
}
},
@ -133,7 +140,7 @@ export default mixins(showMessage).extend({
try {
this.apiKey = (await this.settingsStore.getApiKey()) || '';
} catch (error) {
this.$showError(error, this.$locale.baseText('settings.api.view.error'));
this.showError(error, this.$locale.baseText('settings.api.view.error'));
} finally {
this.mounted = true;
}
@ -144,7 +151,7 @@ export default mixins(showMessage).extend({
try {
this.apiKey = (await this.settingsStore.createApiKey()) || '';
} catch (error) {
this.$showError(error, this.$locale.baseText('settings.api.create.error'));
this.showError(error, this.$locale.baseText('settings.api.create.error'));
} finally {
this.loading = false;
this.$telemetry.track('User clicked create API key button');
@ -153,13 +160,13 @@ export default mixins(showMessage).extend({
async deleteApiKey() {
try {
await this.settingsStore.deleteApiKey();
this.$showMessage({
this.showMessage({
title: this.$locale.baseText('settings.api.delete.toast'),
type: 'success',
});
this.apiKey = '';
} catch (error) {
this.$showError(error, this.$locale.baseText('settings.api.delete.error'));
this.showError(error, this.$locale.baseText('settings.api.delete.error'));
} finally {
this.$telemetry.track('User clicked delete API key button');
}

View file

@ -58,7 +58,7 @@ import {
COMMUNITY_NODES_NPM_INSTALLATION_URL,
} from '@/constants';
import CommunityPackageCard from '@/components/CommunityPackageCard.vue';
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
import { pushConnection } from '@/mixins/pushConnection';
import mixins from 'vue-typed-mixins';
import type { PublicInstalledPackage } from 'n8n-workflow';
@ -70,11 +70,16 @@ import { useSettingsStore } from '@/stores/settings.store';
const PACKAGE_COUNT_THRESHOLD = 31;
export default mixins(showMessage, pushConnection).extend({
export default mixins(pushConnection).extend({
name: 'SettingsCommunityNodesView',
components: {
CommunityPackageCard,
},
setup() {
return {
...useToast(),
};
},
data() {
return {
loading: false,
@ -113,7 +118,7 @@ export default mixins(showMessage, pushConnection).extend({
number_of_updates_available: packagesToUpdate.length,
});
} catch (error) {
this.$showError(
this.showError(
error,
this.$locale.baseText('settings.communityNodes.fetchError.title'),
this.$locale.baseText('settings.communityNodes.fetchError.message'),

View file

@ -143,8 +143,9 @@
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { convertToDisplayDate } from '@/utils';
import { showMessage } from '@/mixins/showMessage';
import { useToast, useMessage } from '@/composables';
import type {
ILdapConfig,
ILdapSyncData,
@ -153,7 +154,7 @@ import type {
IFormInputs,
IUser,
} from '@/Interface';
import mixins from 'vue-typed-mixins';
import { MODAL_CONFIRM } from '@/constants';
import humanizeDuration from 'humanize-duration';
import type { rowCallbackParams, cellCallbackParams } from 'element-ui/types/table';
@ -180,11 +181,17 @@ type rowType = rowCallbackParams & tableRow;
type cellType = cellCallbackParams & { property: keyof tableRow };
export default mixins(showMessage).extend({
export default defineComponent({
name: 'SettingsLdapView',
components: {
InfiniteLoading,
},
setup() {
return {
...useToast(),
...useMessage(),
};
},
data() {
return {
dataTable: [] as ILdapSyncTable[],
@ -301,13 +308,20 @@ export default mixins(showMessage).extend({
try {
if (this.adConfig.loginEnabled === true && newConfiguration.loginEnabled === false) {
saveForm = await this.confirmMessage(
const confirmAction = await this.confirm(
this.$locale.baseText('settings.ldap.confirmMessage.beforeSaveForm.message'),
this.$locale.baseText('settings.ldap.confirmMessage.beforeSaveForm.headline'),
null,
this.$locale.baseText('settings.ldap.confirmMessage.beforeSaveForm.cancelButtonText'),
this.$locale.baseText('settings.ldap.confirmMessage.beforeSaveForm.confirmButtonText'),
{
cancelButtonText: this.$locale.baseText(
'settings.ldap.confirmMessage.beforeSaveForm.cancelButtonText',
),
confirmButtonText: this.$locale.baseText(
'settings.ldap.confirmMessage.beforeSaveForm.confirmButtonText',
),
},
);
saveForm = confirmAction === MODAL_CONFIRM;
}
if (!saveForm) {
@ -315,13 +329,13 @@ export default mixins(showMessage).extend({
}
this.adConfig = await this.settingsStore.updateLdapConfig(newConfiguration);
this.$showToast({
this.showToast({
title: this.$locale.baseText('settings.ldap.updateConfiguration'),
message: '',
type: 'success',
});
} catch (error) {
this.$showError(error, this.$locale.baseText('settings.ldap.configurationError'));
this.showError(error, this.$locale.baseText('settings.ldap.configurationError'));
} finally {
if (saveForm) {
this.hasAnyChanges = false;
@ -335,13 +349,13 @@ export default mixins(showMessage).extend({
this.loadingTestConnection = true;
try {
await this.settingsStore.testLdapConnection();
this.$showToast({
this.showToast({
title: this.$locale.baseText('settings.ldap.connectionTest'),
message: this.$locale.baseText('settings.ldap.toast.connection.success'),
type: 'success',
});
} catch (error) {
this.$showToast({
this.showToast({
title: this.$locale.baseText('settings.ldap.connectionTestError'),
message: error.message,
type: 'error',
@ -354,13 +368,13 @@ export default mixins(showMessage).extend({
this.loadingDryRun = true;
try {
await this.settingsStore.runLdapSync({ type: 'dry' });
this.$showToast({
this.showToast({
title: this.$locale.baseText('settings.ldap.runSync.title'),
message: this.$locale.baseText('settings.ldap.toast.sync.success'),
type: 'success',
});
} catch (error) {
this.$showError(error, this.$locale.baseText('settings.ldap.synchronizationError'));
this.showError(error, this.$locale.baseText('settings.ldap.synchronizationError'));
} finally {
this.loadingDryRun = false;
await this.reloadLdapSynchronizations();
@ -370,13 +384,13 @@ export default mixins(showMessage).extend({
this.loadingLiveRun = true;
try {
await this.settingsStore.runLdapSync({ type: 'live' });
this.$showToast({
this.showToast({
title: this.$locale.baseText('settings.ldap.runSync.title'),
message: this.$locale.baseText('settings.ldap.toast.sync.success'),
type: 'success',
});
} catch (error) {
this.$showError(error, this.$locale.baseText('settings.ldap.synchronizationError'));
this.showError(error, this.$locale.baseText('settings.ldap.synchronizationError'));
} finally {
this.loadingLiveRun = false;
await this.reloadLdapSynchronizations();
@ -669,7 +683,7 @@ export default mixins(showMessage).extend({
},
];
} catch (error) {
this.$showError(error, this.$locale.baseText('settings.ldap.configurationError'));
this.showError(error, this.$locale.baseText('settings.ldap.configurationError'));
}
},
async getLdapSynchronizations(state: any) {
@ -688,7 +702,7 @@ export default mixins(showMessage).extend({
}
this.loadingTable = false;
} catch (error) {
this.$showError(error, this.$locale.baseText('settings.ldap.synchronizationError'));
this.showError(error, this.$locale.baseText('settings.ldap.synchronizationError'));
}
},
async reloadLdapSynchronizations() {
@ -697,7 +711,7 @@ export default mixins(showMessage).extend({
this.tableKey += 1;
this.dataTable = [];
} catch (error) {
this.$showError(error, this.$locale.baseText('settings.ldap.synchronizationError'));
this.showError(error, this.$locale.baseText('settings.ldap.synchronizationError'));
}
},
},

View file

@ -58,18 +58,23 @@
</template>
<script lang="ts">
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
import { CHANGE_PASSWORD_MODAL_KEY } from '@/constants';
import type { IFormInputs, IUser } from '@/Interface';
import { useUIStore } from '@/stores/ui.store';
import { useUsersStore } from '@/stores/users.store';
import { useSettingsStore } from '@/stores/settings.store';
import { mapStores } from 'pinia';
import mixins from 'vue-typed-mixins';
import { defineComponent } from 'vue';
import { createEventBus } from '@/event-bus';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'SettingsPersonalView',
setup() {
return {
...useToast(),
};
},
data() {
return {
hasAnyChanges: false,
@ -154,14 +159,14 @@ export default mixins(showMessage).extend({
lastName: form.lastName,
email: form.email,
});
this.$showToast({
this.showToast({
title: this.$locale.baseText('settings.personal.personalSettingsUpdated'),
message: '',
type: 'success',
});
this.hasAnyChanges = false;
} catch (e) {
this.$showError(e, this.$locale.baseText('settings.personal.personalSettingsUpdatedError'));
this.showError(e, this.$locale.baseText('settings.personal.personalSettingsUpdatedError'));
}
},
onSaveClick() {

View file

@ -61,10 +61,10 @@
<script lang="ts">
import { EnterpriseEditionFeature, INVITE_USER_MODAL_KEY, VIEWS } from '@/constants';
import PageAlert from '../components/PageAlert.vue';
import PageAlert from '@/components/PageAlert.vue';
import type { IUser, IUserListAction } from '@/Interface';
import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
import { copyPaste } from '@/mixins/copyPaste';
import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui.store';
@ -73,11 +73,16 @@ import { useUsersStore } from '@/stores/users.store';
import { useUsageStore } from '@/stores/usage.store';
import { useSSOStore } from '@/stores/sso.store';
export default mixins(showMessage, copyPaste).extend({
export default mixins(copyPaste).extend({
name: 'SettingsUsersView',
components: {
PageAlert,
},
setup() {
return {
...useToast(),
};
},
async mounted() {
if (!this.usersStore.showUMSetupWarning) {
await this.usersStore.fetchUsers();
@ -126,7 +131,7 @@ export default mixins(showMessage, copyPaste).extend({
try {
await this.usersStore.reinviteUser({ id: user.id });
this.$showToast({
this.showToast({
type: 'success',
title: this.$locale.baseText('settings.users.inviteResent'),
message: this.$locale.baseText('settings.users.emailSentTo', {
@ -134,7 +139,7 @@ export default mixins(showMessage, copyPaste).extend({
}),
});
} catch (e) {
this.$showError(e, this.$locale.baseText('settings.users.userReinviteError'));
this.showError(e, this.$locale.baseText('settings.users.userReinviteError'));
}
}
},
@ -143,7 +148,7 @@ export default mixins(showMessage, copyPaste).extend({
if (user?.inviteAcceptUrl) {
this.copyToClipboard(user.inviteAcceptUrl);
this.$showToast({
this.showToast({
type: 'success',
title: this.$locale.baseText('settings.users.inviteUrlCreated'),
message: this.$locale.baseText('settings.users.inviteUrlCreated.message'),

View file

@ -10,22 +10,28 @@
<script lang="ts">
import AuthView from './AuthView.vue';
import { showMessage } from '@/mixins/showMessage';
import { defineComponent } from 'vue';
import mixins from 'vue-typed-mixins';
import { useToast, useMessage } from '@/composables';
import type { IFormBoxConfig } from '@/Interface';
import { VIEWS } from '@/constants';
import { MODAL_CONFIRM, VIEWS } from '@/constants';
import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui.store';
import { useSettingsStore } from '@/stores/settings.store';
import { useUsersStore } from '@/stores/users.store';
import { useCredentialsStore } from '@/stores/credentials.store';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'SetupView',
components: {
AuthView,
},
setup() {
return {
...useToast(),
...useMessage(),
};
},
async mounted() {
const { credentials, workflows } = await this.usersStore.preOwnerSetup();
this.credentialsCount = credentials;
@ -126,17 +132,20 @@ export default mixins(showMessage).extend({
interpolate: { workflows, credentials },
})
: workflows || credentials;
return this.confirmMessage(
const confirm = await this.confirm(
this.$locale.baseText('auth.setup.confirmOwnerSetupMessage', {
interpolate: {
entities,
},
}),
this.$locale.baseText('auth.setup.confirmOwnerSetup'),
null,
this.$locale.baseText('auth.setup.createAccount'),
this.$locale.baseText('auth.setup.goBack'),
{
confirmButtonText: this.$locale.baseText('auth.setup.createAccount'),
cancelButtonText: this.$locale.baseText('auth.setup.goBack'),
},
);
return confirm === MODAL_CONFIRM;
},
async onSubmit(values: { [key: string]: string | boolean }) {
try {
@ -163,19 +172,20 @@ export default mixins(showMessage).extend({
await this.$router.push({ name: VIEWS.USERS_SETTINGS });
}
} catch (error) {
this.$showError(error, this.$locale.baseText('auth.setup.settingUpOwnerError'));
this.showError(error, this.$locale.baseText('auth.setup.settingUpOwnerError'));
}
this.loading = false;
},
async showSkipConfirmation() {
const skip = await this.confirmMessage(
const skip = await this.confirm(
this.$locale.baseText('auth.setup.ownerAccountBenefits'),
this.$locale.baseText('auth.setup.skipOwnerSetupQuestion'),
null,
this.$locale.baseText('auth.setup.skipSetup'),
this.$locale.baseText('auth.setup.goBack'),
{
confirmButtonText: this.$locale.baseText('auth.setup.skipSetup'),
cancelButtonText: this.$locale.baseText('auth.setup.goBack'),
},
);
if (skip) {
if (skip === MODAL_CONFIRM) {
this.onSkip();
}
},

View file

@ -9,21 +9,26 @@
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import AuthView from './AuthView.vue';
import { showMessage } from '@/mixins/showMessage';
import { useToast } from '@/composables';
import mixins from 'vue-typed-mixins';
import type { IFormBoxConfig } from '@/Interface';
import { VIEWS } from '@/constants';
import { mapStores } from 'pinia';
import { useUsersStore } from '@/stores/users.store';
import { useSettingsStore } from '@/stores/settings.store';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'SigninView',
components: {
AuthView,
},
setup() {
return {
...useToast(),
};
},
data() {
return {
FORM_CONFIG: {} as IFormBoxConfig,
@ -97,7 +102,7 @@ export default mixins(showMessage).extend({
await this.$router.push({ name: VIEWS.HOMEPAGE });
} catch (error) {
this.$showError(error, this.$locale.baseText('auth.signin.error'));
this.showError(error, this.$locale.baseText('auth.signin.error'));
this.loading = false;
}
},

View file

@ -2,11 +2,16 @@
import { VIEWS } from '@/constants';
import { mapStores } from 'pinia';
import { useUsersStore } from '@/stores/users.store';
import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage';
import { defineComponent } from 'vue';
import { useToast } from '@/composables';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'SignoutView',
setup() {
return {
...useToast(),
};
},
computed: {
...mapStores(useUsersStore),
},
@ -16,7 +21,7 @@ export default mixins(showMessage).extend({
await this.usersStore.logout();
void this.$router.replace({ name: VIEWS.SIGNIN });
} catch (e) {
this.$showError(e, this.$locale.baseText('auth.signout.error'));
this.showError(e, this.$locale.baseText('auth.signout.error'));
}
},
},

View file

@ -8,21 +8,26 @@
</template>
<script lang="ts">
import AuthView from './AuthView.vue';
import { showMessage } from '@/mixins/showMessage';
import AuthView from '@/views/AuthView.vue';
import { useToast } from '@/composables';
import mixins from 'vue-typed-mixins';
import { defineComponent } from 'vue';
import type { IFormBoxConfig } from '@/Interface';
import { VIEWS } from '@/constants';
import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui.store';
import { useUsersStore } from '@/stores/users.store';
export default mixins(showMessage).extend({
export default defineComponent({
name: 'SignupView',
components: {
AuthView,
},
setup() {
return {
...useToast(),
};
},
data() {
const FORM_CONFIG: IFormBoxConfig = {
title: this.$locale.baseText('auth.signup.setupYourAccount'),
@ -96,7 +101,7 @@ export default mixins(showMessage).extend({
const invite = await this.usersStore.validateSignupToken({ inviteeId, inviterId });
this.inviter = invite.inviter as { firstName: string; lastName: string };
} catch (e) {
this.$showError(e, this.$locale.baseText('auth.signup.tokenValidationError'));
this.showError(e, this.$locale.baseText('auth.signup.tokenValidationError'));
void this.$router.replace({ name: VIEWS.SIGNIN });
}
},
@ -115,7 +120,7 @@ export default mixins(showMessage).extend({
methods: {
async onSubmit(values: { [key: string]: string | boolean }) {
if (!this.inviterId || !this.inviteeId) {
this.$showError(
this.showError(
new Error(this.$locale.baseText('auth.changePassword.tokenValidationError')),
this.$locale.baseText('auth.signup.setupYourAccountError'),
);
@ -144,7 +149,7 @@ export default mixins(showMessage).extend({
await this.$router.push({ name: VIEWS.NEW_WORKFLOW });
} catch (error) {
this.$showError(error, this.$locale.baseText('auth.signup.setupYourAccountError'));
this.showError(error, this.$locale.baseText('auth.signup.setupYourAccountError'));
}
this.loading = false;
},

View file

@ -78,7 +78,7 @@
import CollectionsCarousel from '@/components/CollectionsCarousel.vue';
import TemplateFilters from '@/components/TemplateFilters.vue';
import TemplateList from '@/components/TemplateList.vue';
import TemplatesView from './TemplatesView.vue';
import TemplatesView from '@/views/TemplatesView.vue';
import { genericHelpers } from '@/mixins/genericHelpers';
import type {
@ -97,6 +97,7 @@ import { useSettingsStore } from '@/stores/settings.store';
import { useUsersStore } from '@/stores/users.store';
import { useTemplatesStore } from '@/stores/templates.store';
import { useUIStore } from '@/stores/ui.store';
import { useToast } from '@/composables';
interface ISearchEvent {
search_string: string;
@ -114,6 +115,11 @@ export default mixins(genericHelpers, debounceHelper).extend({
TemplateList,
TemplatesView,
},
setup() {
return {
...useToast(),
};
},
data() {
return {
areCategoriesPrepopulated: false,
@ -287,7 +293,7 @@ export default mixins(genericHelpers, debounceHelper).extend({
search: this.search,
});
} catch (e) {
this.$showMessage({
this.showMessage({
title: 'Error',
message: 'Could not load more workflows',
type: 'error',

View file

@ -89,17 +89,10 @@
</template>
<script lang="ts">
import { showMessage } from '@/mixins/showMessage';
import mixins from 'vue-typed-mixins';
import SettingsView from './SettingsView.vue';
import { defineComponent } from 'vue';
import ResourcesListLayout from '@/components/layouts/ResourcesListLayout.vue';
import PageViewLayout from '@/components/layouts/PageViewLayout.vue';
import PageViewLayoutList from '@/components/layouts/PageViewLayoutList.vue';
import WorkflowCard from '@/components/WorkflowCard.vue';
import TemplateCard from '@/components/TemplateCard.vue';
import { EnterpriseEditionFeature, VIEWS } from '@/constants';
import { debounceHelper } from '@/mixins/debounce';
import type Vue from 'vue';
import type { ITag, IUser, IWorkflowDb } from '@/Interface';
import TagsDropdown from '@/components/TagsDropdown.vue';
@ -118,14 +111,10 @@ const StatusFilter = {
ALL: '',
};
const WorkflowsView = mixins(showMessage, debounceHelper).extend({
const WorkflowsView = defineComponent({
name: 'WorkflowsView',
components: {
ResourcesListLayout,
TemplateCard,
PageViewLayout,
PageViewLayoutList,
SettingsView,
WorkflowCard,
TagsDropdown,
},
@ -157,9 +146,6 @@ const WorkflowsView = mixins(showMessage, debounceHelper).extend({
isShareable(): boolean {
return this.settingsStore.isEnterpriseFeatureEnabled(EnterpriseEditionFeature.Sharing);
},
hasActiveWorkflows(): boolean {
return !!this.workflowsStore.activeWorkflows.length;
},
statusFilterOptions(): Array<{ label: string; value: string | boolean }> {
return [
{