Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c2025de
moving prefs up nit from prev ticket
ruchitharajaghatta Nov 8, 2024
c8ae0da
new modal and plugin
ruchitharajaghatta Nov 13, 2024
ae6fa98
removing console log
ruchitharajaghatta Nov 13, 2024
ab8a8eb
review comments and checking for userPref
ruchitharajaghatta Nov 13, 2024
842007a
review comments and checking for userPref
ruchitharajaghatta Nov 13, 2024
be9d03d
PR comments
ruchitharajaghatta Nov 14, 2024
f116d9e
PR comments
ruchitharajaghatta Nov 14, 2024
ee684c7
reducer name change bug
ruchitharajaghatta Nov 14, 2024
cdbfa92
fixing post request
ruchitharajaghatta Nov 14, 2024
c09dd67
fixing test setup failures
ruchitharajaghatta Nov 14, 2024
8cda9e9
new test and sign in test fixes
ruchitharajaghatta Nov 14, 2024
102306b
Merge branch 'main' of github.com:mongodb-js/compass into COMPASS-8378
ruchitharajaghatta Nov 14, 2024
514816c
test fixes and package.json fix
ruchitharajaghatta Nov 15, 2024
59bdf04
state name update
ruchitharajaghatta Nov 15, 2024
d2c0290
test and reducer bug fixes
ruchitharajaghatta Nov 15, 2024
3803589
commenting out errors for evg patch
ruchitharajaghatta Nov 15, 2024
ce2cccd
fixing reducer type and entrypoint
ruchitharajaghatta Nov 18, 2024
b41dbda
npm check fix
ruchitharajaghatta Nov 18, 2024
618d1de
removing ts-expect-errors
ruchitharajaghatta Nov 18, 2024
222487e
Merge branch 'main' of github.com:mongodb-js/compass into COMPASS-8378
ruchitharajaghatta Nov 18, 2024
5feb8fd
prettier fix
ruchitharajaghatta Nov 18, 2024
ce93dd2
taking out duplicated function
ruchitharajaghatta Nov 18, 2024
587e4ec
addressing changes to modal
ruchitharajaghatta Nov 19, 2024
e0c897d
fixing flag for disabling opt in
ruchitharajaghatta Nov 19, 2024
5fbf83f
nit:
ruchitharajaghatta Nov 19, 2024
0f554dc
nits and fixing optin modal/refctoring for projid
ruchitharajaghatta Nov 20, 2024
712aefb
merge main
ruchitharajaghatta Nov 20, 2024
072e8d6
fixing projectID prop
ruchitharajaghatta Nov 20, 2024
b69f37f
optin modal test
ruchitharajaghatta Nov 21, 2024
f93424a
test tweak
ruchitharajaghatta Nov 21, 2024
baedb84
nit comment
ruchitharajaghatta Nov 21, 2024
2860198
Merge branch 'main' of github.com:mongodb-js/compass into COMPASS-8378
ruchitharajaghatta Nov 22, 2024
70d3566
fixing projectId
ruchitharajaghatta Nov 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion packages/compass-generative-ai/src/atlas-ai-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import type { Document } from 'mongodb';
import type { Logger } from '@mongodb-js/compass-logging';
import { EJSON } from 'bson';
import { signIntoAtlasWithModalPrompt } from './store/atlas-signin-reducer';
import { getStore } from './store/atlas-signin-store';
import { getStore } from './store/atlas-ai-store';
import { optIntoGenAIWithModalPrompt } from './store/atlas-optin-reducer';
import { throwIfNotOk } from '../../atlas-service/src/util';

