diff --git a/packages/compass-generative-ai/src/atlas-ai-service.ts b/packages/compass-generative-ai/src/atlas-ai-service.ts
index d504c1fcc9a..c3529d7cc64 100644
--- a/packages/compass-generative-ai/src/atlas-ai-service.ts
+++ b/packages/compass-generative-ai/src/atlas-ai-service.ts
@@ -281,7 +281,9 @@ export class AtlasAiService {
// the user is signed into Atlas and opted in.
if (this.apiURLPreset === 'cloud') {
- return getStore().dispatch(optIntoGenAIWithModalPrompt({ signal }));
+ return getStore().dispatch(
+ optIntoGenAIWithModalPrompt({ signal, isCloudOptIn: true })
+ );
}
return getStore().dispatch(signIntoAtlasWithModalPrompt({ signal }));
}
diff --git a/packages/compass-generative-ai/src/components/ai-image-banner.tsx b/packages/compass-generative-ai/src/components/ai-image-banner.tsx
index cfba44e0f6e..689aca2cf44 100644
--- a/packages/compass-generative-ai/src/components/ai-image-banner.tsx
+++ b/packages/compass-generative-ai/src/components/ai-image-banner.tsx
@@ -3,577 +3,262 @@ import { css } from '@mongodb-js/compass-components';
const bannerStyles = css({
display: 'block',
- width: 462,
- height: 263,
+ width: 200,
+ height: 151,
});
export const AiImageBanner = () => {
return (
);
};
diff --git a/packages/compass-generative-ai/src/components/ai-optin-modal.spec.tsx b/packages/compass-generative-ai/src/components/ai-optin-modal.spec.tsx
index e196bb8c626..dfb47c9cda4 100644
--- a/packages/compass-generative-ai/src/components/ai-optin-modal.spec.tsx
+++ b/packages/compass-generative-ai/src/components/ai-optin-modal.spec.tsx
@@ -9,6 +9,15 @@ import { PreferencesProvider } from 'compass-preferences-model/provider';
let mockPreferences: PreferencesAccess;
describe('AIOptInModal Component', function () {
+ const baseProps = {
+ projectId: 'ab123',
+ isCloudOptIn: true,
+ isOptInModalVisible: true,
+ isOptInInProgress: false,
+ onOptInModalClose: () => {},
+ onOptInClick: () => {},
+ };
+
beforeEach(async function () {
mockPreferences = await createSandboxFromDefaultPreferences();
});
@@ -20,37 +29,23 @@ describe('AIOptInModal Component', function () {
it('should show the modal title', function () {
render(
- {}}
- onOptInClick={() => {}}
- >
+
);
expect(
screen.getByRole('heading', {
- name: 'Use natural language to generate queries and pipelines',
+ name: 'Opt-in Gen AI-Powered features',
})
).to.exist;
});
- it('should show the cancel button', function () {
+ it('should show the not now link', function () {
render(
- {}}
- onOptInClick={() => {}}
- >
- {' '}
-
+
);
- const button = screen.getByText('Cancel').closest('button');
- expect(button).to.not.match('disabled');
+ const link = screen.getByText('Not now');
+ expect(link).to.exist;
});
it('should show the opt in button enabled when project AI setting is enabled', async function () {
@@ -59,19 +54,34 @@ describe('AIOptInModal Component', function () {
});
render(
- {}}
- onOptInClick={() => {}}
- >
- {' '}
-
+
+
+ );
+ const button = screen.getByText('Opt-in AI features');
+ expect(button).to.exist;
+ });
+
+ it('should show an info banner in a cloud opt-in', async function () {
+ await mockPreferences.savePreferences({
+ enableGenAIFeaturesAtlasProject: true,
+ });
+ render(
+
+
+
+ );
+ const banner = screen.getByTestId('ai-optin-cloud-banner');
+ expect(banner).to.exist;
+ });
+
+ it('should not show a banner in non-cloud environment', function () {
+ render(
+
+
);
- const button = screen.getByText('Use Natural Language').closest('button');
- expect(button?.getAttribute('aria-disabled')).to.equal('false');
+ const banner = screen.queryByTestId('ai-optin-cloud-banner');
+ expect(banner).to.not.exist;
});
it('should disable the opt in button if project AI setting is disabled ', async function () {
@@ -80,18 +90,10 @@ describe('AIOptInModal Component', function () {
});
render(
- {}}
- onOptInClick={() => {}}
- >
- {' '}
-
+
);
- const button = screen.getByText('Use Natural Language').closest('button');
- expect(button?.getAttribute('aria-disabled')).to.equal('true');
+ const button = screen.getByText('AI features disabled');
+ expect(button).to.exist;
});
});
diff --git a/packages/compass-generative-ai/src/components/ai-optin-modal.tsx b/packages/compass-generative-ai/src/components/ai-optin-modal.tsx
index 13244680e73..cd79b795c54 100644
--- a/packages/compass-generative-ai/src/components/ai-optin-modal.tsx
+++ b/packages/compass-generative-ai/src/components/ai-optin-modal.tsx
@@ -4,12 +4,12 @@ import {
Banner,
Body,
Link,
- ConfirmationModal,
- SpinLoader,
+ MarketingModal,
css,
spacing,
- H3,
palette,
+ useDarkMode,
+ SpinLoader,
} from '@mongodb-js/compass-components';
import { AiImageBanner } from './ai-image-banner';
import { closeOptInModal, optIn } from '../store/atlas-optin-reducer';
@@ -22,50 +22,42 @@ const GEN_AI_FAQ_LINK = 'https://www.mongodb.com/docs/generative-ai-faq/';
type OptInModalProps = {
isOptInModalVisible: boolean;
isOptInInProgress: boolean;
+ isCloudOptIn: boolean;
onOptInModalClose: () => void;
onOptInClick: () => void;
projectId?: string;
};
-const titleStyles = css({
- marginBottom: spacing[400],
- marginTop: spacing[400],
- marginLeft: spacing[500],
- marginRight: spacing[500],
- textAlign: 'center',
-});
-
-const bodyStyles = css({
- marginBottom: spacing[400],
- marginTop: spacing[400],
- marginLeft: spacing[300],
- marginRight: spacing[300],
- display: 'flex',
- flexDirection: 'column',
- alignItems: 'center',
- textAlign: 'center',
-});
-
const disclaimerStyles = css({
color: palette.gray.dark1,
- marginTop: spacing[400],
- marginLeft: spacing[800],
- marginRight: spacing[800],
+ paddingLeft: spacing[800],
+ paddingRight: spacing[800],
});
-const bannerStyles = css({
- padding: spacing[400],
- marginTop: spacing[400],
- textAlign: 'left',
+// TODO: The LG MarketingModal does not provide a way to disable a button
+// so this is a temporary workaround to make the button look disabled.
+const disableOptInButtonStyles = css({
+ button: {
+ opacity: 0.5,
+ pointerEvents: 'none',
+ cursor: 'not-allowed',
+ },
});
-const getButtonText = (isOptInInProgress: boolean) => {
+
+const getButtonText = ({
+ isOptInInProgress,
+ darkMode,
+}: {
+ isOptInInProgress: boolean;
+ darkMode: boolean | undefined;
+}) => {
return (
<>
- Use Natural Language
+ Opt-in AI features
{isOptInInProgress && (
<>
-
+
>
)}
>
@@ -75,12 +67,14 @@ const getButtonText = (isOptInInProgress: boolean) => {
export const AIOptInModal: React.FunctionComponent = ({
isOptInModalVisible,
isOptInInProgress,
+ isCloudOptIn,
onOptInModalClose,
onOptInClick,
projectId,
}) => {
const isProjectAIEnabled = usePreference('enableGenAIFeaturesAtlasProject');
const track = useTelemetry();
+ const darkMode = useDarkMode();
const PROJECT_SETTINGS_LINK = projectId
? window.location.origin + '/v2/' + projectId + '#/settings/groupSettings'
: null;
@@ -92,7 +86,7 @@ export const AIOptInModal: React.FunctionComponent = ({
}, [isOptInModalVisible, track]);
const onConfirmClick = () => {
- if (isOptInInProgress) {
+ if (isOptInInProgress || !isProjectAIEnabled) {
return;
}
onOptInClick();
@@ -104,43 +98,22 @@ export const AIOptInModal: React.FunctionComponent = ({
}, [track, onOptInModalClose]);
return (
-
-
-
-
- Use natural language to generate queries and pipelines
-
- Atlas users can now quickly create queries and aggregations with
- MongoDB's intelligent AI-powered feature, available today.
-
- {isProjectAIEnabled
- ? 'AI features are enabled for project users with data access.'
- : 'AI features are disabled for project users.'}{' '}
- Project Owners can {isProjectAIEnabled ? 'disable' : 'enable'} Data
- Explorer AI features in the{' '}
- {PROJECT_SETTINGS_LINK !== null ? (
-
- Project Settings
-
- ) : (
- 'Project Settings'
- )}
- .
-
+ }
+ darkMode={darkMode}
+ disclaimer={
This is a feature powered by generative AI, and may give inaccurate
responses. Please see our{' '}
@@ -149,8 +122,49 @@ export const AIOptInModal: React.FunctionComponent = ({
{' '}
for more information.
+ }
+ >
+
+ Opt in now MongoDB’s intelligent AI-powered features:
+
+
AI Assistant allows you to ask questions across connections
+
Natural Language Bar to create queries and aggregations
+ {/*
Mock Data Generator to create AI powered sample data