Skip to content

Commit c8ae0da

Browse files
new modal and plugin
1 parent c2025de commit c8ae0da

File tree

12 files changed

+501
-28
lines changed

12 files changed

+501
-28
lines changed

packages/compass-generative-ai/src/atlas-ai-service.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import type { Document } from 'mongodb';
1010
import type { Logger } from '@mongodb-js/compass-logging';
1111
import { EJSON } from 'bson';
1212
import { signIntoAtlasWithModalPrompt } from './store/atlas-signin-reducer';
13-
import { getStore } from './store/atlas-signin-store';
13+
import { getStore } from './store/atlas-ai-store';
14+
import { optIntoGenAIWithModalPrompt } from './store/atlas-optin-reducer';
1415

1516
type GenerativeAiInput = {
1617
userInput: string;
@@ -329,6 +330,10 @@ export class AtlasAiService {
329330
async ensureAiFeatureAccess({ signal }: { signal?: AbortSignal } = {}) {
330331
// When the ai feature is attempted to be opened we make sure
331332
// the user is signed into Atlas and opted in.
333+
334+
if (this.apiURLPreset === 'cloud') {
335+
return getStore().dispatch(optIntoGenAIWithModalPrompt({ signal }));
336+
}
332337
return getStore().dispatch(signIntoAtlasWithModalPrompt({ signal }));
333338
}
334339

@@ -437,6 +442,30 @@ export class AtlasAiService {
437442
);
438443
}
439444

445+
// optIn function w post request to set the user preference to true
446+
async optIntoGenAIFeaturesAtlas() {
447+
const res = await this.atlasService.authenticatedFetch(
448+
this.atlasService.cloudEndpoint(
449+
'/settings/optInDataExplorerGenAIFeatures'
450+
),
451+
{
452+
method: 'POST',
453+
body: JSON.stringify({
454+
isEnabled: true,
455+
}),
456+
headers: {
457+
'Content-Type': 'application/json',
458+
Accept: 'application/json',
459+
},
460+
}
461+
);
462+
if (res.ok) {
463+
await this.preferences.savePreferences({
464+
enableGenAIFeatures: true,
465+
});
466+
}
467+
}
468+
440469
private validateAIFeatureEnablementResponse(
441470
response: any
442471
): asserts response is AIFeatureEnablement {
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import React from 'react';
2+
import { connect } from 'react-redux';
3+
import {
4+
Body,
5+
Link,
6+
MarketingModal,
7+
css,
8+
spacing,
9+
useDarkMode,
10+
} from '@mongodb-js/compass-components';
11+
import { AISignInImageBanner } from './ai-signin-banner-image';
12+
import {
13+
closeOptInModal,
14+
optIn,
15+
type AtlasOptInState,
16+
} from '../store/atlas-optin-reducer';
17+
18+
const GEN_AI_FAQ_LINK = 'https://www.mongodb.com/docs/generative-ai-faq/';
19+
20+
type OptInModalProps = {
21+
isOptInModalVisible?: boolean;
22+
isOptInInProgress?: boolean;
23+
onOptInModalClose?: () => void;
24+
onOptInClick?: () => void;
25+
};
26+
27+
const titleStyles = css({
28+
marginBottom: spacing[400],
29+
display: 'flex',
30+
flexDirection: 'column',
31+
alignItems: 'center',
32+
});
33+
34+
const disclaimer = css({
35+
padding: `0 ${spacing[900]}px`,
36+
});
37+
38+
const AIOptInModal: React.FunctionComponent<OptInModalProps> = ({
39+
isOptInModalVisible,
40+
isOptInInProgress,
41+
onOptInModalClose,
42+
onOptInClick,
43+
}) => {
44+
const darkMode = useDarkMode();
45+
46+
return (
47+
<MarketingModal
48+
darkMode={darkMode}
49+
disclaimer={
50+
<div className={disclaimer}>
51+
This is a feature powered by generative AI, and may give inaccurate
52+
responses. Please see our{' '}
53+
<Link hideExternalIcon={false} href={GEN_AI_FAQ_LINK} target="_blank">
54+
FAQ
55+
</Link>{' '}
56+
for more information.
57+
</div>
58+
}
59+
graphic={<AISignInImageBanner></AISignInImageBanner>}
60+
title={
61+
<div className={titleStyles}>
62+
Use natural language to generate queries and pipelines
63+
</div>
64+
}
65+
open={isOptInModalVisible}
66+
onClose={onOptInModalClose}
67+
buttonText="Opt In to Generative AI Features"
68+
onButtonClick={() => {
69+
// We can't control buttons in marketing modal, so instead we just do
70+
// nothing when button is clicked and sign in is in progress
71+
if (isOptInInProgress) {
72+
return;
73+
}
74+
onOptInClick?.();
75+
}}
76+
linkText="Back to Classic Mode"
77+
onLinkClick={onOptInModalClose}
78+
>
79+
<Body>
80+
Atlas users can now quickly create queries and aggregations with
81+
MongoDB&apos;s&nbsp; intelligent AI-powered feature, available today in
82+
Compass.
83+
</Body>
84+
</MarketingModal>
85+
);
86+
};
87+
88+
export default connect(
89+
(state: AtlasOptInState) => {
90+
return {
91+
isOptInModalVisible: state.optInReducer.isModalOpen,
92+
isOptInInProgress: state.state === 'in-progress',
93+
};
94+
},
95+
{ onOptInModalClose: closeOptInModal, onOptInClick: optIn }
96+
)(AIOptInModal);
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import {
1111
useDarkMode,
1212
} from '@mongodb-js/compass-components';
1313
import { AISignInImageBanner } from './ai-signin-banner-image';
14-
import type { AtlasSignInState } from '../../store/atlas-signin-reducer';
15-
import { closeSignInModal, signIn } from '../../store/atlas-signin-reducer';
14+
import type { AtlasSignInState } from '../store/atlas-signin-reducer';
15+
import { closeSignInModal, signIn } from '../store/atlas-signin-reducer';
1616

1717
const GEN_AI_FAQ_LINK = 'https://www.mongodb.com/docs/generative-ai-faq/';
1818

@@ -102,7 +102,7 @@ const AISignInModal: React.FunctionComponent<SignInModalProps> = ({
102102
export default connect(
103103
(state: AtlasSignInState) => {
104104
return {
105-
isSignInModalVisible: state.isModalOpen,
105+
isSignInModalVisible: state.signInReducer.isModalOpen,
106106
isSignInInProgress: state.state === 'in-progress',
107107
};
108108
},

packages/compass-generative-ai/src/components/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ export {
33
AIExperienceEntry,
44
createAIPlaceholderHTMLPlaceholder,
55
} from './ai-experience-entry';
6-
export { AtlasSignIn } from './atlas-signin';
6+
export { AtlasAiPlugin } from './plugin';
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import React from 'react';
22
import AISignInModal from './ai-signin-modal';
3+
import AIOptInModal from './ai-optin-modal';
34
import { ConfirmationModalArea } from '@mongodb-js/compass-components';
45

5-
export const AtlasSignIn = () => {
6+
7+
export const AtlasAiPlugin = () => {
68
return (
79
<ConfirmationModalArea>
810
<AISignInModal></AISignInModal>
11+
<AIOptInModal></AIOptInModal>
912
</ConfirmationModalArea>
1013
);
11-
};
14+
};

packages/compass-generative-ai/src/index.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
import { registerHadronPlugin } from 'hadron-app-registry';
22
import { atlasAuthServiceLocator } from '@mongodb-js/atlas-service/provider';
33

4-
import { activatePlugin } from './store/atlas-signin-store';
5-
import { AtlasSignIn } from './components';
4+
import { activatePlugin } from './store/atlas-ai-store';
5+
import { AtlasAiPlugin } from './components';
6+
import { atlasAiServiceLocator } from './provider';
67

78
export const CompassGenerativeAIPlugin = registerHadronPlugin(
89
{
910
name: 'CompassGenerativeAI',
10-
component: AtlasSignIn,
11+
component: AtlasAiPlugin,
1112
activate: activatePlugin,
1213
},
1314
{
1415
atlasAuthService: atlasAuthServiceLocator,
16+
atlasAiService: atlasAiServiceLocator,
1517
}
1618
);
1719

packages/compass-generative-ai/src/store/atlas-signin-store.ts renamed to packages/compass-generative-ai/src/store/atlas-ai-store.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
import { createStore, applyMiddleware } from 'redux';
1+
import { createStore, applyMiddleware, combineReducers } from 'redux';
22
import thunk from 'redux-thunk';
3-
import reducer, {
3+
import signInReducer, {
44
atlasServiceSignedOut,
55
atlasServiceSignedIn,
6-
atlasServiceTokenRefreshFailed,
6+
//atlasServiceSignInTokenRefreshFailed,
77
} from './atlas-signin-reducer';
8+
import optInReducer, {/*atlasAiServiceOptedIn,*/ atlasServiceOptInTokenRefreshFailed } from './atlas-optin-reducer';
89
import type { AtlasAuthService } from '@mongodb-js/atlas-service/provider';
910
import type { ActivateHelpers } from 'hadron-app-registry';
11+
import type { AtlasAiService } from '../atlas-ai-service';
1012

1113
let store: CompassGenerativeAIServiceStore;
1214
export function getStore() {
@@ -15,17 +17,22 @@ export function getStore() {
1517
}
1618
return store;
1719
}
20+
const reducer = combineReducers({
21+
signInReducer,
22+
optInReducer
23+
});
1824

1925
export type CompassGenerativeAIPluginServices = {
2026
atlasAuthService: AtlasAuthService;
27+
atlasAiService: AtlasAiService
2128
};
2229
export function activatePlugin(
2330
_: Record<string, never>,
2431
services: CompassGenerativeAIPluginServices,
2532
{ cleanup }: ActivateHelpers
2633
) {
2734
store = configureStore(services);
28-
35+
console.log(services.atlasAiService)
2936
services.atlasAuthService.on('signed-in', () => {
3037
void store.dispatch(atlasServiceSignedIn());
3138
});
@@ -35,18 +42,17 @@ export function activatePlugin(
3542
});
3643

3744
services.atlasAuthService.on('token-refresh-failed', () => {
38-
void store.dispatch(atlasServiceTokenRefreshFailed());
45+
void store.dispatch(atlasServiceOptInTokenRefreshFailed());
3946
});
40-
4147
return { store, deactivate: cleanup };
4248
}
4349

4450
export function configureStore({
45-
atlasAuthService,
51+
atlasAuthService, atlasAiService
4652
}: CompassGenerativeAIPluginServices) {
4753
const store = createStore(
4854
reducer,
49-
applyMiddleware(thunk.withExtraArgument({ atlasAuthService }))
55+
applyMiddleware(thunk.withExtraArgument({ atlasAuthService, atlasAiService }))
5056
);
5157
return store;
5258
}

0 commit comments

Comments
 (0)