feat(editor): Add dynamic banner text support (no-changelog) (#21466)

This commit is contained in:
Juuso Tapaninen 2025-11-03 05:46:17 +02:00 committed by GitHub
parent 7e1f07dfd6
commit 680b516e57
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 63 additions and 4 deletions

View File

@ -35,6 +35,9 @@ export declare namespace Cloud {
information?: {
[key: string]: string | string[];
};
trialBannerData?: {
bannerText: string;
};
};
}

View File

@ -22,12 +22,17 @@ const DEFAULT_STATE: CloudPlanState = {
loadingPlan: false,
};
const DYNAMIC_TRIAL_BANNER_DISMISSED_KEY = 'n8n-dynamic-trial-banner-dismissed';
export const useCloudPlanStore = defineStore(STORES.CLOUD_PLAN, () => {
const rootStore = useRootStore();
const settingsStore = useSettingsStore();
const state = reactive<CloudPlanState>(DEFAULT_STATE);
const currentUserCloudInfo = ref<Cloud.UserAccount | null>(null);
const isDynamicTrialBannerDismissed = ref<boolean>(
localStorage.getItem(DYNAMIC_TRIAL_BANNER_DISMISSED_KEY) === 'true',
);
const reset = () => {
currentUserCloudInfo.value = null;
@ -61,6 +66,23 @@ export const useCloudPlanStore = defineStore(STORES.CLOUD_PLAN, () => {
return information.which_of_these_do_you_feel_comfortable_doing.length;
});
const dynamicTrialBannerText = computed(() => {
return currentUserCloudInfo.value?.trialBannerData?.bannerText;
});
const shouldShowDynamicTrialBanner = computed(() => {
return (
dynamicTrialBannerText.value !== undefined &&
dynamicTrialBannerText.value !== '' &&
!isDynamicTrialBannerDismissed.value
);
});
const dismissDynamicTrialBanner = () => {
isDynamicTrialBannerDismissed.value = true;
localStorage.setItem(DYNAMIC_TRIAL_BANNER_DISMISSED_KEY, 'true');
};
const trialExpired = computed(
() =>
state.data?.metadata?.group === 'trial' &&
@ -217,5 +239,8 @@ export const useCloudPlanStore = defineStore(STORES.CLOUD_PLAN, () => {
getAutoLoginCode,
selectedApps,
codingSkill,
dynamicTrialBannerText,
shouldShowDynamicTrialBanner,
dismissDynamicTrialBanner,
};
});

View File

@ -6,13 +6,16 @@ import { computed } from 'vue';
import type { CloudPlanAndUsageData } from '@/Interface';
import { usePageRedirectionHelper } from '@/app/composables/usePageRedirectionHelper';
import { N8nButton, N8nText } from '@n8n/design-system';
import { N8nBadge, N8nButton, N8nText } from '@n8n/design-system';
const PROGRESS_BAR_MINIMUM_THRESHOLD = 8;
const cloudPlanStore = useCloudPlanStore();
const pageRedirectionHelper = usePageRedirectionHelper();
const shouldShowTrialBanner = computed(() => cloudPlanStore.shouldShowDynamicTrialBanner);
const trialBannerText = computed(() => cloudPlanStore.dynamicTrialBannerText);
const trialDaysLeft = computed(() => -1 * cloudPlanStore.trialDaysLeft);
const messageText = computed(() => {
return locale.baseText('banners.trial.message', {
@ -52,6 +55,10 @@ const currentExecutions = computed(() => {
});
function onUpdatePlanClick() {
if (shouldShowTrialBanner.value) {
cloudPlanStore.dismissDynamicTrialBanner();
}
void pageRedirectionHelper.goToUpgrade('canvas-nav', 'upgrade-canvas-nav', 'redirect');
}
</script>
@ -86,9 +93,19 @@ function onUpdatePlanClick() {
</div>
</template>
<template #trailingContent>
<N8nButton type="success" icon="gem" size="small" @click="onUpdatePlanClick">{{
locale.baseText('generic.upgradeNow')
}}</N8nButton>
<div :class="$style.trailingContentWrapper">
<N8nBadge
v-if="shouldShowTrialBanner"
:class="$style.dynamicBanner"
size="small"
:show-border="false"
:bold="true"
>{{ trialBannerText }}</N8nBadge
>
<N8nButton type="success" icon="gem" size="small" @click="onUpdatePlanClick">{{
locale.baseText('generic.upgradeNow')
}}</N8nButton>
</div>
</template>
</BaseBanner>
</template>
@ -174,4 +191,18 @@ function onUpdatePlanClick() {
.executionsCountSection {
margin-left: var(--spacing--xs);
}
.trailingContentWrapper {
display: flex;
align-items: center;
gap: var(--spacing--2xs);
}
.dynamicBanner {
color: var(--color--foreground--tint-2);
border: none;
background: var(--color--foreground--shade-2);
border-radius: var(--radius);
padding: var(--spacing--5xs) var(--spacing--3xs);
}
</style>