diff --git a/redisinsight/api/src/modules/cloud/job/jobs/create-free-subscription-and-database.cloud-job.ts b/redisinsight/api/src/modules/cloud/job/jobs/create-free-subscription-and-database.cloud-job.ts index 48494c0ada..378b0c15e1 100644 --- a/redisinsight/api/src/modules/cloud/job/jobs/create-free-subscription-and-database.cloud-job.ts +++ b/redisinsight/api/src/modules/cloud/job/jobs/create-free-subscription-and-database.cloud-job.ts @@ -4,7 +4,7 @@ import { CloudSubscriptionCapiService } from 'src/modules/cloud/subscription/clo import { CreateFreeSubscriptionCloudJob } from 'src/modules/cloud/job/jobs/create-free-subscription.cloud-job'; import { CloudDatabaseCapiService } from 'src/modules/cloud/database/cloud-database.capi.service'; import { CloudJobName } from 'src/modules/cloud/job/constants'; -import { CloudJobStep } from 'src/modules/cloud/job/models'; +import { CloudJobStatus, CloudJobStep } from 'src/modules/cloud/job/models'; import { DatabaseService } from 'src/modules/database/database.service'; import { Database } from 'src/modules/database/models/database'; import { CloudDatabaseAnalytics } from 'src/modules/cloud/database/cloud-database.analytics'; @@ -54,12 +54,18 @@ export class CreateFreeSubscriptionAndDatabaseCloudJob extends CloudJob { this.changeState({ step: CloudJobStep.Database }); - return this.runChildJob( + const database = await this.runChildJob( CreateFreeDatabaseCloudJob, { subscriptionId: freeSubscription.id, }, this.options, ); + + this.result = { resourceId: database.id }; + + this.changeState({ status: CloudJobStatus.Finished }); + + return database; } } diff --git a/redisinsight/ui/src/components/global-subscriptions/CommonAppSubscription/CommonAppSubscription.tsx b/redisinsight/ui/src/components/global-subscriptions/CommonAppSubscription/CommonAppSubscription.tsx index 1194e6129b..64939482b5 100644 --- a/redisinsight/ui/src/components/global-subscriptions/CommonAppSubscription/CommonAppSubscription.tsx +++ b/redisinsight/ui/src/components/global-subscriptions/CommonAppSubscription/CommonAppSubscription.tsx @@ -53,7 +53,11 @@ const CommonAppSubscription = () => { }) socketRef.current.on(CloudJobEvents.Monitor, (data: CloudJobInfo) => { - if ((data.name as unknown) === CloudJobName.CreateFreeDatabase) { + const jobName = data.name as unknown + if ( + jobName === CloudJobName.CreateFreeDatabase + || jobName === CloudJobName.CreateFreeSubscriptionAndDatabase + || jobName === CloudJobName.ImportFreeDatabase) { dispatch(setJob(data)) } }) diff --git a/redisinsight/ui/src/components/notifications/Notifications.tsx b/redisinsight/ui/src/components/notifications/Notifications.tsx index 800bba70ca..a917c53523 100644 --- a/redisinsight/ui/src/components/notifications/Notifications.tsx +++ b/redisinsight/ui/src/components/notifications/Notifications.tsx @@ -22,8 +22,9 @@ import { IError, IMessage, InfiniteMessage } from 'uiSrc/slices/interfaces' import { ApiEncryptionErrors } from 'uiSrc/constants/apiErrors' import { DEFAULT_ERROR_MESSAGE } from 'uiSrc/utils' import { showOAuthProgress } from 'uiSrc/slices/oauth/cloud' - import { CustomErrorCodes } from 'uiSrc/constants' +import { TelemetryEvent, sendEventTelemetry } from 'uiSrc/telemetry' + import errorMessages from './error-messages' import { InfiniteMessagesIds } from './components' @@ -115,9 +116,25 @@ const Notifications = () => { text: Inner, color: 'success', onClose: () => { - if (id === InfiniteMessagesIds.oAuthProgress) { - dispatch(showOAuthProgress(false)) + switch (id) { + case InfiniteMessagesIds.oAuthProgress: + dispatch(showOAuthProgress(false)) + break + case InfiniteMessagesIds.databaseExists: + sendEventTelemetry({ + event: TelemetryEvent.CLOUD_IMPORT_EXISTING_DATABASE_FORM_CLOSED, + }) + break + case InfiniteMessagesIds.subscriptionExists: + sendEventTelemetry({ + event: TelemetryEvent.CLOUD_CREATE_DATABASE_IN_SUBSCRIPTION_FORM_CLOSED, + }) + break + + default: + break } + dispatch(removeInfiniteNotification(id)) }, toastLifeTimeMs: 3_600_000, diff --git a/redisinsight/ui/src/components/notifications/components/infinite-messages/InfiniteMessages.spec.tsx b/redisinsight/ui/src/components/notifications/components/infinite-messages/InfiniteMessages.spec.tsx index b7d2bea037..bf75206f2f 100644 --- a/redisinsight/ui/src/components/notifications/components/infinite-messages/InfiniteMessages.spec.tsx +++ b/redisinsight/ui/src/components/notifications/components/infinite-messages/InfiniteMessages.spec.tsx @@ -24,8 +24,70 @@ describe('INFINITE_MESSAGES', () => { }) describe('PENDING_CREATE_DB', () => { it('should render message', () => { - const { Inner } = INFINITE_MESSAGES.PENDING_CREATE_DB + const { Inner } = INFINITE_MESSAGES.PENDING_CREATE_DB() expect(render(<>{Inner})).toBeTruthy() }) }) + describe('DATABASE_EXISTS', () => { + it('should render message', () => { + const { Inner } = INFINITE_MESSAGES.DATABASE_EXISTS(jest.fn()) + expect(render(<>{Inner})).toBeTruthy() + }) + + it('should call onSuccess', () => { + const onSuccess = jest.fn() + const { Inner } = INFINITE_MESSAGES.DATABASE_EXISTS(onSuccess) + render(<>{Inner}) + + fireEvent.click(screen.getByTestId('import-db-sso-btn')) + fireEvent.mouseUp(screen.getByTestId('database-exists-notification')) + fireEvent.mouseDown(screen.getByTestId('database-exists-notification')) + + expect(onSuccess).toBeCalled() + }) + + it('should call onCancel', () => { + const onSuccess = jest.fn() + const onCancel = jest.fn() + const { Inner } = INFINITE_MESSAGES.DATABASE_EXISTS(onSuccess, onCancel) + render(<>{Inner}) + + fireEvent.click(screen.getByTestId('cancel-import-db-sso-btn')) + fireEvent.mouseUp(screen.getByTestId('database-exists-notification')) + fireEvent.mouseDown(screen.getByTestId('database-exists-notification')) + + expect(onCancel).toBeCalled() + }) + }) + describe('SUBSCRIPTION_EXISTS', () => { + it('should render message', () => { + const { Inner } = INFINITE_MESSAGES.SUBSCRIPTION_EXISTS(jest.fn()) + expect(render(<>{Inner})).toBeTruthy() + }) + + it('should call onSuccess', () => { + const onSuccess = jest.fn() + const { Inner } = INFINITE_MESSAGES.SUBSCRIPTION_EXISTS(onSuccess) + render(<>{Inner}) + + fireEvent.click(screen.getByTestId('create-subscription-sso-btn')) + fireEvent.mouseUp(screen.getByTestId('subscription-exists-notification')) + fireEvent.mouseDown(screen.getByTestId('subscription-exists-notification')) + + expect(onSuccess).toBeCalled() + }) + + it('should call onCancel', () => { + const onSuccess = jest.fn() + const onCancel = jest.fn() + const { Inner } = INFINITE_MESSAGES.SUBSCRIPTION_EXISTS(onSuccess, onCancel) + render(<>{Inner}) + + fireEvent.click(screen.getByTestId('cancel-create-subscription-sso-btn')) + fireEvent.mouseUp(screen.getByTestId('subscription-exists-notification')) + fireEvent.mouseDown(screen.getByTestId('subscription-exists-notification')) + + expect(onCancel).toBeCalled() + }) + }) }) diff --git a/redisinsight/ui/src/components/notifications/components/infinite-messages/InfiniteMessages.tsx b/redisinsight/ui/src/components/notifications/components/infinite-messages/InfiniteMessages.tsx index c331db702c..def1671de1 100644 --- a/redisinsight/ui/src/components/notifications/components/infinite-messages/InfiniteMessages.tsx +++ b/redisinsight/ui/src/components/notifications/components/infinite-messages/InfiniteMessages.tsx @@ -5,10 +5,12 @@ import { CloudJobStep } from 'uiSrc/electron/constants' export enum InfiniteMessagesIds { oAuthProgress = 'oAuthProgress', oAuthSuccess = 'oAuthSuccess', + databaseExists = 'databaseExists', + subscriptionExists = 'subscriptionExists', } export const INFINITE_MESSAGES = { - PENDING_CREATE_DB: (step: CloudJobStep) => ({ + PENDING_CREATE_DB: (step?: CloudJobStep) => ({ id: InfiniteMessagesIds.oAuthProgress, Inner: (
@@ -70,4 +73,84 @@ export const INFINITE_MESSAGES = {
) }), + DATABASE_EXISTS: (onSuccess?: () => void, onClose?: () => void) => ({ + id: InfiniteMessagesIds.databaseExists, + Inner: ( +
{ e.preventDefault() }} + onMouseUp={(e) => { e.preventDefault() }} + data-testid="database-exists-notification" + > + You already have a free Redis Enterprise Cloud subscription. + + Do you want to import your existing database into RedisInsight? + + + + + onSuccess?.()} + data-testid="import-db-sso-btn" + > + Import + + + + onClose?.()} + data-testid="cancel-import-db-sso-btn" + > + Cancel + + + +
+ ) + }), + SUBSCRIPTION_EXISTS: (onSuccess?: () => void, onClose?: () => void) => ({ + id: InfiniteMessagesIds.subscriptionExists, + Inner: ( +
{ e.preventDefault() }} + onMouseUp={(e) => { e.preventDefault() }} + data-testid="subscription-exists-notification" + > + Your subscription does not have a free Redis Enterprise Cloud database. + + Do you want to create a free database in your existing subscription? + + + + + onSuccess?.()} + data-testid="create-subscription-sso-btn" + > + Create + + + + onClose?.()} + data-testid="cancel-create-subscription-sso-btn" + > + Cancel + + + +
+ ) + }), } diff --git a/redisinsight/ui/src/components/oauth/oauth-jobs/OAuthJobs.spec.tsx b/redisinsight/ui/src/components/oauth/oauth-jobs/OAuthJobs.spec.tsx index d82273aa10..f4614e177e 100644 --- a/redisinsight/ui/src/components/oauth/oauth-jobs/OAuthJobs.spec.tsx +++ b/redisinsight/ui/src/components/oauth/oauth-jobs/OAuthJobs.spec.tsx @@ -9,6 +9,7 @@ import { addErrorNotification, addInfiniteNotification, removeInfiniteNotificati import { RootState } from 'uiSrc/slices/store' import { loadInstances } from 'uiSrc/slices/instances/instances' import { INFINITE_MESSAGES, InfiniteMessagesIds } from 'uiSrc/components/notifications/components' +import { CustomErrorCodes } from 'uiSrc/constants' import OAuthJobs from './OAuthJobs' jest.mock('react-redux', () => ({ @@ -128,8 +129,68 @@ describe('OAuthJobs', () => { rerender() const expectedActions = [ - removeInfiniteNotification(InfiniteMessagesIds.oAuthProgress), addErrorNotification({ response: { data: error } } as AxiosError), + removeInfiniteNotification(InfiniteMessagesIds.oAuthProgress), + ] + expect(clearStoreActions(store.getActions())).toEqual( + clearStoreActions(expectedActions) + ) + }) + + it('should call addInfiniteNotification and removeInfiniteNotification when errorCode is 11_108', async () => { + const mockDatabaseId = '123' + const error = { + errorCode: CustomErrorCodes.CloudDatabaseAlreadyExistsFree, + resource: { + databaseId: mockDatabaseId + } + }; + (oauthCloudJobSelector as jest.Mock).mockImplementation(() => ({ + status: '' + })) + + const { rerender } = render(); + + (oauthCloudJobSelector as jest.Mock).mockImplementation(() => ({ + status: CloudJobStatus.Failed, + error, + })) + + rerender() + + const expectedActions = [ + addInfiniteNotification(INFINITE_MESSAGES.DATABASE_EXISTS()), + removeInfiniteNotification(InfiniteMessagesIds.oAuthProgress), + ] + expect(clearStoreActions(store.getActions())).toEqual( + clearStoreActions(expectedActions) + ) + }) + + it('should call addInfiniteNotification and removeInfiniteNotification when errorCode is 11_114', async () => { + const mockDatabaseId = '123' + const error = { + errorCode: CustomErrorCodes.CloudSubscriptionAlreadyExistsFree, + resource: { + databaseId: mockDatabaseId + } + }; + (oauthCloudJobSelector as jest.Mock).mockImplementation(() => ({ + status: '' + })) + + const { rerender } = render(); + + (oauthCloudJobSelector as jest.Mock).mockImplementation(() => ({ + status: CloudJobStatus.Failed, + error, + })) + + rerender() + + const expectedActions = [ + addInfiniteNotification(INFINITE_MESSAGES.DATABASE_EXISTS()), + removeInfiniteNotification(InfiniteMessagesIds.oAuthProgress), ] expect(clearStoreActions(store.getActions())).toEqual( clearStoreActions(expectedActions) diff --git a/redisinsight/ui/src/components/oauth/oauth-jobs/OAuthJobs.tsx b/redisinsight/ui/src/components/oauth/oauth-jobs/OAuthJobs.tsx index dd06207543..22c5afc2b6 100644 --- a/redisinsight/ui/src/components/oauth/oauth-jobs/OAuthJobs.tsx +++ b/redisinsight/ui/src/components/oauth/oauth-jobs/OAuthJobs.tsx @@ -1,13 +1,16 @@ import { useEffect } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useHistory } from 'react-router-dom' +import { get } from 'lodash' import { CloudJobStatus, CloudJobName, CloudJobStep } from 'uiSrc/electron/constants' import { fetchInstancesAction } from 'uiSrc/slices/instances/instances' -import { createFreeDbSuccess, oauthCloudJobSelector, oauthCloudSelector, setJob, showOAuthProgress } from 'uiSrc/slices/oauth/cloud' +import { createFreeDbJob, createFreeDbSuccess, oauthCloudJobSelector, oauthCloudSelector, setJob } from 'uiSrc/slices/oauth/cloud' import { addErrorNotification, addInfiniteNotification, removeInfiniteNotification } from 'uiSrc/slices/app/notifications' import { parseCloudOAuthError } from 'uiSrc/utils' import { INFINITE_MESSAGES, InfiniteMessagesIds } from 'uiSrc/components/notifications/components' +import { TelemetryEvent, sendEventTelemetry } from 'uiSrc/telemetry' +import { CustomErrorCodes } from 'uiSrc/constants' const OAuthJobs = () => { const { @@ -31,13 +34,40 @@ const OAuthJobs = () => { case CloudJobStatus.Finished: dispatch(fetchInstancesAction(() => dispatch(createFreeDbSuccess(resourceId, history)))) - dispatch(setJob({ id: '', name: CloudJobName.CreateFreeDatabase, status: '' })) + dispatch(setJob({ id: '', name: CloudJobName.CreateFreeSubscriptionAndDatabase, status: '' })) break case CloudJobStatus.Failed: - const err = parseCloudOAuthError(error || '') + + const errorCode = get(error, 'errorCode', 0) as CustomErrorCodes + const subscriptionId = get(error, 'resource.subscriptionId', 0) + const databaseId = get(error, 'resource.databaseId', 0) + // eslint-disable-next-line sonarjs/no-nested-switch + switch (errorCode) { + case CustomErrorCodes.CloudDatabaseAlreadyExistsFree: + dispatch(addInfiniteNotification( + INFINITE_MESSAGES.DATABASE_EXISTS( + () => importDatabase(subscriptionId, databaseId), + closeImportDatabase, + ) + )) + + break + + case CustomErrorCodes.CloudSubscriptionAlreadyExistsFree: + dispatch(addInfiniteNotification(INFINITE_MESSAGES.SUBSCRIPTION_EXISTS( + () => createFreeDatabase(subscriptionId), + closeCreateFreeDatabase, + ))) + break + + default: + const err = parseCloudOAuthError(error || '') + dispatch(addErrorNotification(err)) + break + } + dispatch(removeInfiniteNotification(InfiniteMessagesIds.oAuthProgress)) - dispatch(addErrorNotification(err)) break default: @@ -45,6 +75,48 @@ const OAuthJobs = () => { } }, [status, error, step, resourceId, showProgress]) + const importDatabase = (subscriptionId: number, databaseId: number) => { + sendEventTelemetry({ + event: TelemetryEvent.CLOUD_IMPORT_EXISTING_DATABASE, + }) + dispatch(createFreeDbJob({ + name: CloudJobName.ImportFreeDatabase, + resources: { subscriptionId, databaseId }, + onSuccessAction: () => { + dispatch(removeInfiniteNotification(InfiniteMessagesIds.databaseExists)) + dispatch(addInfiniteNotification(INFINITE_MESSAGES.PENDING_CREATE_DB(CloudJobStep.Credentials))) + } + })) + } + + const createFreeDatabase = (subscriptionId: number) => { + sendEventTelemetry({ + event: TelemetryEvent.CLOUD_CREATE_DATABASE_IN_SUBSCRIPTION, + }) + dispatch(createFreeDbJob({ + name: CloudJobName.CreateFreeDatabase, + resources: { subscriptionId }, + onSuccessAction: () => { + dispatch(removeInfiniteNotification(InfiniteMessagesIds.subscriptionExists)) + dispatch(addInfiniteNotification(INFINITE_MESSAGES.PENDING_CREATE_DB(CloudJobStep.Credentials))) + } + })) + } + + const closeImportDatabase = () => { + sendEventTelemetry({ + event: TelemetryEvent.CLOUD_IMPORT_EXISTING_DATABASE_FORM_CLOSED, + }) + dispatch(removeInfiniteNotification(InfiniteMessagesIds.databaseExists)) + } + + const closeCreateFreeDatabase = () => { + sendEventTelemetry({ + event: TelemetryEvent.CLOUD_CREATE_DATABASE_IN_SUBSCRIPTION_FORM_CLOSED, + }) + dispatch(removeInfiniteNotification(InfiniteMessagesIds.subscriptionExists)) + } + return null } diff --git a/redisinsight/ui/src/components/oauth/oauth-select-plan/OAuthSelectPlan.tsx b/redisinsight/ui/src/components/oauth/oauth-select-plan/OAuthSelectPlan.tsx index 4d643ead21..a77847634b 100644 --- a/redisinsight/ui/src/components/oauth/oauth-select-plan/OAuthSelectPlan.tsx +++ b/redisinsight/ui/src/components/oauth/oauth-select-plan/OAuthSelectPlan.tsx @@ -25,7 +25,7 @@ import { import { TelemetryEvent, sendEventTelemetry } from 'uiSrc/telemetry' import { addInfiniteNotification } from 'uiSrc/slices/app/notifications' import { INFINITE_MESSAGES } from 'uiSrc/components/notifications/components' -import { CloudJobStep } from 'uiSrc/electron/constants' +import { CloudJobName, CloudJobStep } from 'uiSrc/electron/constants' import { appFeatureFlagsFeaturesSelector } from 'uiSrc/slices/app/features' import { FeatureFlags, Theme } from 'uiSrc/constants' import { OAuthSocialSource, Region } from 'uiSrc/slices/interfaces' @@ -147,11 +147,14 @@ const OAuthSelectPlan = () => { } const handleSubmit = () => { - dispatch(createFreeDbJob(toNumber(planIdSelected), - () => { + dispatch(createFreeDbJob({ + name: CloudJobName.CreateFreeSubscriptionAndDatabase, + resources: { planId: toNumber(planIdSelected) }, + onSuccessAction: () => { dispatch(setIsOpenSelectPlanDialog(false)) dispatch(addInfiniteNotification(INFINITE_MESSAGES.PENDING_CREATE_DB(CloudJobStep.Credentials))) - })) + } + })) } return ( diff --git a/redisinsight/ui/src/constants/customErrorCodes.ts b/redisinsight/ui/src/constants/customErrorCodes.ts index 277b91395d..50ac2040eb 100644 --- a/redisinsight/ui/src/constants/customErrorCodes.ts +++ b/redisinsight/ui/src/constants/customErrorCodes.ts @@ -30,4 +30,5 @@ export enum CustomErrorCodes { CloudSubscriptionUnableToDetermine = 11_111, CloudTaskNotFound = 11_112, CloudJobNotFound = 11_113, + CloudSubscriptionAlreadyExistsFree = 11_114, } diff --git a/redisinsight/ui/src/electron/components/ConfigOAuth/ConfigOAuth.tsx b/redisinsight/ui/src/electron/components/ConfigOAuth/ConfigOAuth.tsx index 960da4a00f..31a2d37b9e 100644 --- a/redisinsight/ui/src/electron/components/ConfigOAuth/ConfigOAuth.tsx +++ b/redisinsight/ui/src/electron/components/ConfigOAuth/ConfigOAuth.tsx @@ -61,7 +61,7 @@ const ConfigOAuth = () => { const cloudOauthCallback = (_e: any, { status, message = '', error }: CloudAuthResponse) => { if (status === CloudAuthStatus.Succeed) { - dispatch(setJob({ id: '', name: CloudJobName.CreateFreeDatabase, status: '' })) + dispatch(setJob({ id: '', name: CloudJobName.CreateFreeSubscriptionAndDatabase, status: '' })) dispatch(showOAuthProgress(true)) dispatch(addInfiniteNotification(INFINITE_MESSAGES.PENDING_CREATE_DB(CloudJobStep.Credentials))) dispatch(setSignInDialogState(null)) diff --git a/redisinsight/ui/src/electron/constants/cloudAuth.ts b/redisinsight/ui/src/electron/constants/cloudAuth.ts index 0ae762e9a3..8163677c82 100644 --- a/redisinsight/ui/src/electron/constants/cloudAuth.ts +++ b/redisinsight/ui/src/electron/constants/cloudAuth.ts @@ -25,11 +25,14 @@ export enum CloudJobStep { Credentials = 'credentials', Subscription = 'subscription', Database = 'database', + Import = 'import', } export enum CloudJobName { CreateFreeDatabase = 'CREATE_FREE_DATABASE', CreateFreeSubscription = 'CREATE_FREE_SUBSCRIPTION', + CreateFreeSubscriptionAndDatabase = 'CREATE_FREE_SUBSCRIPTION_AND_DATABASE', + ImportFreeDatabase = 'IMPORT_FREE_DATABASE', WaitForActiveDatabase = 'WAIT_FOR_ACTIVE_DATABASE', WaitForActiveSubscription = 'WAIT_FOR_ACTIVE_SUBSCRIPTION', WaitForTask = 'WAIT_FOR_TASK', diff --git a/redisinsight/ui/src/slices/oauth/cloud.ts b/redisinsight/ui/src/slices/oauth/cloud.ts index c077a3520f..bb5ec53041 100644 --- a/redisinsight/ui/src/slices/oauth/cloud.ts +++ b/redisinsight/ui/src/slices/oauth/cloud.ts @@ -11,6 +11,7 @@ import { InfiniteMessagesIds } from 'uiSrc/components/notifications/components' import successMessages from 'uiSrc/components/notifications/success-messages' +import { getCloudSsoUtmParams } from 'uiSrc/utils/oauth/cloudSsoUtm' import { CloudUser } from 'apiSrc/modules/cloud/user/models' import { CloudJobInfo } from 'apiSrc/modules/cloud/job/models' import { CloudSubscriptionPlanResponse } from 'apiSrc/modules/cloud/subscription/dto' @@ -32,7 +33,6 @@ import { } from '../app/notifications' import { checkConnectToInstanceAction, setConnectedInstanceId } from '../instances/instances' import { setAppContextInitialState } from '../app/context' -import { getCloudSsoUtmParams } from 'uiSrc/utils/oauth/cloudSsoUtm'; export const initialState: StateAppOAuth = { loading: false, @@ -40,7 +40,7 @@ export const initialState: StateAppOAuth = { message: '', job: { id: localStorageService.get(BrowserStorageItem.OAuthJobId) ?? '', - name: CloudJobName.CreateFreeDatabase, + name: CloudJobName.CreateFreeSubscriptionAndDatabase, status: '', }, source: null, @@ -301,7 +301,21 @@ export function fetchUserInfo(onSuccessAction?: (isMultiAccount: boolean) => voi } // Asynchronous thunk action -export function createFreeDbJob(planId: number, onSuccessAction?: () => void, onFailAction?: () => void) { +export function createFreeDbJob({ + name, + resources = {}, + onSuccessAction, + onFailAction +}: { + name: CloudJobName, + resources?: { + planId?: number, + databaseId?: number, + subscriptionId?: number, + } + onSuccessAction?: () => void, + onFailAction?: () => void +}) { return async (dispatch: AppDispatch) => { dispatch(addFreeDb()) @@ -309,15 +323,17 @@ export function createFreeDbJob(planId: number, onSuccessAction?: () => void, on const { data, status } = await apiService.post( ApiEndpoints.CLOUD_ME_JOBS, { - name: CloudJobName.CreateFreeDatabase, + name, runMode: 'async', - data: { planId }, + data: resources, } ) if (isStatusSuccessful(status)) { localStorageService.set(BrowserStorageItem.OAuthJobId, data.id) - dispatch(setJob({ id: data.id, name: CloudJobName.CreateFreeDatabase, status: CloudJobStatus.Running })) + dispatch(setJob( + { id: data.id, name, status: CloudJobStatus.Running } + )) onSuccessAction?.() } } catch (_err) { diff --git a/redisinsight/ui/src/slices/tests/oauth/cloud.spec.ts b/redisinsight/ui/src/slices/tests/oauth/cloud.spec.ts index c5626b494d..1abf1c69ad 100644 --- a/redisinsight/ui/src/slices/tests/oauth/cloud.spec.ts +++ b/redisinsight/ui/src/slices/tests/oauth/cloud.spec.ts @@ -886,14 +886,18 @@ describe('oauth cloud slice', () => { describe('createFreeDb', () => { it('call both addFreeDb and setJob when post is successed', async () => { // Arrange - const data = { id: '123123', name: CloudJobName.CreateFreeDatabase, status: CloudJobStatus.Running } + const data = { + id: '123123', + name: CloudJobName.CreateFreeSubscriptionAndDatabase, + status: CloudJobStatus.Running, + } const responsePayload = { data, status: 200 } apiService.post = jest.fn().mockResolvedValue(responsePayload) apiService.get = jest.fn().mockResolvedValue(responsePayload) // Act - await store.dispatch(createFreeDbJob()) + await store.dispatch(createFreeDbJob({ name: CloudJobName.CreateFreeSubscriptionAndDatabase })) // Assert const expectedActions = [ @@ -916,7 +920,7 @@ describe('oauth cloud slice', () => { apiService.post = jest.fn().mockRejectedValueOnce(responsePayload) // Act - await store.dispatch(createFreeDbJob()) + await store.dispatch(createFreeDbJob({ name: CloudJobName.CreateFreeSubscriptionAndDatabase })) // Assert const expectedActions = [ diff --git a/redisinsight/ui/src/telemetry/events.ts b/redisinsight/ui/src/telemetry/events.ts index 215d0782b2..f8940e180e 100644 --- a/redisinsight/ui/src/telemetry/events.ts +++ b/redisinsight/ui/src/telemetry/events.ts @@ -259,6 +259,10 @@ export enum TelemetryEvent { CLOUD_IMPORT_DATABASES_CLICKED = 'CLOUD_IMPORT_DATABASES_CLICKED', CLOUD_API_KEY_REMOVED = 'CLOUD_API_KEY_REMOVED', CLOUD_LINK_CLICKED = 'CLOUD_LINK_CLICKED', + CLOUD_IMPORT_EXISTING_DATABASE = 'CLOUD_IMPORT_EXISTING_DATABASE', + CLOUD_IMPORT_EXISTING_DATABASE_FORM_CLOSED = 'CLOUD_IMPORT_EXISTING_DATABASE_FORM_CLOSED', + CLOUD_CREATE_DATABASE_IN_SUBSCRIPTION = 'CLOUD_CREATE_DATABASE_IN_SUBSCRIPTION', + CLOUD_CREATE_DATABASE_IN_SUBSCRIPTION_FORM_CLOSED = 'CLOUD_CREATE_DATABASE_IN_SUBSCRIPTION_FORM_CLOSED', TRIGGERS_AND_FUNCTIONS_LIBRARIES_SORTED = 'TRIGGERS_AND_FUNCTIONS_LIBRARIES_SORTED', TRIGGERS_AND_FUNCTIONS_LIBRARY_LIST_REFRESH_CLICKED = 'TRIGGERS_AND_FUNCTIONS_LIBRARY_LIST_REFRESH_CLICKED',