type GenerativeAiInput = {
userInput: string;
Expand Down Expand Up @@ -329,6 +331,10 @@ export class AtlasAiService {
async ensureAiFeatureAccess({ signal }: { signal?: AbortSignal } = {}) {
// When the ai feature is attempted to be opened we make sure
// the user is signed into Atlas and opted in.

if (this.apiURLPreset === 'cloud') {
return getStore().dispatch(optIntoGenAIWithModalPrompt({ signal }));
}
return getStore().dispatch(signIntoAtlasWithModalPrompt({ signal }));
}

Expand Down Expand Up @@ -437,6 +443,29 @@ export class AtlasAiService {
);
}

// optIn function w post request to set the user preference to true
async optIntoGenAIFeaturesAtlas() {
const res = await this.atlasService.authenticatedFetch(
this.atlasService.cloudEndpoint(
'/settings/optInDataExplorerGenAIFeatures'
),
{
method: 'POST',
body: JSON.stringify({
isEnabled: true,
}),
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
}
);
await throwIfNotOk(res);
await this.preferences.savePreferences({
optInDataExplorerGenAIFeatures: true,
});
}

private validateAIFeatureEnablementResponse(
response: any
): asserts response is AIFeatureEnablement {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import React from 'react';
import { connect } from 'react-redux';
import {
Body,
Link,
MarketingModal,
css,
spacing,
useDarkMode,
} from '@mongodb-js/compass-components';
import { AISignInImageBanner } from './ai-signin-banner-image';
import {
closeOptInModal,
optIn,
type AtlasOptInState,
} from '../store/atlas-optin-reducer';

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

type OptInModalProps = {
isOptInModalVisible: boolean;
isOptInInProgress: boolean;
onOptInModalClose: () => void;
onOptInClick: () => void;
};

const titleStyles = css({
marginBottom: spacing[400],
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
});

const disclaimer = css({
padding: `0 ${spacing[900]}px`,
});

const AIOptInModal: React.FunctionComponent<OptInModalProps> = ({
isOptInModalVisible,
isOptInInProgress,
onOptInModalClose,
onOptInClick,
}) => {
const darkMode = useDarkMode();

return (
<MarketingModal
darkMode={darkMode}
disclaimer={
<div className={disclaimer}>
This is a feature powered by generative AI, and may give inaccurate
responses. Please see our{' '}
<Link hideExternalIcon={false} href={GEN_AI_FAQ_LINK} target="_blank">
FAQ
</Link>{' '}
for more information.
</div>
}
graphic={<AISignInImageBanner></AISignInImageBanner>}
title={
<div className={titleStyles}>
Use natural language to generate queries and pipelines
</div>
}
open={isOptInModalVisible}
onClose={onOptInModalClose}
buttonText="Opt In to Generative AI Features"
onButtonClick={() => {
// We can't control buttons in marketing modal, so instead we just do
// nothing when button is clicked and sign in is in progress
if (isOptInInProgress) {
return;
}
onOptInClick();
}}
linkText="Cancel"
onLinkClick={onOptInModalClose}
>
<Body>
Atlas users can now quickly create queries and aggregations with
MongoDB&apos;s&nbsp; intelligent AI-powered feature, available today.
</Body>
</MarketingModal>
);
};

export default connect(
(state: AtlasOptInState) => {
return {
isOptInModalVisible: state.optInReducer.isModalOpen,
isOptInInProgress: state.state === 'in-progress',
};
},
{ onOptInModalClose: closeOptInModal, onOptInClick: optIn }
)(AIOptInModal);
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import {
useDarkMode,
} from '@mongodb-js/compass-components';
import { AISignInImageBanner } from './ai-signin-banner-image';
import type { AtlasSignInState } from '../../store/atlas-signin-reducer';
import { closeSignInModal, signIn } from '../../store/atlas-signin-reducer';
import type { AtlasSignInState } from '../store/atlas-signin-reducer';
import { closeSignInModal, signIn } from '../store/atlas-signin-reducer';

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

Expand Down Expand Up @@ -102,7 +102,7 @@ const AISignInModal: React.FunctionComponent<SignInModalProps> = ({
export default connect(
(state: AtlasSignInState) => {
return {
isSignInModalVisible: state.isModalOpen,
isSignInModalVisible: state.signInReducer.isModalOpen,
isSignInInProgress: state.state === 'in-progress',
};
},
Expand Down
2 changes: 1 addition & 1 deletion packages/compass-generative-ai/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ export {
AIExperienceEntry,
createAIPlaceholderHTMLPlaceholder,
} from './ai-experience-entry';
export { AtlasSignIn } from './atlas-signin';
export { AtlasAiPlugin } from './plugin';
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import React from 'react';
import AISignInModal from './ai-signin-modal';
import AIOptInModal from './ai-optin-modal';
import { ConfirmationModalArea } from '@mongodb-js/compass-components';

export const AtlasSignIn = () => {

export const AtlasAiPlugin = () => {
return (
<ConfirmationModalArea>
<AISignInModal></AISignInModal>
<AIOptInModal></AIOptInModal>
</ConfirmationModalArea>
);
};
};
8 changes: 5 additions & 3 deletions packages/compass-generative-ai/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import { registerHadronPlugin } from 'hadron-app-registry';
import { atlasAuthServiceLocator } from '@mongodb-js/atlas-service/provider';

import { activatePlugin } from './store/atlas-signin-store';
import { AtlasSignIn } from './components';
import { activatePlugin } from './store/atlas-ai-store';
import { AtlasAiPlugin } from './components';
import { atlasAiServiceLocator } from './provider';

export const CompassGenerativeAIPlugin = registerHadronPlugin(
{
name: 'CompassGenerativeAI',
component: AtlasSignIn,
component: AtlasAiPlugin,
activate: activatePlugin,
},
{
atlasAuthService: atlasAuthServiceLocator,
atlasAiService: atlasAiServiceLocator,
}
);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { createStore, applyMiddleware } from 'redux';
import { createStore, applyMiddleware, combineReducers } from 'redux';
import thunk from 'redux-thunk';
import reducer, {
import signInReducer, {
atlasServiceSignedOut,
atlasServiceSignedIn,
atlasServiceTokenRefreshFailed,
atlasServiceSignInTokenRefreshFailed,
} from './atlas-signin-reducer';
import optInReducer from './atlas-optin-reducer';
import type { AtlasAuthService } from '@mongodb-js/atlas-service/provider';
import type { ActivateHelpers } from 'hadron-app-registry';
import type { AtlasAiService } from '../atlas-ai-service';
import type { PreferencesAccess } from 'compass-preferences-model';

let store: CompassGenerativeAIServiceStore;
export function getStore() {
Expand All @@ -15,17 +18,22 @@ export function getStore() {
}
return store;
}
const reducer = combineReducers({
signInReducer,
optInReducer,
});

export type CompassGenerativeAIPluginServices = {
export type CompassGenerativeAIExtraArgs = {
atlasAuthService: AtlasAuthService;
atlasAiService: AtlasAiService;
preferences: PreferencesAccess;
};
export function activatePlugin(
_: Record<string, never>,
services: CompassGenerativeAIPluginServices,
services: CompassGenerativeAIExtraArgs,
{ cleanup }: ActivateHelpers
) {
store = configureStore(services);

services.atlasAuthService.on('signed-in', () => {
void store.dispatch(atlasServiceSignedIn());
});
Expand All @@ -35,18 +43,21 @@ export function activatePlugin(
});

services.atlasAuthService.on('token-refresh-failed', () => {
void store.dispatch(atlasServiceTokenRefreshFailed());
void store.dispatch(atlasServiceSignInTokenRefreshFailed());
});

return { store, deactivate: cleanup };
}

export function configureStore({
atlasAuthService,
}: CompassGenerativeAIPluginServices) {
atlasAiService,
preferences,
}: CompassGenerativeAIExtraArgs) {
const store = createStore(
reducer,
applyMiddleware(thunk.withExtraArgument({ atlasAuthService }))
applyMiddleware(
thunk.withExtraArgument({ atlasAuthService, atlasAiService, preferences })
)
);
return store;
}
Expand Down
Loading
Loading