Skip to content

Commit b40c788

Browse files
committed
Merge branch 'feature/RI-4806-sso-feature-flag' into fe/feature/RI-4814-sso_from_triggers_and_functions
2 parents 6ca5cc6 + 9e12ab0 commit b40c788

File tree

7 files changed

+155
-66
lines changed

7 files changed

+155
-66
lines changed

redisinsight/api/src/modules/feature/feature.service.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { FeatureFlagProvider } from 'src/modules/feature/providers/feature-flag/
77
import { EventEmitter2, OnEvent } from '@nestjs/event-emitter';
88
import { FeatureAnalytics } from 'src/modules/feature/feature.analytics';
99
import { knownFeatures } from 'src/modules/feature/constants/known-features';
10+
import { Feature } from 'src/modules/feature/model/feature';
1011

1112
@Injectable()
1213
export class FeatureService {
@@ -38,7 +39,7 @@ export class FeatureService {
3839
/**
3940
* Returns list of features flags
4041
*/
41-
async list() {
42+
async list(): Promise<{ features: Record<string, Feature> }> {
4243
this.logger.log('Getting features list');
4344

4445
const features = {};
@@ -68,14 +69,6 @@ export class FeatureService {
6869
}
6970
});
7071

71-
try {
72-
this.analytics.sendFeatureFlagRecalculated({
73-
configVersion: (await this.featuresConfigRepository.getOrCreate())?.data?.version,
74-
features,
75-
});
76-
} catch (e) {
77-
// ignore telemetry error
78-
}
7972
return { features };
8073
}
8174

@@ -118,7 +111,17 @@ export class FeatureService {
118111
`Features flags recalculated. Updated: ${actions.toUpsert.length} deleted: ${actions.toDelete.length}`,
119112
);
120113

121-
this.eventEmitter.emit(FeatureServerEvents.FeaturesRecalculated, await this.list());
114+
const list = await this.list();
115+
this.eventEmitter.emit(FeatureServerEvents.FeaturesRecalculated, list);
116+
117+
try {
118+
this.analytics.sendFeatureFlagRecalculated({
119+
configVersion: (await this.featuresConfigRepository.getOrCreate())?.data?.version,
120+
features: list.features,
121+
});
122+
} catch (e) {
123+
// ignore telemetry error
124+
}
122125
} catch (e) {
123126
this.logger.error('Unable to recalculate features flags', e);
124127
}

redisinsight/ui/src/components/oauth/oauth-social/OAuthSocial.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ export enum OAuthSocialType {
2424

2525
interface Props {
2626
type?: OAuthSocialType
27+
hideTitle?: boolean
2728
}
2829

29-
const OAuthSocial = ({ type = OAuthSocialType.Modal }: Props) => {
30+
const OAuthSocial = ({ type = OAuthSocialType.Modal, hideTitle = false }: Props) => {
3031
const agreement = useSelector(oauthCloudPAgreementSelector)
3132

3233
const dispatch = useDispatch()
@@ -99,8 +100,12 @@ const OAuthSocial = ({ type = OAuthSocialType.Modal }: Props) => {
99100

100101
return (
101102
<div className={cx(styles.containerAuto)} data-testid="oauth-container-autodiscovery">
102-
<EuiTitle className={styles.title}><h4>Sign in to your Cloud Account</h4></EuiTitle>
103-
<EuiText className={styles.text} color="subdued">Auto-discover subscriptions and add your databases or create a free starter database</EuiText>
103+
{!hideTitle && (<EuiTitle className={styles.title}><h4>Sign in to your Cloud Account</h4></EuiTitle>)}
104+
<EuiText className={styles.text} color="subdued">
105+
Auto-discover subscriptions and add your databases.
106+
<br />
107+
A new Redis Enterprise Cloud account will be created for you if you don’t have one.
108+
</EuiText>
104109
<div className={styles.buttonsAuto}>
105110
{buttons}
106111
</div>
Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,49 @@
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 CloudConnectionForm, { Props } from './CloudConnectionForm'
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+
cloudSso: {
13+
flag: false,
14+
}
15+
}),
16+
}))
17+
818
describe('CloudConnectionForm', () => {
919
it('should render', () => {
1020
expect(
1121
render(<CloudConnectionForm {...instance(mockedProps)} />)
1222
).toBeTruthy()
1323
})
24+
25+
it('should not render cloud sso form by default', () => {
26+
render(<CloudConnectionForm {...instance(mockedProps)} />)
27+
expect(screen.queryByTestId('use-cloud-account-accordion')).not.toBeInTheDocument()
28+
expect(screen.queryByTestId('use-cloud-keys-accordion')).not.toBeInTheDocument()
29+
30+
expect(screen.getByTestId('access-key')).toBeInTheDocument()
31+
expect(screen.getByTestId('secret-key')).toBeInTheDocument()
32+
})
33+
34+
it('should render cloud sso form and collapsible nav groups with feature flag', () => {
35+
(appFeatureFlagsFeaturesSelector as jest.Mock).mockReturnValue({
36+
cloudSso: {
37+
flag: true
38+
}
39+
})
40+
41+
render(<CloudConnectionForm {...instance(mockedProps)} />)
42+
43+
expect(screen.getByTestId('use-cloud-account-accordion')).toBeInTheDocument()
44+
expect(screen.getByTestId('use-cloud-keys-accordion')).toBeInTheDocument()
45+
46+
expect(screen.getByTestId('access-key')).toBeInTheDocument()
47+
expect(screen.getByTestId('secret-key')).toBeInTheDocument()
48+
})
1449
})

