refactor(editor): Apply Prettier (no-changelog) (#4920)

*  Adjust `format` script

* 🔥 Remove exemption for `editor-ui`

* 🎨 Prettify

* 👕 Fix lint
This commit is contained in:
Iván Ovejero
2022-12-14 10:04:10 +01:00
committed by GitHub
parent bcde07e032
commit 5ca2148c7e
284 changed files with 19247 additions and 15540 deletions

View File

@@ -1,10 +1,10 @@
<template>
<div :class="$style.container">
<div :class="$style.logoContainer">
<Logo />
<Logo />
</div>
<div v-if="subtitle" :class="$style.textContainer">
<n8n-text size="large">{{subtitle}}</n8n-text>
<n8n-text size="large">{{ subtitle }}</n8n-text>
</div>
<div :class="$style.formContainer">
<n8n-form-box
@@ -30,8 +30,7 @@ export default Vue.extend({
Logo,
},
props: {
form: {
},
form: {},
formLoading: {
type: Boolean,
default: false,
@@ -41,10 +40,10 @@ export default Vue.extend({
},
},
methods: {
onInput(e: {name: string, value: string}) {
onInput(e: { name: string; value: string }) {
this.$emit('input', e);
},
onSubmit(values: {[key: string]: string}) {
onSubmit(values: { [key: string]: string }) {
this.$emit('submit', values);
},
onSecondaryClick() {
@@ -86,9 +85,7 @@ body {
</style>
<style lang="scss">
.el-checkbox__label span {
font-size: var(--font-size-2xs) !important;
}
</style>

View File

@@ -1,6 +1,18 @@
<template>
<div :class="$style.container" :style="containerCssVars" ref="container" data-test-id="canvas-add-button">
<n8n-tooltip placement="top" :value="showTooltip" manual :disabled="nodeCreatorStore.showScrim" :popper-class="$style.tooltip" :open-delay="700">
<div
:class="$style.container"
:style="containerCssVars"
ref="container"
data-test-id="canvas-add-button"
>
<n8n-tooltip
placement="top"
:value="showTooltip"
manual
:disabled="nodeCreatorStore.showScrim"
:popper-class="$style.tooltip"
:open-delay="700"
>
<button :class="$style.button" @click="$emit('click')" data-test-id="canvas-plus-button">
<font-awesome-icon icon="plus" size="lg" />
</button>
@@ -47,7 +59,7 @@ const containerCssVars = computed(() => ({
z-index: 101;
&:hover .button svg path {
fill: var(--color-primary)
fill: var(--color-primary);
}
}
@@ -65,7 +77,7 @@ const containerCssVars = computed(() => ({
width: 26px !important;
height: 40px;
path {
fill: var(--color-foreground-xdark)
fill: var(--color-foreground-xdark);
}
}
}
@@ -78,7 +90,7 @@ const containerCssVars = computed(() => ({
width: max-content;
font-weight: var(--font-weight-bold);
font-size: var(--font-size-m);
line-height: var(--font-line-height-xloose );
line-height: var(--font-line-height-xloose);
color: var(--color-text-dark);
margin-top: var(--spacing-2xs);
}

View File

@@ -18,9 +18,7 @@ import { VIEWS } from '@/constants';
import { mapStores } from 'pinia';
import { useUsersStore } from '@/stores/users';
export default mixins(
showMessage,
).extend({
export default mixins(showMessage).extend({
name: 'ChangePasswordView',
components: {
AuthView,
@@ -48,7 +46,7 @@ export default mixins(
label: this.$locale.baseText('auth.newPassword'),
type: 'password',
required: true,
validationRules: [{name: 'DEFAULT_PASSWORD_RULES'}],
validationRules: [{ name: 'DEFAULT_PASSWORD_RULES' }],
infoText: this.$locale.baseText('auth.defaultPasswordRequirements'),
autocomplete: 'new-password',
capitalize: true,
@@ -65,15 +63,21 @@ export default mixins(
validate: this.passwordsMatch,
},
},
validationRules: [{name: 'TWO_PASSWORDS_MATCH'}],
validationRules: [{ name: 'TWO_PASSWORDS_MATCH' }],
autocomplete: 'new-password',
capitalize: true,
},
},
],
};
const token = (!this.$route.query.token || typeof this.$route.query.token !== 'string') ? null : this.$route.query.token;
const userId = (!this.$route.query.userId || typeof this.$route.query.userId !== 'string') ? null : this.$route.query.userId;
const token =
!this.$route.query.token || typeof this.$route.query.token !== 'string'
? null
: this.$route.query.token;
const userId =
!this.$route.query.userId || typeof this.$route.query.userId !== 'string'
? null
: this.$route.query.userId;
try {
if (!token) {
throw new Error(this.$locale.baseText('auth.changePassword.missingTokenError'));
@@ -84,7 +88,10 @@ export default mixins(
await this.usersStore.validatePasswordToken({ token, userId });
} catch (e) {
this.$showMessage({title: this.$locale.baseText('auth.changePassword.tokenValidationError'), type: 'error'});
this.$showMessage({
title: this.$locale.baseText('auth.changePassword.tokenValidationError'),
type: 'error',
});
}
},
methods: {
@@ -101,7 +108,7 @@ export default mixins(
return false;
},
onInput(e: {name: string, value: string}) {
onInput(e: { name: string; value: string }) {
if (e.name === 'password') {
this.password = e.value;
}
@@ -109,11 +116,17 @@ export default mixins(
async onSubmit() {
try {
this.loading = true;
const token = (!this.$route.query.token || typeof this.$route.query.token !== 'string') ? null : this.$route.query.token;
const userId = (!this.$route.query.userId || typeof this.$route.query.userId !== 'string') ? null : this.$route.query.userId;
const token =
!this.$route.query.token || typeof this.$route.query.token !== 'string'
? null
: this.$route.query.token;
const userId =
!this.$route.query.userId || typeof this.$route.query.userId !== 'string'
? null
: this.$route.query.userId;
if (token && userId) {
await this.usersStore.changePassword({token, userId, password: this.password});
await this.usersStore.changePassword({ token, userId, password: this.password });
this.$showMessage({
type: 'success',
@@ -123,7 +136,10 @@ export default mixins(
await this.$router.push({ name: VIEWS.SIGNIN });
} else {
this.$showError(new Error(this.$locale.baseText('auth.validation.missingParameters')), this.$locale.baseText('auth.changePassword.error'));
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'));

View File

@@ -10,7 +10,7 @@
@update:filters="filters = $event"
>
<template #default="{ data }">
<credential-card :data="data"/>
<credential-card :data="data" />
</template>
<template #filters="{ setKeyValue }">
<div class="mb-s">
@@ -43,22 +43,22 @@
</template>
<script lang="ts">
import {showMessage} from '@/mixins/showMessage';
import {ICredentialsResponse, ICredentialTypeMap, IUser} from '@/Interface';
import { showMessage } from '@/mixins/showMessage';
import { ICredentialsResponse, ICredentialTypeMap, IUser } from '@/Interface';
import mixins from 'vue-typed-mixins';
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 {ICredentialType} from "n8n-workflow";
import TemplateCard from "@/components/TemplateCard.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 { 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 Vue from "vue";
import ResourceOwnershipSelect from '@/components/forms/ResourceOwnershipSelect.ee.vue';
import ResourceFiltersDropdown from '@/components/forms/ResourceFiltersDropdown.vue';
import { CREDENTIAL_SELECT_MODAL_KEY } from '@/constants';
import Vue from 'vue';
import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui';
import { useUsersStore } from '@/stores/users';
@@ -67,10 +67,7 @@ import { useCredentialsStore } from '@/stores/credentials';
type IResourcesListLayoutInstance = Vue & { sendFiltersTelemetry: (source: string) => void };
export default mixins(
showMessage,
debounceHelper,
).extend({
export default mixins(showMessage, debounceHelper).extend({
name: 'SettingsPersonalView',
components: {
ResourcesListLayout,
@@ -93,12 +90,7 @@ export default mixins(
};
},
computed: {
...mapStores(
useCredentialsStore,
useNodeTypesStore,
useUIStore,
useUsersStore,
),
...mapStores(useCredentialsStore, useNodeTypesStore, useUIStore, useUsersStore),
allCredentials(): ICredentialsResponse[] {
return this.credentialsStore.allCredentials;
},
@@ -118,7 +110,6 @@ export default mixins(
});
},
async initialize() {
const loadPromises = [
this.credentialsStore.fetchAllCredentials(),
this.credentialsStore.fetchCredentialTypes(false),
@@ -132,7 +123,11 @@ export default mixins(
this.usersStore.fetchUsers(); // Can be loaded in the background, used for filtering
},
onFilter(resource: ICredentialsResponse, filters: { type: string[]; search: string; }, matches: boolean): boolean {
onFilter(
resource: ICredentialsResponse,
filters: { type: string[]; search: string },
matches: boolean,
): boolean {
if (filters.type.length > 0) {
matches = matches && filters.type.includes(resource.type);
}
@@ -140,9 +135,12 @@ export default mixins(
if (filters.search) {
const searchString = filters.search.toLowerCase();
matches = matches || (
this.credentialTypesById[resource.type] && this.credentialTypesById[resource.type].displayName.toLowerCase().includes(searchString)
);
matches =
matches ||
(this.credentialTypesById[resource.type] &&
this.credentialTypesById[resource.type].displayName
.toLowerCase()
.includes(searchString));
}
return matches;
@@ -168,4 +166,3 @@ export default mixins(
padding: 0 !important;
}
</style>

View File

@@ -9,14 +9,11 @@
</div>
<div>
<n8n-text size="large" v-if="errorCode">
{{errorCode}} {{ $locale.baseText('error') }}
{{ errorCode }} {{ $locale.baseText('error') }}
</n8n-text>
</div>
</div>
<n8n-button
:label="$locale.baseText(redirectTextKey)"
@click="onButtonClick"
/>
<n8n-button :label="$locale.baseText(redirectTextKey)" @click="onButtonClick" />
</div>
</template>

View File

@@ -1,9 +1,5 @@
<template>
<AuthView
:form="formConfig"
:formLoading="loading"
@submit="onSubmit"
/>
<AuthView :form="formConfig" :formLoading="loading" @submit="onSubmit" />
</template>
<script lang="ts">
@@ -16,9 +12,7 @@ import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/settings';
import { useUsersStore } from '@/stores/users';
export default mixins(
showMessage,
).extend({
export default mixins(showMessage).extend({
name: 'ForgotMyPasswordView',
components: {
AuthView,
@@ -29,10 +23,7 @@ export default mixins(
};
},
computed: {
...mapStores(
useSettingsStore,
useUsersStore,
),
...mapStores(useSettingsStore, useUsersStore),
formConfig(): IFormBoxConfig {
const EMAIL_INPUTS: IFormBoxConfig['inputs'] = [
{
@@ -41,7 +32,7 @@ export default mixins(
label: this.$locale.baseText('auth.email'),
type: 'email',
required: true,
validationRules: [{name: 'VALID_EMAIL'}],
validationRules: [{ name: 'VALID_EMAIL' }],
autocomplete: 'email',
capitalize: true,
},
@@ -86,10 +77,9 @@ export default mixins(
this.$showMessage({
type: 'success',
title: this.$locale.baseText('forgotPassword.recoveryEmailSent'),
message: this.$locale.baseText(
'forgotPassword.emailSentIfExists',
{ interpolate: { email: values.email }},
),
message: this.$locale.baseText('forgotPassword.emailSentIfExists', {
interpolate: { email: values.email },
}),
});
} catch (error) {
this.$showMessage({

View File

@@ -1,5 +1,5 @@
<template>
<div :class="$style.wrapper" data-test-id="node-view-loader">
<div :class="$style.wrapper" data-test-id="node-view-loader">
<div :class="$style.spinner">
<n8n-spinner />
</div>

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
<div :class="$style.header">
<n8n-heading size="2xlarge">
{{ $locale.baseText('settings.api') }}
<span :style="{ fontSize: 'var(--font-size-s)', color: 'var(--color-text-light)', }">
<span :style="{ fontSize: 'var(--font-size-s)', color: 'var(--color-text-light)' }">
({{ $locale.baseText('beta') }})
</span>
</n8n-heading>
@@ -57,7 +57,11 @@
</div>
<n8n-action-box
v-else-if="mounted"
:buttonText="$locale.baseText(loading ? 'settings.api.create.button.loading' : 'settings.api.create.button')"
:buttonText="
$locale.baseText(
loading ? 'settings.api.create.button.loading' : 'settings.api.create.button',
)
"
:description="$locale.baseText('settings.api.create.description')"
@click="createApiKey"
/>
@@ -75,9 +79,7 @@ import { useSettingsStore } from '@/stores/settings';
import { useRootStore } from '@/stores/n8nRootStore';
import { useUsersStore } from '@/stores/users';
export default mixins(
showMessage,
).extend({
export default mixins(showMessage).extend({
name: 'SettingsPersonalView',
components: {
CopyInput,
@@ -98,11 +100,7 @@ export default mixins(
this.apiPlaygroundPath = `${baseUrl}${apiPath}/v${latestVersion}/docs`;
},
computed: {
...mapStores(
useRootStore,
useSettingsStore,
useUsersStore,
),
...mapStores(useRootStore, useSettingsStore, useUsersStore),
currentUser(): IUser | null {
return this.usersStore.currentUser;
},
@@ -122,7 +120,7 @@ export default mixins(
},
async getApiKey() {
try {
this.apiKey = await this.settingsStore.getApiKey() || '';
this.apiKey = (await this.settingsStore.getApiKey()) || '';
} catch (error) {
this.$showError(error, this.$locale.baseText('settings.api.view.error'));
} finally {
@@ -133,7 +131,7 @@ export default mixins(
this.loading = true;
try {
this.apiKey = await this.settingsStore.createApiKey() || '';
this.apiKey = (await this.settingsStore.createApiKey()) || '';
} catch (error) {
this.$showError(error, this.$locale.baseText('settings.api.create.error'));
} finally {
@@ -144,7 +142,10 @@ export default mixins(
async deleteApiKey() {
try {
await this.settingsStore.deleteApiKey();
this.$showMessage({ title: this.$locale.baseText("settings.api.delete.toast"), type: 'success' });
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'));
@@ -191,4 +192,3 @@ export default mixins(
color: var(--color-text-light);
}
</style>

View File

@@ -3,7 +3,11 @@
<div :class="$style.headingContainer">
<n8n-heading size="2xlarge">{{ $locale.baseText('settings.communityNodes') }}</n8n-heading>
<n8n-button
v-if="!settingsStore.isQueueModeEnabled && communityNodesStore.getInstalledPackages.length > 0 && !loading"
v-if="
!settingsStore.isQueueModeEnabled &&
communityNodesStore.getInstalledPackages.length > 0 &&
!loading
"
:label="$locale.baseText('settings.communityNodes.installModal.installButton.label')"
size="large"
@click="openInstallModal"
@@ -17,10 +21,7 @@
:calloutTheme="actionBoxConfig.calloutTheme"
/>
</div>
<div
:class="$style.cardsContainer"
v-else-if="loading"
>
<div :class="$style.cardsContainer" v-else-if="loading">
<community-package-card
v-for="n in 2"
:key="'index-' + n"
@@ -44,10 +45,7 @@
@click="openInstallModal"
/>
</div>
<div
:class="$style.cardsContainer"
v-else
>
<div :class="$style.cardsContainer" v-else>
<community-package-card
v-for="communityPackage in communityNodesStore.getInstalledPackages"
:key="communityPackage.packageName"
@@ -75,14 +73,12 @@ import { useSettingsStore } from '@/stores/settings';
const PACKAGE_COUNT_THRESHOLD = 31;
export default mixins(
showMessage,
).extend({
export default mixins(showMessage).extend({
name: 'SettingsCommunityNodesView',
components: {
CommunityPackageCard,
},
data () {
data() {
return {
loading: false,
};
@@ -92,19 +88,22 @@ export default mixins(
this.$data.loading = true;
await this.communityNodesStore.fetchInstalledPackages();
const installedPackages: PublicInstalledPackage[] = this.communityNodesStore.getInstalledPackages;
const packagesToUpdate: PublicInstalledPackage[] = installedPackages.filter(p => p.updateAvailable );
const installedPackages: PublicInstalledPackage[] =
this.communityNodesStore.getInstalledPackages;
const packagesToUpdate: PublicInstalledPackage[] = installedPackages.filter(
(p) => p.updateAvailable,
);
this.$telemetry.track('user viewed cnr settings page', {
num_of_packages_installed: installedPackages.length,
installed_packages: installedPackages.map(p => {
installed_packages: installedPackages.map((p) => {
return {
package_name: p.packageName,
package_version: p.installedVersion,
package_nodes: p.installedNodes.map(node => `${node.name}-v${node.latestVersion}`),
package_nodes: p.installedNodes.map((node) => `${node.name}-v${node.latestVersion}`),
is_update_available: p.updateAvailable !== undefined,
};
}),
packages_to_update: packagesToUpdate.map(p => {
packages_to_update: packagesToUpdate.map((p) => {
return {
package_name: p.packageName,
package_version_current: p.installedVersion,
@@ -129,25 +128,21 @@ export default mixins(
}
},
computed: {
...mapStores(
useCommunityNodesStore,
useSettingsStore,
useUIStore,
),
...mapStores(useCommunityNodesStore, useSettingsStore, useUIStore),
getEmptyStateDescription() {
const packageCount = this.communityNodesStore.availablePackageCount;
return packageCount < PACKAGE_COUNT_THRESHOLD ?
this.$locale.baseText('settings.communityNodes.empty.description.no-packages', {
interpolate: {
docURL: COMMUNITY_NODES_INSTALLATION_DOCS_URL,
},
}) :
this.$locale.baseText('settings.communityNodes.empty.description', {
interpolate: {
docURL: COMMUNITY_NODES_INSTALLATION_DOCS_URL,
count: (Math.floor(packageCount / 10) * 10).toString(),
},
});
return packageCount < PACKAGE_COUNT_THRESHOLD
? this.$locale.baseText('settings.communityNodes.empty.description.no-packages', {
interpolate: {
docURL: COMMUNITY_NODES_INSTALLATION_DOCS_URL,
},
})
: this.$locale.baseText('settings.communityNodes.empty.description', {
interpolate: {
docURL: COMMUNITY_NODES_INSTALLATION_DOCS_URL,
count: (Math.floor(packageCount / 10) * 10).toString(),
},
});
},
shouldShowInstallButton() {
return !this.settingsStore.isDesktopDeployment && this.settingsStore.isNpmAvailable;
@@ -163,10 +158,9 @@ export default mixins(
if (!this.settingsStore.isNpmAvailable) {
return {
calloutText: this.$locale.baseText(
'settings.communityNodes.npmUnavailable.warning',
{ interpolate: { npmUrl: COMMUNITY_NODES_NPM_INSTALLATION_URL } },
),
calloutText: this.$locale.baseText('settings.communityNodes.npmUnavailable.warning', {
interpolate: { npmUrl: COMMUNITY_NODES_NPM_INSTALLATION_URL },
}),
calloutTheme: 'warning',
hideButton: true,
};
@@ -174,10 +168,9 @@ export default mixins(
if (this.settingsStore.isQueueModeEnabled) {
return {
calloutText: this.$locale.baseText(
'settings.communityNodes.queueMode.warning',
{ interpolate: { docURL: COMMUNITY_NODES_INSTALLATION_DOCS_URL } },
),
calloutText: this.$locale.baseText('settings.communityNodes.queueMode.warning', {
interpolate: { docURL: COMMUNITY_NODES_INSTALLATION_DOCS_URL },
}),
calloutTheme: 'warning',
hideButton: true,
};
@@ -192,7 +185,9 @@ export default mixins(
},
methods: {
openInstallModal(event: MouseEvent) {
const telemetryPayload = { is_empty_state: this.communityNodesStore.getInstalledPackages.length === 0 };
const telemetryPayload = {
is_empty_state: this.communityNodesStore.getInstalledPackages.length === 0,
};
this.$telemetry.track('user clicked cnr install button', telemetryPayload);
this.$externalHooks().run('settingsCommunityNodesView.openInstallModal', telemetryPayload);
this.uiStore.openModal(COMMUNITY_PACKAGE_INSTALL_MODAL_KEY);
@@ -202,31 +197,31 @@ export default mixins(
</script>
<style lang="scss" module>
.container {
height: 100%;
padding-right: var(--spacing-2xs);
> * {
margin-bottom: var(--spacing-2xl);
}
.container {
height: 100%;
padding-right: var(--spacing-2xs);
> * {
margin-bottom: var(--spacing-2xl);
}
}
.headingContainer {
display: flex;
justify-content: space-between;
}
.headingContainer {
display: flex;
justify-content: space-between;
}
.loadingContainer {
display: flex;
gap: var(--spacing-xs);
}
.loadingContainer {
display: flex;
gap: var(--spacing-xs);
}
.actionBoxContainer {
text-align: center;
}
.actionBoxContainer {
text-align: center;
}
.cardsContainer {
display: flex;
flex-direction: column;
gap: var(--spacing-2xs);
}
.cardsContainer {
display: flex;
flex-direction: column;
gap: var(--spacing-2xs);
}
</style>

View File

@@ -22,7 +22,7 @@ export default Vue.extend({
},
computed: {
...mapStores(useUIStore),
featureInfo(): IFakeDoor|undefined {
featureInfo(): IFakeDoor | undefined {
return this.uiStore.getFakeDoorById(this.featureId);
},
},

View File

@@ -1,17 +1,25 @@
<template>
<div :class="$style.container">
<div :class="$style.header">
<n8n-heading size="2xlarge">{{ $locale.baseText('settings.personal.personalSettings') }}</n8n-heading>
<n8n-heading size="2xlarge">{{
$locale.baseText('settings.personal.personalSettings')
}}</n8n-heading>
<div class="ph-no-capture" :class="$style.user">
<span :class="$style.username">
<n8n-text color="text-light">{{currentUser.fullName}}</n8n-text>
<n8n-text color="text-light">{{ currentUser.fullName }}</n8n-text>
</span>
<n8n-avatar :firstName="currentUser.firstName" :lastName="currentUser.lastName" size="large" />
<n8n-avatar
:firstName="currentUser.firstName"
:lastName="currentUser.lastName"
size="large"
/>
</div>
</div>
<div>
<div :class="$style.sectionHeader">
<n8n-heading size="large">{{ $locale.baseText('settings.personal.basicInformation') }}</n8n-heading>
<n8n-heading size="large">{{
$locale.baseText('settings.personal.basicInformation')
}}</n8n-heading>
</div>
<div>
<n8n-form-inputs
@@ -30,15 +38,22 @@
</div>
<div>
<n8n-input-label :label="$locale.baseText('auth.password')">
<n8n-link @click="openPasswordModal">{{ $locale.baseText('auth.changePassword') }}</n8n-link>
<n8n-link @click="openPasswordModal">{{
$locale.baseText('auth.changePassword')
}}</n8n-link>
</n8n-input-label>
</div>
</div>
<div>
<n8n-button float="right" :label="$locale.baseText('settings.personal.save')" size="large" :disabled="!hasAnyChanges || !readyToSubmit" @click="onSaveClick" />
<n8n-button
float="right"
:label="$locale.baseText('settings.personal.save')"
size="large"
:disabled="!hasAnyChanges || !readyToSubmit"
@click="onSaveClick"
/>
</div>
</div>
</template>
<script lang="ts">
@@ -51,9 +66,7 @@ import { mapStores } from 'pinia';
import Vue from 'vue';
import mixins from 'vue-typed-mixins';
export default mixins(
showMessage,
).extend({
export default mixins(showMessage).extend({
name: 'SettingsPersonalView',
data() {
return {
@@ -94,7 +107,7 @@ export default mixins(
label: this.$locale.baseText('auth.email'),
type: 'email',
required: true,
validationRules: [{name: 'VALID_EMAIL'}],
validationRules: [{ name: 'VALID_EMAIL' }],
autocomplete: 'email',
capitalize: true,
},
@@ -102,10 +115,7 @@ export default mixins(
];
},
computed: {
...mapStores(
useUIStore,
useUsersStore,
),
...mapStores(useUIStore, useUsersStore),
currentUser(): IUser | null {
return this.usersStore.currentUser;
},
@@ -117,7 +127,7 @@ export default mixins(
onReadyToSubmit(ready: boolean) {
this.readyToSubmit = ready;
},
async onSubmit(form: {firstName: string, lastName: string, email: string}) {
async onSubmit(form: { firstName: string; lastName: string; email: string }) {
if (!this.hasAnyChanges || !this.usersStore.currentUserId) {
return;
}
@@ -134,8 +144,7 @@ export default mixins(
type: 'success',
});
this.hasAnyChanges = false;
}
catch (e) {
} catch (e) {
this.$showError(e, this.$locale.baseText('settings.personal.personalSettingsUpdatedError'));
}
},
@@ -176,7 +185,6 @@ export default mixins(
}
}
.username {
margin-right: var(--spacing-s);
text-align: right;
@@ -192,4 +200,3 @@ export default mixins(
margin-bottom: var(--spacing-s);
}
</style>

View File

@@ -3,22 +3,27 @@
<div>
<n8n-heading size="2xlarge">{{ $locale.baseText('settings.users') }}</n8n-heading>
<div :class="$style.buttonContainer" v-if="!usersStore.showUMSetupWarning">
<n8n-tooltip :disabled="settingsStore.isSmtpSetup" placement="bottom">
<template #content>
<i18n path="settings.users.setupSMTPToInviteUsers" tag="span">
<template #action>
<a
href="https://docs.n8n.io/reference/user-management.html#step-one-smtp"
target="_blank"
v-text="$locale.baseText('settings.users.setupSMTPToInviteUsers.instructions')"
/>
</template>
</i18n>
</template>
<div>
<n8n-button :label="$locale.baseText('settings.users.invite')" @click="onInvite" size="large" :disabled="!settingsStore.isSmtpSetup" />
</div>
</n8n-tooltip>
<n8n-tooltip :disabled="settingsStore.isSmtpSetup" placement="bottom">
<template #content>
<i18n path="settings.users.setupSMTPToInviteUsers" tag="span">
<template #action>
<a
href="https://docs.n8n.io/reference/user-management.html#step-one-smtp"
target="_blank"
v-text="$locale.baseText('settings.users.setupSMTPToInviteUsers.instructions')"
/>
</template>
</i18n>
</template>
<div>
<n8n-button
:label="$locale.baseText('settings.users.invite')"
@click="onInvite"
size="large"
:disabled="!settingsStore.isSmtpSetup"
/>
</div>
</n8n-tooltip>
</div>
</div>
<div v-if="usersStore.showUMSetupWarning" :class="$style.setupInfoContainer">
@@ -35,7 +40,12 @@
:message="$locale.baseText('settings.users.smtpToAddUsersWarning')"
:popupClass="$style.alert"
/>
<n8n-users-list :users="usersStore.allUsers" :currentUserId="usersStore.currentUserId" @delete="onDelete" @reinvite="onReinvite" />
<n8n-users-list
:users="usersStore.allUsers"
:currentUserId="usersStore.currentUserId"
@delete="onDelete"
@reinvite="onReinvite"
/>
</div>
</div>
</template>
@@ -63,15 +73,11 @@ export default mixins(showMessage).extend({
}
},
computed: {
...mapStores(
useSettingsStore,
useUIStore,
useUsersStore,
),
...mapStores(useSettingsStore, useUIStore, useUsersStore),
},
methods: {
redirectToSetup() {
this.$router.push({name: VIEWS.SETUP});
this.$router.push({ name: VIEWS.SETUP });
},
onInvite() {
this.uiStore.openModal(INVITE_USER_MODAL_KEY);
@@ -91,10 +97,9 @@ export default mixins(showMessage).extend({
this.$showToast({
type: 'success',
title: this.$locale.baseText('settings.users.inviteResent'),
message: this.$locale.baseText(
'settings.users.emailSentTo',
{ interpolate: { email: user.email || '' } },
),
message: this.$locale.baseText('settings.users.emailSentTo', {
interpolate: { email: user.email || '' },
}),
});
} catch (e) {
this.$showError(e, this.$locale.baseText('settings.users.userReinviteError'));
@@ -136,5 +141,4 @@ export default mixins(showMessage).extend({
.alert {
left: calc(50% + 100px);
}
</style>

View File

@@ -26,7 +26,7 @@ const SettingsView = defineComponent({
SettingsSidebar,
},
beforeRouteEnter(to, from, next) {
next(vm => {
next((vm) => {
(vm as unknown as InstanceType<typeof SettingsView>).previousRoute = from;
});
},

View File

@@ -22,11 +22,7 @@ import { useSettingsStore } from '@/stores/settings';
import { useUsersStore } from '@/stores/users';
import { useCredentialsStore } from '@/stores/credentials';
export default mixins(
showMessage,
restApi,
).extend({
export default mixins(showMessage, restApi).extend({
name: 'SetupView',
components: {
AuthView,
@@ -103,12 +99,7 @@ export default mixins(
};
},
computed: {
...mapStores(
useCredentialsStore,
useSettingsStore,
useUIStore,
useUsersStore,
),
...mapStores(useCredentialsStore, useSettingsStore, useUIStore, useUsersStore),
},
methods: {
async getAllCredentials() {
@@ -124,21 +115,26 @@ export default mixins(
return true;
}
const workflows = this.workflowsCount > 0
? this.$locale.baseText(
'auth.setup.setupConfirmation.existingWorkflows',
{ adjustToNumber: this.workflowsCount },
)
: '';
const workflows =
this.workflowsCount > 0
? this.$locale.baseText('auth.setup.setupConfirmation.existingWorkflows', {
adjustToNumber: this.workflowsCount,
})
: '';
const credentials = this.credentialsCount > 0
? this.$locale.baseText(
'auth.setup.setupConfirmation.credentials',
{ adjustToNumber: this.credentialsCount },
)
: '';
const credentials =
this.credentialsCount > 0
? this.$locale.baseText('auth.setup.setupConfirmation.credentials', {
adjustToNumber: this.credentialsCount,
})
: '';
const entities = workflows && credentials ? this.$locale.baseText('auth.setup.setupConfirmation.concatEntities', {interpolate: { workflows, credentials }}) : (workflows || credentials);
const entities =
workflows && credentials
? this.$locale.baseText('auth.setup.setupConfirmation.concatEntities', {
interpolate: { workflows, credentials },
})
: workflows || credentials;
return await this.confirmMessage(
this.$locale.baseText('auth.setup.confirmOwnerSetupMessage', {
interpolate: {
@@ -151,7 +147,7 @@ export default mixins(
this.$locale.baseText('auth.setup.goBack'),
);
},
async onSubmit(values: {[key: string]: string | boolean}) {
async onSubmit(values: { [key: string]: string | boolean }) {
try {
const confirmSetup = await this.confirmSetupOrGoBack();
if (!confirmSetup) {
@@ -160,21 +156,21 @@ export default mixins(
const forceRedirectedHere = this.settingsStore.showSetupPage;
this.loading = true;
await this.usersStore.createOwner(values as { firstName: string; lastName: string; email: string; password: string;});
await this.usersStore.createOwner(
values as { firstName: string; lastName: string; email: string; password: string },
);
if (values.agree === true) {
try {
await this.uiStore.submitContactEmail(values.email.toString(), values.agree);
} catch { }
} catch {}
}
if (forceRedirectedHere) {
await this.$router.push({ name: VIEWS.HOMEPAGE });
}
else {
} else {
await this.$router.push({ name: VIEWS.USERS_SETTINGS });
}
} catch (error) {
this.$showError(error, this.$locale.baseText('auth.setup.settingUpOwnerError'));
}

View File

@@ -17,9 +17,7 @@ import { VIEWS } from '@/constants';
import { mapStores } from 'pinia';
import { useUsersStore } from '@/stores/users';
export default mixins(
showMessage,
).extend({
export default mixins(showMessage).extend({
name: 'SigninView',
components: {
AuthView,
@@ -68,16 +66,17 @@ export default mixins(
...mapStores(useUsersStore),
},
methods: {
async onSubmit(values: {[key: string]: string}) {
async onSubmit(values: { [key: string]: string }) {
try {
this.loading = true;
await this.usersStore.loginWithCreds(values as {email: string, password: string});
await this.usersStore.loginWithCreds(values as { email: string; password: string });
this.clearAllStickyNotifications();
this.loading = false;
if (typeof this.$route.query.redirect === 'string') {
const redirect = decodeURIComponent(this.$route.query.redirect);
if (redirect.startsWith('/')) { // protect against phishing
if (redirect.startsWith('/')) {
// protect against phishing
this.$router.push(redirect);
return;

View File

@@ -18,9 +18,7 @@ import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui';
import { useUsersStore } from '@/stores/users';
export default mixins(
showMessage,
).extend({
export default mixins(showMessage).extend({
name: 'SignupView',
components: {
AuthView,
@@ -74,14 +72,20 @@ export default mixins(
return {
FORM_CONFIG,
loading: false,
inviter: null as null | {firstName: string, lastName: string},
inviter: null as null | { firstName: string; lastName: string },
inviterId: null as string | null,
inviteeId: null as string | null,
};
},
async mounted() {
const inviterId = (!this.$route.query.inviterId || typeof this.$route.query.inviterId !== 'string') ? null : this.$route.query.inviterId;
const inviteeId = (!this.$route.query.inviteeId || typeof this.$route.query.inviteeId !== 'string') ? null : this.$route.query.inviteeId;
const inviterId =
!this.$route.query.inviterId || typeof this.$route.query.inviterId !== 'string'
? null
: this.$route.query.inviterId;
const inviteeId =
!this.$route.query.inviteeId || typeof this.$route.query.inviteeId !== 'string'
? null
: this.$route.query.inviteeId;
try {
if (!inviterId || !inviteeId) {
throw new Error(this.$locale.baseText('auth.signup.missingTokenError'));
@@ -90,43 +94,52 @@ export default mixins(
this.inviteeId = inviteeId;
const invite = await this.usersStore.validateSignupToken({ inviteeId, inviterId });
this.inviter = invite.inviter as {firstName: string, lastName: string};
this.inviter = invite.inviter as { firstName: string; lastName: string };
} catch (e) {
this.$showError(e, this.$locale.baseText('auth.signup.tokenValidationError'));
this.$router.replace({name: VIEWS.SIGNIN});
this.$router.replace({ name: VIEWS.SIGNIN });
}
},
computed: {
...mapStores(
useUIStore,
useUsersStore,
),
...mapStores(useUIStore, useUsersStore),
inviteMessage(): null | string {
if (!this.inviter) {
return null;
}
return this.$locale.baseText(
'settings.signup.signUpInviterInfo',
{ interpolate: { firstName: this.inviter.firstName, lastName: this.inviter.lastName }},
);
return this.$locale.baseText('settings.signup.signUpInviterInfo', {
interpolate: { firstName: this.inviter.firstName, lastName: this.inviter.lastName },
});
},
},
methods: {
async onSubmit(values: {[key: string]: string | boolean}) {
async onSubmit(values: { [key: string]: string | boolean }) {
if (!this.inviterId || !this.inviteeId) {
this.$showError(new Error(this.$locale.baseText('auth.changePassword.tokenValidationError')), this.$locale.baseText('auth.signup.setupYourAccountError'));
this.$showError(
new Error(this.$locale.baseText('auth.changePassword.tokenValidationError')),
this.$locale.baseText('auth.signup.setupYourAccountError'),
);
return;
}
try {
this.loading = true;
await this.usersStore.signup({...values, inviterId: this.inviterId, inviteeId: this.inviteeId} as { inviteeId: string; inviterId: string; firstName: string; lastName: string; password: string;});
await this.usersStore.signup({
...values,
inviterId: this.inviterId,
inviteeId: this.inviteeId,
} as {
inviteeId: string;
inviterId: string;
firstName: string;
lastName: string;
password: string;
});
if (values.agree === true) {
try {
await this.uiStore.submitContactEmail(values.email.toString(), values.agree);
} catch { }
} catch {}
}
await this.$router.push({ name: VIEWS.HOMEPAGE });

View File

@@ -13,7 +13,9 @@
</div>
</div>
<div :class="$style.notFound" v-else>
<n8n-text color="text-base">{{ $locale.baseText('templates.collectionsNotFound') }}</n8n-text>
<n8n-text color="text-base">{{
$locale.baseText('templates.collectionsNotFound')
}}</n8n-text>
</div>
</template>
<template v-if="!notFoundError" #content>
@@ -74,9 +76,7 @@ export default mixins(workflowHelpers).extend({
TemplatesView,
},
computed: {
...mapStores(
useTemplatesStore,
),
...mapStores(useTemplatesStore),
collection(): null | ITemplatesCollectionFull {
return this.templatesStore.getCollectionById(this.collectionId);
},
@@ -110,10 +110,10 @@ export default mixins(workflowHelpers).extend({
}
}, 50);
},
onOpenTemplate({event, id}: {event: MouseEvent, id: string}) {
onOpenTemplate({ event, id }: { event: MouseEvent; id: string }) {
this.navigateTo(event, VIEWS.TEMPLATE, id);
},
onUseWorkflow({event, id}: {event: MouseEvent, id: string}) {
onUseWorkflow({ event, id }: { event: MouseEvent; id: string }) {
const telemetryPayload = {
template_id: id,
wf_template_repo_session_id: this.workflowsStore.currentSessionId,
@@ -138,8 +138,7 @@ export default mixins(workflowHelpers).extend({
collection(collection: ITemplatesCollection) {
if (collection) {
setPageTitle(`n8n - Template collection: ${collection.name}`);
}
else {
} else {
setPageTitle(`n8n - Templates`);
}
},

View File

@@ -81,7 +81,12 @@ import TemplateList from '@/components/TemplateList.vue';
import TemplatesView from './TemplatesView.vue';
import { genericHelpers } from '@/mixins/genericHelpers';
import { ITemplatesCollection, ITemplatesWorkflow, ITemplatesQuery, ITemplatesCategory } from '@/Interface';
import {
ITemplatesCollection,
ITemplatesWorkflow,
ITemplatesQuery,
ITemplatesCategory,
} from '@/Interface';
import mixins from 'vue-typed-mixins';
import { IDataObject } from 'n8n-workflow';
import { setPageTitle } from '@/utils';
@@ -123,12 +128,7 @@ export default mixins(genericHelpers, debounceHelper).extend({
};
},
computed: {
...mapStores(
useSettingsStore,
useTemplatesStore,
useUIStore,
useUsersStore,
),
...mapStores(useSettingsStore, useTemplatesStore, useUIStore, useUsersStore),
totalWorkflows(): number {
return this.templatesStore.getSearchedWorkflowsTotal(this.query);
},
@@ -145,7 +145,11 @@ export default mixins(genericHelpers, debounceHelper).extend({
if (this.workflows.length && this.workflows.length >= this.totalWorkflows) {
return this.$locale.baseText('templates.endResult');
}
if (!this.loadingCollections && this.workflows.length === 0 && this.collections.length === 0) {
if (
!this.loadingCollections &&
this.workflows.length === 0 &&
this.collections.length === 0
) {
if (!this.settingsStore.isTemplatesEndpointReachable && this.errorLoadingWorkflows) {
return this.$locale.baseText('templates.connectionWarning');
}
@@ -170,10 +174,10 @@ export default mixins(genericHelpers, debounceHelper).extend({
},
},
methods: {
onOpenCollection({event, id}: {event: MouseEvent, id: string}) {
onOpenCollection({ event, id }: { event: MouseEvent; id: string }) {
this.navigateTo(event, VIEWS.COLLECTION, id);
},
onOpenTemplate({event, id}: {event: MouseEvent, id: string}) {
onOpenTemplate({ event, id }: { event: MouseEvent; id: string }) {
this.navigateTo(event, VIEWS.TEMPLATE, id);
},
navigateTo(e: MouseEvent, page: string, id: string) {
@@ -209,7 +213,10 @@ export default mixins(genericHelpers, debounceHelper).extend({
},
trackSearch() {
if (this.searchEventToTrack) {
this.$telemetry.track('User searched workflow templates', this.searchEventToTrack as unknown as IDataObject);
this.$telemetry.track(
'User searched workflow templates',
this.searchEventToTrack as unknown as IDataObject,
);
this.searchEventToTrack = null;
}
},
@@ -292,7 +299,7 @@ export default mixins(genericHelpers, debounceHelper).extend({
async loadCategories() {
try {
await this.templatesStore.getCategories();
} catch (e) { }
} catch (e) {}
this.loadingCategories = false;
},
async loadCollections() {
@@ -302,8 +309,7 @@ export default mixins(genericHelpers, debounceHelper).extend({
categories: this.categories,
search: this.search,
});
} catch (e) {
}
} catch (e) {}
this.loadingCollections = false;
},
@@ -352,7 +358,11 @@ export default mixins(genericHelpers, debounceHelper).extend({
const contentArea = document.getElementById('content');
if (contentArea) {
// When leaving this page, store current scroll position in route data
if (this.$route.meta && this.$route.meta.setScrollPosition && typeof this.$route.meta.setScrollPosition === 'function') {
if (
this.$route.meta &&
this.$route.meta.setScrollPosition &&
typeof this.$route.meta.setScrollPosition === 'function'
) {
this.$route.meta.setScrollPosition(contentArea.scrollTop);
}
}
@@ -379,7 +389,9 @@ export default mixins(genericHelpers, debounceHelper).extend({
}
if (typeof this.$route.query.categories === 'string' && this.$route.query.categories.length) {
this.categories = this.$route.query.categories.split(',').map((categoryId) => parseInt(categoryId, 10));
this.categories = this.$route.query.categories
.split(',')
.map((categoryId) => parseInt(categoryId, 10));
this.areCategoriesPrepopulated = true;
}
},
@@ -422,5 +434,4 @@ export default mixins(genericHelpers, debounceHelper).extend({
.header {
margin-bottom: var(--spacing-2xs);
}
</style>

View File

@@ -75,9 +75,7 @@ export default mixins(workflowHelpers).extend({
WorkflowPreview,
},
computed: {
...mapStores(
useTemplatesStore,
),
...mapStores(useTemplatesStore),
template(): ITemplatesWorkflow | ITemplatesWorkflowFull {
return this.templatesStore.getTemplateById(this.templateId);
},
@@ -128,8 +126,7 @@ export default mixins(workflowHelpers).extend({
template(template: ITemplatesWorkflowFull) {
if (template) {
setPageTitle(`n8n - Template template: ${template.name}`);
}
else {
} else {
setPageTitle(`n8n - Templates`);
}
},

View File

@@ -17,20 +17,37 @@
<template #empty>
<div class="text-center mt-s">
<n8n-heading tag="h2" size="xlarge" class="mb-2xs">
{{ $locale.baseText(currentUser.firstName ? 'workflows.empty.heading' : 'workflows.empty.heading.userNotSetup', { interpolate: { name: currentUser.firstName } }) }}
{{
$locale.baseText(
currentUser.firstName
? 'workflows.empty.heading'
: 'workflows.empty.heading.userNotSetup',
{ interpolate: { name: currentUser.firstName } },
)
}}
</n8n-heading>
<n8n-text size="large" color="text-base">
{{ $locale.baseText('workflows.empty.description') }}
</n8n-text>
</div>
<div class="text-center mt-2xl">
<n8n-card :class="[$style.emptyStateCard, 'mr-s']" hoverable @click="addWorkflow" data-test-id="new-workflow-card">
<n8n-card
:class="[$style.emptyStateCard, 'mr-s']"
hoverable
@click="addWorkflow"
data-test-id="new-workflow-card"
>
<n8n-icon :class="$style.emptyStateCardIcon" icon="file" />
<n8n-text size="large" class="mt-xs" color="text-base">
{{ $locale.baseText('workflows.empty.startFromScratch') }}
</n8n-text>
</n8n-card>
<n8n-card :class="$style.emptyStateCard" hoverable @click="goToTemplates" data-test-id="new-workflow-template-card">
<n8n-card
:class="$style.emptyStateCard"
hoverable
@click="goToTemplates"
data-test-id="new-workflow-template-card"
>
<n8n-icon :class="$style.emptyStateCardIcon" icon="box-open" />
<n8n-text size="large" class="mt-xs" color="text-base">
{{ $locale.baseText('workflows.empty.browseTemplates') }}
@@ -67,7 +84,8 @@
v-for="option in statusFilterOptions"
:key="option.label"
:label="option.label"
:value="option.value">
:value="option.value"
>
</n8n-option>
</n8n-select>
</div>
@@ -76,20 +94,20 @@
</template>
<script lang="ts">
import {showMessage} from '@/mixins/showMessage';
import { showMessage } from '@/mixins/showMessage';
import mixins from 'vue-typed-mixins';
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 WorkflowCard from "@/components/WorkflowCard.vue";
import TemplateCard from "@/components/TemplateCard.vue";
import {EnterpriseEditionFeature, VIEWS} from '@/constants';
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 Vue from "vue";
import {ITag, IUser, IWorkflowDb} from "@/Interface";
import TagsDropdown from "@/components/TagsDropdown.vue";
import Vue from 'vue';
import { ITag, IUser, IWorkflowDb } from '@/Interface';
import TagsDropdown from '@/components/TagsDropdown.vue';
import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui';
import { useSettingsStore } from '@/stores/settings';
@@ -104,10 +122,7 @@ const StatusFilter = {
ALL: '',
};
export default mixins(
showMessage,
debounceHelper,
).extend({
export default mixins(showMessage, debounceHelper).extend({
name: 'WorkflowsView',
components: {
ResourcesListLayout,
@@ -130,22 +145,19 @@ export default mixins(
};
},
computed: {
...mapStores(
useSettingsStore,
useUIStore,
useUsersStore,
useWorkflowsStore,
),
...mapStores(useSettingsStore, useUIStore, useUsersStore, useWorkflowsStore),
currentUser(): IUser {
return this.usersStore.currentUser || {} as IUser;
return this.usersStore.currentUser || ({} as IUser);
},
allWorkflows(): IWorkflowDb[] {
return this.workflowsStore.allWorkflows;
},
isShareable(): boolean {
return this.settingsStore.isEnterpriseFeatureEnabled(EnterpriseEditionFeature.WorkflowSharing);
return this.settingsStore.isEnterpriseFeatureEnabled(
EnterpriseEditionFeature.WorkflowSharing,
);
},
statusFilterOptions(): Array<{ label: string, value: string | boolean }> {
statusFilterOptions(): Array<{ label: string; value: string | boolean }> {
return [
{
label: this.$locale.baseText('workflows.filters.status.all'),
@@ -187,11 +199,21 @@ export default mixins(
this.filters.tags.push(tagId);
}
},
onFilter(resource: IWorkflowDb, filters: { tags: string[]; search: string; status: string | boolean }, matches: boolean): boolean {
onFilter(
resource: IWorkflowDb,
filters: { tags: string[]; search: string; status: string | boolean },
matches: boolean,
): boolean {
if (this.settingsStore.areTagsEnabled && filters.tags.length > 0) {
matches = matches && filters.tags.every(
(tag) => (resource.tags as ITag[])?.find((resourceTag) => typeof resourceTag === 'object' ? `${resourceTag.id}` === `${tag}` : `${resourceTag}` === `${tag}`),
);
matches =
matches &&
filters.tags.every((tag) =>
(resource.tags as ITag[])?.find((resourceTag) =>
typeof resourceTag === 'object'
? `${resourceTag.id}` === `${tag}`
: `${resourceTag}` === `${tag}`,
),
);
}
if (filters.status !== '') {
@@ -233,10 +255,9 @@ export default mixins(
font-size: 48px;
svg {
width: 48px!important;
width: 48px !important;
color: var(--color-foreground-dark);
transition: color 0.3s ease;}
transition: color 0.3s ease;
}
}
</style>