fix(editor): Show claim free ai credits modal on credentials (#19241)

Co-authored-by: konstantintieber <konstantin.tieber@n8n.io>
This commit is contained in:
Benjamin Schroth
2025-09-08 15:38:52 +02:00
committed by GitHub
parent 3c57dc488a
commit cf356e77b3
3 changed files with 57 additions and 1 deletions

View File

@@ -32,6 +32,7 @@ import GoogleAuthButton from './GoogleAuthButton.vue';
import OauthButton from './OauthButton.vue'; import OauthButton from './OauthButton.vue';
import { useAssistantStore } from '@/stores/assistant.store'; import { useAssistantStore } from '@/stores/assistant.store';
import InlineAskAssistantButton from '@n8n/design-system/components/InlineAskAssistantButton/InlineAskAssistantButton.vue'; import InlineAskAssistantButton from '@n8n/design-system/components/InlineAskAssistantButton/InlineAskAssistantButton.vue';
import FreeAiCreditsCallout from '@/components/FreeAiCreditsCallout.vue';
type Props = { type Props = {
mode: string; mode: string;
@@ -229,6 +230,7 @@ watch(showOAuthSuccessBanner, (newValue, oldValue) => {
</n8n-callout> </n8n-callout>
<div v-else> <div v-else>
<div :class="$style.config" data-test-id="node-credentials-config-container"> <div :class="$style.config" data-test-id="node-credentials-config-container">
<FreeAiCreditsCallout :credential-type-name="credentialType?.name" />
<Banner <Banner
v-show="showValidationWarning" v-show="showValidationWarning"
theme="danger" theme="danger"

View File

@@ -183,4 +183,48 @@ describe('FreeAiCreditsCallout', () => {
assertUserCannotClaimCredits(); assertUserCannotClaimCredits();
}); });
describe('credentialTypeName prop (credentials page)', () => {
it('should not show claim callout when editing a non-openapi credential', async () => {
(useNDVStore as any).mockReturnValue({
activeNode: null,
});
renderComponent(FreeAiCreditsCallout, {
props: {
credentialTypeName: 'googleSheetsOAuth2Api',
},
});
assertUserCannotClaimCredits();
});
it('should show claim callout editing openapi credential with no active node', async () => {
(useNDVStore as any).mockReturnValue({
activeNode: null,
});
renderComponent(FreeAiCreditsCallout, {
props: {
credentialTypeName: 'openAiApi',
},
});
assertUserCanClaimCredits();
});
it('should not show claim callout when credential type is undefined and no valid active node', async () => {
(useNDVStore as any).mockReturnValue({
activeNode: null,
});
renderComponent(FreeAiCreditsCallout, {
props: {
credentialTypeName: undefined,
},
});
assertUserCannotClaimCredits();
});
});
}); });

View File

@@ -11,6 +11,12 @@ import { computed, ref } from 'vue';
import { OPEN_AI_API_CREDENTIAL_TYPE } from 'n8n-workflow'; import { OPEN_AI_API_CREDENTIAL_TYPE } from 'n8n-workflow';
import { N8nCallout, N8nText } from '@n8n/design-system'; import { N8nCallout, N8nText } from '@n8n/design-system';
type Props = {
credentialTypeName?: string;
};
const props = defineProps<Props>();
const LANGCHAIN_NODES_PREFIX = '@n8n/n8n-nodes-langchain.'; const LANGCHAIN_NODES_PREFIX = '@n8n/n8n-nodes-langchain.';
const N8N_NODES_PREFIX = '@n8n/n8n-nodes.'; const N8N_NODES_PREFIX = '@n8n/n8n-nodes.';
@@ -42,6 +48,10 @@ const userHasOpenAiCredentialAlready = computed(
).length, ).length,
); );
const isEditingOpenAiCredential = computed(
() => props.credentialTypeName && props.credentialTypeName === OPEN_AI_API_CREDENTIAL_TYPE,
);
const userHasClaimedAiCreditsAlready = computed( const userHasClaimedAiCreditsAlready = computed(
() => !!usersStore.currentUser?.settings?.userClaimedAiCredits, () => !!usersStore.currentUser?.settings?.userClaimedAiCredits,
); );
@@ -55,7 +65,7 @@ const activeNodeHasOpenAiApiCredential = computed(
const userCanClaimOpenAiCredits = computed(() => { const userCanClaimOpenAiCredits = computed(() => {
return ( return (
settingsStore.isAiCreditsEnabled && settingsStore.isAiCreditsEnabled &&
activeNodeHasOpenAiApiCredential.value && (activeNodeHasOpenAiApiCredential.value || isEditingOpenAiCredential.value) &&
!userHasOpenAiCredentialAlready.value && !userHasOpenAiCredentialAlready.value &&
!userHasClaimedAiCreditsAlready.value !userHasClaimedAiCreditsAlready.value
); );