fix(editor): Update Usage page for Community+ edition (#11074)

This commit is contained in:
Csaba Tuncsik 2024-10-03 13:39:48 +02:00 committed by GitHub
parent dbd2ae1995
commit 3974981ea5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 91 additions and 4 deletions

View file

@ -1797,6 +1797,7 @@
"settings.usageAndPlan.license.activation.error.title": "Activation failed", "settings.usageAndPlan.license.activation.error.title": "Activation failed",
"settings.usageAndPlan.license.activation.success.title": "License activated", "settings.usageAndPlan.license.activation.success.title": "License activated",
"settings.usageAndPlan.license.activation.success.message": "Your {name} {type} has been successfully activated.", "settings.usageAndPlan.license.activation.success.message": "Your {name} {type} has been successfully activated.",
"settings.usageAndPlan.license.communityRegistered.tooltip": "You have registered your email to unlock additional features on your community plan",
"settings.externalSecrets.title": "External Secrets", "settings.externalSecrets.title": "External Secrets",
"settings.externalSecrets.info": "Connect external secrets tools for centralized credentials management across environments, and to enhance system security.", "settings.externalSecrets.info": "Connect external secrets tools for centralized credentials management across environments, and to enhance system security.",
"settings.externalSecrets.info.link": "More info", "settings.externalSecrets.info.link": "More info",

View file

@ -0,0 +1,51 @@
import { createTestingPinia } from '@pinia/testing';
import { createComponentRenderer } from '@/__tests__/render';
import { mockedStore } from '@/__tests__/utils';
import { useUsageStore } from '@/stores/usage.store';
import SettingsUsageAndPlan from '@/views/SettingsUsageAndPlan.vue';
vi.mock('vue-router', () => {
return {
useRoute: () => ({
query: {},
}),
useRouter: () => ({
replace: vi.fn(),
}),
RouterLink: {
template: '<a><slot /></a>',
},
};
});
let usageStore: ReturnType<typeof mockedStore<typeof useUsageStore>>;
const renderComponent = createComponentRenderer(SettingsUsageAndPlan);
describe('SettingsUsageAndPlan', () => {
beforeEach(() => {
createTestingPinia();
usageStore = mockedStore(useUsageStore);
});
it('should not throw errors when rendering', async () => {
expect(() => renderComponent()).not.toThrow();
});
it('should render the title only while loading', async () => {
const { getByRole } = renderComponent();
expect(getByRole('heading', { level: 2 })).toBeInTheDocument();
expect(getByRole('heading').nextElementSibling).toBeNull();
});
it('should show community registered badge', async () => {
usageStore.isLoading = false;
usageStore.viewPlansUrl = 'https://subscription.n8n.io';
usageStore.managePlanUrl = 'https://subscription.n8n.io';
usageStore.planName = 'Community registered';
const { getByRole, container } = renderComponent();
expect(getByRole('heading', { level: 3 })).toHaveTextContent('Community Edition');
expect(getByRole('heading', { level: 3 })).toContain(container.querySelector('.n8n-badge'));
expect(container.querySelector('.n8n-badge')).toHaveTextContent('registered');
});
});

View file

@ -32,6 +32,18 @@ const canUserActivateLicense = computed(() =>
hasPermission(['rbac'], { rbac: { scope: 'license:manage' } }), hasPermission(['rbac'], { rbac: { scope: 'license:manage' } }),
); );
const badgedPlanName = computed(() => {
const [name, badge] = usageStore.planName.split(' ');
return {
name,
badge,
};
});
const isCommunityEditionRegistered = computed(
() => usageStore.planName.toLowerCase() === 'community registered',
);
const showActivationSuccess = () => { const showActivationSuccess = () => {
toast.showMessage({ toast.showMessage({
type: 'success', type: 'success',
@ -125,11 +137,15 @@ const onDialogOpened = () => {
<template> <template>
<div class="settings-usage-and-plan"> <div class="settings-usage-and-plan">
<n8n-heading size="2xlarge">{{ locale.baseText('settings.usageAndPlan.title') }}</n8n-heading> <n8n-heading tag="h2" size="2xlarge">{{
locale.baseText('settings.usageAndPlan.title')
}}</n8n-heading>
<div v-if="!usageStore.isLoading"> <div v-if="!usageStore.isLoading">
<n8n-heading :class="$style.title" size="large"> <n8n-heading tag="h3" :class="$style.title" size="large">
<i18n-t keypath="settings.usageAndPlan.description" tag="span"> <i18n-t keypath="settings.usageAndPlan.description" tag="span">
<template #name>{{ usageStore.planName }}</template> <template #name>{{
badgedPlanName.badge ? badgedPlanName.name : usageStore.planName
}}</template>
<template #type> <template #type>
<span v-if="usageStore.planId">{{ <span v-if="usageStore.planId">{{
locale.baseText('settings.usageAndPlan.plan') locale.baseText('settings.usageAndPlan.plan')
@ -137,6 +153,18 @@ const onDialogOpened = () => {
<span v-else>{{ locale.baseText('settings.usageAndPlan.edition') }}</span> <span v-else>{{ locale.baseText('settings.usageAndPlan.edition') }}</span>
</template> </template>
</i18n-t> </i18n-t>
<span :class="$style.titleTooltip">
<N8nTooltip v-if="badgedPlanName.badge" placement="top">
<template #content>
<i18n-t
v-if="isCommunityEditionRegistered"
keypath="settings.usageAndPlan.license.communityRegistered.tooltip"
>
</i18n-t>
</template>
<N8nBadge>{{ badgedPlanName.badge }}</N8nBadge>
</N8nTooltip>
</span>
</n8n-heading> </n8n-heading>
<div :class="$style.quota"> <div :class="$style.quota">
@ -239,7 +267,8 @@ const onDialogOpened = () => {
} }
.title { .title {
display: block; display: flex;
align-items: center;
padding: var(--spacing-2xl) 0 var(--spacing-m); padding: var(--spacing-2xl) 0 var(--spacing-m);
} }
@ -309,6 +338,12 @@ div[class*='info'] > span > span:last-child {
line-height: 1.4; line-height: 1.4;
padding: 0 0 0 var(--spacing-4xs); padding: 0 0 0 var(--spacing-4xs);
} }
.titleTooltip {
display: flex;
align-items: center;
margin: 0 0 0 var(--spacing-2xs);
}
</style> </style>
<style lang="scss" scoped> <style lang="scss" scoped>