redisinsight/ui/src/pages/home/components/CloudConnection/CloudConnectionForm/CloudConnectionForm.tsx

Lines changed: 69 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ import { useFormik, FormikErrors } from 'formik'
44
import { isEmpty } from 'lodash'
55
import {
66
EuiButton,
7+
EuiCollapsibleNavGroup,
78
EuiFieldText,
89
EuiFlexGroup,
910
EuiFlexItem,
1011
EuiForm,
1112
EuiFormRow,
1213
EuiLink,
1314
EuiText,
14-
EuiTitle,
1515
EuiToolTip,
1616
EuiWindowEvent,
1717
keys,
@@ -52,9 +52,6 @@ const fieldDisplayNames: Values = {
5252

5353
const Message = () => (
5454
<>
55-
<FeatureFlagComponent name={FeatureFlags.cloudSso}>
56-
<EuiTitle className={styles.messageTitle}><h4>Use Cloud API key</h4></EuiTitle>
57-
</FeatureFlagComponent>
5855
<EuiText color="subdued" size="s" className={styles.message} data-testid="summary">
5956
{`Enter API keys to discover and add databases.
6057
API keys can be enabled by following the steps
@@ -180,57 +177,79 @@ const CloudConnectionForm = (props: Props) => {
180177
return null
181178
}
182179

180+
const CloudApiForm = (
181+
<div className={styles.cloudApi}>
182+
<Message />
183+
<br />
184+
<EuiWindowEvent event="keydown" handler={onKeyDown} />
185+
<EuiForm component="form" onSubmit={formik.handleSubmit}>
186+
<EuiFlexGroup className={flexGroupClassName}>
187+
<EuiFlexItem className={flexItemClassName}>
188+
<EuiFormRow label="API Account Key*">
189+
<EuiFieldText
190+
name="accessKey"
191+
id="accessKey"
192+
data-testid="access-key"
193+
maxLength={200}
194+
placeholder={fieldDisplayNames.accessKey}
195+
value={formik.values.accessKey}
196+
autoComplete="off"
197+
onChange={(e: ChangeEvent<HTMLInputElement>) => {
198+
formik.setFieldValue(e.target.name, validateField(e.target.value.trim()))
199+
}}
200+
/>
201+
</EuiFormRow>
202+
</EuiFlexItem>
203+
</EuiFlexGroup>
204+
<EuiFlexGroup className={flexGroupClassName}>
205+
<EuiFlexItem className={flexItemClassName}>
206+
<EuiFormRow label="API User Key*">
207+
<EuiFieldText
208+
name="secretKey"
209+
id="secretKey"
210+
data-testid="secret-key"
211+
maxLength={200}
212+
placeholder={fieldDisplayNames.secretKey}
213+
value={formik.values.secretKey}
214+
autoComplete="off"
215+
onChange={(e: ChangeEvent<HTMLInputElement>) => {
216+
formik.setFieldValue(e.target.name, validateField(e.target.value.trim()))
217+
}}
218+
/>
219+
</EuiFormRow>
220+
</EuiFlexItem>
221+
</EuiFlexGroup>
222+
<Footer />
223+
</EuiForm>
224+
</div>
225+
)
226+
183227
return (
184228
<>
185229
<div className="getStartedForm">
186230
<FeatureFlagComponent name={FeatureFlags.cloudSso}>
187-
<OAuthSocial type={OAuthSocialType.Autodiscovery} />
188-
<div className={styles.divider}>OR</div>
231+
<EuiText color="subdued" size="s">Connect with:</EuiText>
232+
<EuiCollapsibleNavGroup
233+
isCollapsible
234+
className={styles.accordion}
235+
title="Use Cloud Account"
236+
initialIsOpen={false}
237+
data-testid="use-cloud-account-accordion"
238+
>
239+
<OAuthSocial type={OAuthSocialType.Autodiscovery} hideTitle />
240+
</EuiCollapsibleNavGroup>
241+
</FeatureFlagComponent>
242+
<FeatureFlagComponent name={FeatureFlags.cloudSso} otherwise={CloudApiForm}>
243+
<EuiCollapsibleNavGroup
244+
isCollapsible
245+
className={styles.accordion}
246+
title="Use Cloud API Keys"
247+
initialIsOpen={false}
248+
data-testid="use-cloud-keys-accordion"
249+
>
250+
{CloudApiForm}
251+
</EuiCollapsibleNavGroup>
189252
</FeatureFlagComponent>
190-
<div className={styles.cloudApi}>
191-
<Message />
192-
<br />
193-
<EuiWindowEvent event="keydown" handler={onKeyDown} />
194-
<EuiForm component="form" onSubmit={formik.handleSubmit}>
195-
<EuiFlexGroup className={flexGroupClassName}>
196-
<EuiFlexItem className={flexItemClassName}>
197-
<EuiFormRow label="API Account Key*">
198-
<EuiFieldText
199-
name="accessKey"
200-
id="accessKey"
201-
data-testid="access-key"
202-
maxLength={200}
203-
placeholder={fieldDisplayNames.accessKey}
204-
value={formik.values.accessKey}
205-
autoComplete="off"
206-
onChange={(e: ChangeEvent<HTMLInputElement>) => {
207-
formik.setFieldValue(e.target.name, validateField(e.target.value.trim()))
208-
}}
209-
/>
210-
</EuiFormRow>
211-
</EuiFlexItem>
212-
</EuiFlexGroup>
213-
<EuiFlexGroup className={flexGroupClassName}>
214-
<EuiFlexItem className={flexItemClassName}>
215-
<EuiFormRow label="API User Key*">
216-
<EuiFieldText
217-
name="secretKey"
218-
id="secretKey"
219-
data-testid="secret-key"
220-
maxLength={200}
221-
placeholder={fieldDisplayNames.secretKey}
222-
value={formik.values.secretKey}
223-
autoComplete="off"
224-
onChange={(e: ChangeEvent<HTMLInputElement>) => {
225-
formik.setFieldValue(e.target.name, validateField(e.target.value.trim()))
226-
}}
227-
/>
228-
</EuiFormRow>
229-
</EuiFlexItem>
230-
</EuiFlexGroup>
231-
<Footer />
232-
</EuiForm>
233-
</div>
234253
</div>
235254
</>
236255
)

redisinsight/ui/src/pages/home/components/CloudConnection/styles.module.scss

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,28 @@
5757
font-family: "Graphik", sans-serif;
5858
color: var(--euiTextSubduedColor) !important;
5959
}
60+
61+
.accordion {
62+
background: var(--euiColorLightestShade);
63+
border-radius: 4px;
64+
padding: 12px 18px !important;
65+
margin-top: 14px !important;
66+
67+
:global {
68+
.euiAccordion__triggerWrapper {
69+
background: var(--euiColorLightestShade);
70+
padding: 0 !important;
71+
}
72+
73+
.euiAccordion__triggerWrapper h3 {
74+
font-size: 14px !important;
75+
line-height: 14px !important;
76+
font-weight: 400 !important;
77+
height: auto !important;
78+
}
79+
80+
.euiCollapsibleNavGroup__children {
81+
padding: 12px 0 0 !important;
82+
}
83+
}
84+
}

redisinsight/ui/src/pages/home/components/WelcomeComponent/WelcomeComponent.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,15 @@ const Welcome = ({ onAddInstance }: Props) => {
160160
handleClickLink(HELP_LINKS.cloud.event, { source: OAuthSocialSource.WelcomeScreen })
161161
ssoCloudHandlerClick(e, OAuthSocialSource.WelcomeScreen)
162162
}}
163+
target="_blank"
163164
style={{
164165
...linkStyles,
165166
backgroundImage: linkStyles?.backgroundImage
166167
? `url(${getPathToResource(linkStyles.backgroundImage)})`
167168
: undefined
168169
}}
169170
data-testid="promo-btn"
171+
rel="noreferrer"
170172
>
171173
<EuiIcon className={styles.btnIcon} type={CloudStars} />
172174
<div className={styles.btnContent}>

redisinsight/ui/src/pages/home/components/WelcomeComponent/styles.module.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,10 @@
9494
}
9595
}
9696

97-
.promoButton {
97+
.btn.promoButton {
9898
min-height: 80px;
9999

100-
color: var(--htmlColor);
100+
color: var(--htmlColor) !important;
101101
}
102102

103103
.logo {

0 commit comments

Comments
 (0)