diff --git a/packages/frontend/editor-ui/src/features/settings/usage/views/SettingsUsageAndPlan.test.ts b/packages/frontend/editor-ui/src/features/settings/usage/views/SettingsUsageAndPlan.test.ts
index c649c020b1e..5e6ef8d3616 100644
--- a/packages/frontend/editor-ui/src/features/settings/usage/views/SettingsUsageAndPlan.test.ts
+++ b/packages/frontend/editor-ui/src/features/settings/usage/views/SettingsUsageAndPlan.test.ts
@@ -257,6 +257,63 @@ describe('SettingsUsageAndPlan', () => {
expect(usageStore.activateLicense).toHaveBeenCalledTimes(1);
});
+ it('should preserve activation key during EULA flow and send it with acceptance', async () => {
+ usageStore.isLoading = false;
+ usageStore.planName = 'Community';
+ usersStore.currentUser = {
+ globalScopes: ['license:manage'],
+ } as IUser;
+ rbacStore.setGlobalScopes(['license:manage']);
+ usageStore.activateLicense
+ .mockRejectedValueOnce({
+ httpStatusCode: 400,
+ meta: { eulaUrl: 'https://example.com/eula.pdf' },
+ })
+ .mockResolvedValueOnce(undefined);
+
+ const { getByRole, findByTestId } = renderComponent();
+
+ // Open activation modal and enter key
+ await userEvent.click(getByRole('button', { name: /activation/i }));
+ const input = document.querySelector('input') as HTMLInputElement;
+ await userEvent.type(input, 'test-key-123');
+
+ // Click activate - this should trigger EULA modal
+ await userEvent.click(getByRole('button', { name: /activate/i }));
+
+ // EULA modal should appear
+ const eulaModal = await findByTestId('eula-acceptance-modal');
+ expect(eulaModal).toBeInTheDocument();
+
+ // Accept EULA
+ const checkbox = (await findByTestId('eula-checkbox')).querySelector(
+ 'input[type="checkbox"]',
+ ) as HTMLInputElement;
+ await userEvent.click(checkbox);
+
+ const acceptButton = await findByTestId('eula-accept-button');
+ await userEvent.click(acceptButton);
+
+ // Verify the activation key was preserved and sent with EULA acceptance
+ await waitFor(() => {
+ expect(usageStore.activateLicense).toHaveBeenCalledTimes(2);
+ // First call without EULA
+ expect(usageStore.activateLicense).toHaveBeenNthCalledWith(1, 'test-key-123', undefined);
+ // Second call with EULA URL - key should still be present
+ expect(usageStore.activateLicense).toHaveBeenNthCalledWith(
+ 2,
+ 'test-key-123',
+ 'https://example.com/eula.pdf',
+ );
+ });
+
+ expect(mockToast.showMessage).toHaveBeenCalledWith(
+ expect.objectContaining({
+ type: 'success',
+ }),
+ );
+ });
+
it('should show error when activation fails without EULA requirement', async () => {
usageStore.isLoading = false;
usageStore.planName = 'Community';
@@ -424,5 +481,41 @@ describe('SettingsUsageAndPlan', () => {
expect(reopenedInput).toBeInTheDocument();
});
});
+
+ it('should clear activation key when cancel button is clicked', async () => {
+ usageStore.isLoading = false;
+ usersStore.currentUser = {
+ globalScopes: ['license:manage'],
+ } as IUser;
+ rbacStore.setGlobalScopes(['license:manage']);
+
+ const { getByRole, findByPlaceholderText } = renderComponent();
+
+ await waitAllPromises();
+
+ // Open activation modal
+ await userEvent.click(getByRole('button', { name: /activation/i }));
+ const input = await findByPlaceholderText('Activation key');
+ expect(input).toBeInTheDocument();
+
+ // Enter activation key
+ await userEvent.type(input, 'test-key-should-be-cleared');
+ expect(input).toHaveValue('test-key-should-be-cleared');
+
+ // Click cancel
+ const cancelButton = getByRole('button', { name: /cancel/i });
+ await userEvent.click(cancelButton);
+
+ await waitAllPromises();
+
+ // Reopen modal
+ await userEvent.click(getByRole('button', { name: /activation/i }));
+
+ // Input should be cleared
+ await waitFor(async () => {
+ const reopenedInput = await findByPlaceholderText('Activation key');
+ expect(reopenedInput).toHaveValue('');
+ });
+ });
});
});
diff --git a/packages/frontend/editor-ui/src/features/settings/usage/views/SettingsUsageAndPlan.vue b/packages/frontend/editor-ui/src/features/settings/usage/views/SettingsUsageAndPlan.vue
index 1a5a38e229f..5c0beb4043b 100644
--- a/packages/frontend/editor-ui/src/features/settings/usage/views/SettingsUsageAndPlan.vue
+++ b/packages/frontend/editor-ui/src/features/settings/usage/views/SettingsUsageAndPlan.vue
@@ -111,9 +111,9 @@ const onLicenseActivation = async (eulaUri?: string) => {
} catch (error: unknown) {
// Check if error requires EULA acceptance using type guard
if (isEulaError(error)) {
- activationKeyModal.value = false;
eulaUrl.value = error.meta.eulaUrl;
eulaModal.value = true;
+ activationKeyModal.value = false;
return;
}
@@ -138,6 +138,18 @@ const onEulaCancel = () => {
activationKey.value = '';
};
+const onActivationCancel = () => {
+ activationKeyModal.value = false;
+ activationKey.value = '';
+};
+
+const onActivationModalClose = () => {
+ // Only clear key if not transitioning to EULA flow
+ if (!eulaModal.value) {
+ onActivationCancel();
+ }
+};
+
onMounted(async () => {
documentTitle.set(locale.baseText('settings.usageAndPlan.title'));
usageStore.setLoading(true);
@@ -187,10 +199,6 @@ const onManagePlan = () => {
sendUsageTelemetry('manage_plan');
};
-const onDialogClosed = () => {
- activationKey.value = '';
-};
-
const onDialogOpened = () => {
activationKeyInput.value?.focus();
};
@@ -307,7 +315,7 @@ const openCommunityRegisterModal = () => {
top="0"
:title="locale.baseText('settings.usageAndPlan.dialog.activation.title')"
:modal-class="$style.center"
- @closed="onDialogClosed"
+ @closed="onActivationModalClose"
@opened="onDialogOpened"
>
@@ -318,7 +326,7 @@ const openCommunityRegisterModal = () => {
/>
-
+
{{ locale.baseText('settings.usageAndPlan.dialog.activation.cancel') }}
onLicenseActivation()">