Skip to content

Commit 8a4a1db

Browse files
authored
Merge pull request #4086 from RedisInsight/be/feature/RI-6320-add-feature-flag
#RI-6320 - add feature flag for cloud db in the list of dbs
2 parents 69224f6 + 96e18c2 commit 8a4a1db

File tree

17 files changed

+263
-15
lines changed

17 files changed

+263
-15
lines changed

redisinsight/api/config/features-config.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": 2.56,
2+
"version": 2.57,
33
"features": {
44
"redisDataIntegration": {
55
"flag": true,
@@ -111,6 +111,10 @@
111111
"data": {
112112
"strategy": "ioredis"
113113
}
114+
},
115+
"enhancedCloudUI": {
116+
"flag": true,
117+
"perc": [[0, 50]]
114118
}
115119
}
116120
}

redisinsight/api/src/modules/feature/constants/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export enum KnownFeatures {
2929
DatabaseChat = 'databaseChat',
3030
Rdi = 'redisDataIntegration',
3131
HashFieldExpiration = 'hashFieldExpiration',
32+
EnhancedCloudUI = 'enhancedCloudUI',
3233
}
3334

3435
export interface IFeatureFlag {

redisinsight/api/src/modules/feature/constants/known-features.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,8 @@ export const knownFeatures: Record<KnownFeatures, IFeatureFlag> = {
3939
name: KnownFeatures.Rdi,
4040
storage: FeatureStorage.Database,
4141
},
42+
[KnownFeatures.EnhancedCloudUI]: {
43+
name: KnownFeatures.EnhancedCloudUI,
44+
storage: FeatureStorage.Database,
45+
},
4246
};

redisinsight/api/src/modules/feature/providers/feature-flag/feature-flag.provider.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ export class FeatureFlagProvider {
6060
this.featuresConfigService,
6161
this.settingsService,
6262
));
63+
this.strategies.set(KnownFeatures.EnhancedCloudUI, new WithDataFlagStrategy(
64+
this.featuresConfigService,
65+
this.settingsService,
66+
));
6367
}
6468

6569
getStrategy(name: string): FeatureFlagStrategy {

redisinsight/ui/src/constants/featureFlags.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ export enum FeatureFlags {
77
disabledByEnv = 'disabledByEnv',
88
rdi = 'redisDataIntegration',
99
hashFieldExpiration = 'hashFieldExpiration',
10+
enhancedCloudUI = 'enhancedCloudUI',
1011
}

redisinsight/ui/src/pages/home/HomePage.spec.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react'
22
import { render, screen } from 'uiSrc/utils/test-utils'
3+
import { appFeatureFlagsFeaturesSelector } from 'uiSrc/slices/app/features'
34
import HomePage from './HomePage'
45

56
jest.mock('uiSrc/slices/panels/sidePanels', () => ({
@@ -9,6 +10,24 @@ jest.mock('uiSrc/slices/panels/sidePanels', () => ({
910
}),
1011
}))
1112

13+
jest.mock('uiSrc/slices/content/create-redis-buttons', () => ({
14+
...jest.requireActual('uiSrc/slices/content/create-redis-buttons'),
15+
contentSelector: jest.fn().mockReturnValue({
16+
data: {
17+
cloud_list_of_databases: {}
18+
}
19+
}),
20+
}))
21+
22+
jest.mock('uiSrc/slices/app/features', () => ({
23+
...jest.requireActual('uiSrc/slices/app/features'),
24+
appFeatureFlagsFeaturesSelector: jest.fn().mockReturnValue({
25+
enhancedCloudUI: {
26+
flag: false
27+
}
28+
}),
29+
}))
30+
1231
/**
1332
* HomePage tests
1433
*
@@ -30,4 +49,26 @@ describe('HomePage', () => {
3049

3150
expect(screen.getByTestId('side-panels-insights')).toBeInTheDocument()
3251
})
52+
53+
it('should not render free cloud db with feature flag disabled', async () => {
54+
(appFeatureFlagsFeaturesSelector as jest.Mock).mockReturnValueOnce({
55+
enhancedCloudUI: {
56+
flag: false
57+
}
58+
})
59+
await render(<HomePage />)
60+
61+
expect(screen.queryByTestId('db-row_create-free-cloud-db')).not.toBeInTheDocument()
62+
})
63+
64+
it('should render free cloud db with feature flag enabled', async () => {
65+
(appFeatureFlagsFeaturesSelector as jest.Mock).mockReturnValueOnce({
66+
enhancedCloudUI: {
67+
flag: true
68+
}
69+
})
70+
await render(<HomePage />)
71+
72+
expect(screen.getByTestId('db-row_create-free-cloud-db')).toBeInTheDocument()
73+
})
3374
})

redisinsight/ui/src/pages/home/HomePage.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { useDispatch, useSelector } from 'react-redux'
88
import { clusterSelector, resetDataRedisCluster, resetInstancesRedisCluster, } from 'uiSrc/slices/instances/cluster'
99
import { Nullable, setTitle } from 'uiSrc/utils'
1010
import { HomePageTemplate } from 'uiSrc/templates'
11-
import { BrowserStorageItem } from 'uiSrc/constants'
11+
import { BrowserStorageItem, FeatureFlags } from 'uiSrc/constants'
1212
import { resetKeys } from 'uiSrc/slices/browser/keys'
1313
import { resetCliHelperSettings, resetCliSettingsAction } from 'uiSrc/slices/cli/cli-settings'
1414
import { resetRedisearchKeysData } from 'uiSrc/slices/browser/redisearch'
@@ -41,6 +41,7 @@ import DatabasePanelDialog from './components/database-panel-dialog'
4141

4242
import './styles.scss'
4343
import styles from './styles.module.scss'
44+
import { appFeatureFlagsFeaturesSelector } from 'uiSrc/slices/app/features'
4445

4546
enum OpenDialogName {
4647
AddDatabase = 'add',
@@ -58,6 +59,7 @@ const HomePage = () => {
5859
const { instance: sentinelInstance } = useSelector(sentinelSelector)
5960
const { action, dbConnection } = useSelector(appRedirectionSelector)
6061
const { data: createDbContent } = useSelector(contentSelector)
62+
const { [FeatureFlags.enhancedCloudUI]: enhancedCloudUIFeature } = useSelector(appFeatureFlagsFeaturesSelector)
6163

6264
const {
6365
loading,
@@ -73,7 +75,7 @@ const HomePage = () => {
7375

7476
const { contextInstanceId } = useSelector(appContextSelector)
7577

76-
const predefinedInstances = createDbContent?.cloud_list_of_databases ? [
78+
const predefinedInstances = enhancedCloudUIFeature?.flag && createDbContent?.cloud_list_of_databases ? [
7779
{ id: CREATE_CLOUD_DB_ID, ...createDbContent.cloud_list_of_databases } as Instance
7880
] : []
7981
const isInstanceExists = instances.length > 0 || predefinedInstances.length > 0

redisinsight/ui/src/pages/home/components/database-list-component/DatabasesListWrapper.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ describe('DatabasesListWrapper', () => {
120120

121121
expect(store.getActions()).toEqual([
122122
setSSOFlow(OAuthSocialAction.Create),
123-
setSocialDialogState(OAuthSocialSource.ListOfDatabases)
123+
setSocialDialogState(OAuthSocialSource.DatabaseConnectionList)
124124
])
125125
})
126126

redisinsight/ui/src/pages/home/components/database-list-component/DatabasesListWrapper.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import {
22
Criteria,
33
EuiButtonIcon,
44
EuiIcon,
5-
EuiLink, EuiResizeObserver,
5+
EuiLink,
6+
EuiResizeObserver,
67
EuiTableFieldDataColumnType,
78
EuiText,
89
EuiTextColor,
@@ -53,7 +54,7 @@ import { setSSOFlow } from 'uiSrc/slices/instances/cloud'
5354
import { setSocialDialogState } from 'uiSrc/slices/oauth/cloud'
5455
import { appFeatureFlagsFeaturesSelector } from 'uiSrc/slices/app/features'
5556
import { getUtmExternalLink } from 'uiSrc/utils/links'
56-
import { CREATE_CLOUD_DB_ID } from 'uiSrc/pages/home/constants'
57+
import { CREATE_CLOUD_DB_ID, HELP_LINKS } from 'uiSrc/pages/home/constants'
5758
import styles from './styles.module.scss'
5859

5960
export interface Props {
@@ -243,10 +244,19 @@ const DatabasesListWrapper = (props: Props) => {
243244
const handleClickFreeDb = () => {
244245
if (cloudSsoFeature?.flag) {
245246
dispatch(setSSOFlow(OAuthSocialAction.Create))
246-
dispatch(setSocialDialogState(OAuthSocialSource.ListOfDatabases))
247+
dispatch(setSocialDialogState(OAuthSocialSource.DatabaseConnectionList))
248+
sendEventTelemetry({
249+
event: TelemetryEvent.CLOUD_FREE_DATABASE_CLICKED,
250+
eventData: { source: OAuthSocialSource.DatabaseConnectionList },
251+
})
247252
return
248253
}
249254

255+
sendEventTelemetry({
256+
event: HELP_LINKS.cloud.event,
257+
eventData: { source: HELP_LINKS.cloud.sources.databaseConnectionList },
258+
})
259+
250260
const link = document.createElement('a')
251261
link.setAttribute('href', getUtmExternalLink(EXTERNAL_LINKS.tryFree, { campaign: 'list_of_databases' }))
252262
link.setAttribute('target', '_blank')

redisinsight/ui/src/pages/home/components/database-list-header/DatabaseListHeader.spec.tsx

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,38 @@
11
import React from 'react'
22
import { instance, mock } from 'ts-mockito'
3-
import { render } from 'uiSrc/utils/test-utils'
3+
import { render, screen } from 'uiSrc/utils/test-utils'
4+
import { appFeatureFlagsFeaturesSelector } from 'uiSrc/slices/app/features'
45
import DatabaseListHeader, { Props } from './DatabaseListHeader'
56

67
const mockedProps = mock<Props>()
78

9+
jest.mock('uiSrc/slices/app/features', () => ({
10+
...jest.requireActual('uiSrc/slices/app/features'),
11+
appFeatureFlagsFeaturesSelector: jest.fn().mockReturnValue({
12+
enhancedCloudUI: {
13+
flag: false
14+
}
15+
}),
16+
}))
17+
18+
jest.mock('uiSrc/slices/content/create-redis-buttons', () => ({
19+
...jest.requireActual('uiSrc/slices/content/create-redis-buttons'),
20+
contentSelector: jest.fn().mockReturnValue({
21+
data: {
22+
cloud: {
23+
title: 'Try Redis Cloud: your ultimate Redis starting point',
24+
description: 'Includes native support for JSON, Search and Query, and more',
25+
links: {
26+
main: {
27+
altText: 'Try Redis Cloud.',
28+
url: 'https://redis.io/try-free/?utm_source=redisinsight&utm_medium=main&utm_campaign=main'
29+
}
30+
},
31+
}
32+
}
33+
}),
34+
}))
35+
836
jest.mock('uiSrc/telemetry', () => ({
937
...jest.requireActual('uiSrc/telemetry'),
1038
sendEventTelemetry: jest.fn(),
@@ -14,4 +42,28 @@ describe('DatabaseListHeader', () => {
1442
it('should render', () => {
1543
expect(render(<DatabaseListHeader {...instance(mockedProps)} />)).toBeTruthy()
1644
})
45+
46+
it('should not show promo cloud button with disabled feature flag', () => {
47+
(appFeatureFlagsFeaturesSelector as jest.Mock).mockReturnValueOnce({
48+
enhancedCloudUI: {
49+
flag: true
50+
}
51+
})
52+
53+
render(<DatabaseListHeader {...instance(mockedProps)} />)
54+
55+
expect(screen.queryByTestId('promo-btn')).not.toBeInTheDocument()
56+
})
57+
58+
it('should show promo cloud button with enabled feature flag', () => {
59+
(appFeatureFlagsFeaturesSelector as jest.Mock).mockReturnValueOnce({
60+
enhancedCloudUI: {
61+
flag: false
62+
}
63+
})
64+
65+
render(<DatabaseListHeader {...instance(mockedProps)} />)
66+
67+
expect(screen.getByTestId('promo-btn')).toBeInTheDocument()
68+
})
1769
})

0 commit comments

Comments
 (0)