Skip to content

Commit

Permalink
feat: track gen-ai use in Intercom COMPASS-7116 (#5442)
Browse files Browse the repository at this point in the history
* feat: track gen-ai use in Intercom COMPASS-7116

* test: add onSubmit tests

* closer check and cleanup

* add dependency

* add a catch

* limit track to compass + dependency
  • Loading branch information
paula-stacho committed Feb 16, 2024
1 parent 3965d40 commit 946f648
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 6 deletions.
12 changes: 11 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion packages/compass-generative-ai/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,12 @@
},
"peerDependencies": {
"@mongodb-js/compass-components": "^1.21.3",
"@mongodb-js/compass-utils": "^0.5.11",
"react": "*"
},
"dependencies": {
"@mongodb-js/compass-components": "^1.21.3"
"@mongodb-js/compass-components": "^1.21.3",
"@mongodb-js/compass-utils": "^0.5.11"
},
"devDependencies": {
"@mongodb-js/eslint-config-compass": "^1.0.15",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,16 @@ describe('GenerativeAIInput Component', function () {

describe('when rendered with text', function () {
let onChangeAIPromptTextSpy: SinonSpy;
let onSubmitTextSpy: SinonSpy;
const promptText = 'test';

beforeEach(function () {
onChangeAIPromptTextSpy = sinon.spy();
onSubmitTextSpy = sinon.spy();
renderGenerativeAIInput({
onChangeAIPromptText: onChangeAIPromptTextSpy,
aiPromptText: 'test',
onSubmitText: onSubmitTextSpy,
aiPromptText: promptText,
});
});

Expand All @@ -75,6 +79,16 @@ describe('GenerativeAIInput Component', function () {
it('does not show an error', function () {
expect(screen.queryByTestId('ai-error-msg')).to.be.null;
});

it('calls onSubmitText when submitted with a keypress', function () {
userEvent.keyboard('{Enter}');
expect(onSubmitTextSpy).to.be.calledOnceWith(promptText);
});

it('calls onSubmitText when submitted with a button click', function () {
userEvent.click(screen.getByRole('button', { name: 'Generate' }));
expect(onSubmitTextSpy).to.be.calledOnceWith(promptText);
});
});

describe('when rendered with an error', function () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import {
spacing,
useDarkMode,
} from '@mongodb-js/compass-components';
import {
IntercomTrackingEvent,
intercomTrack,
} from '@mongodb-js/compass-utils';

import { DEFAULT_AI_ENTRY_SIZE } from './ai-entry-svg';
import { AIFeedback } from './ai-feedback';
Expand Down Expand Up @@ -199,19 +203,27 @@ function GenerativeAIInput({
const darkMode = useDarkMode();
const guideCueRef = useRef<HTMLInputElement>(null);

const handleSubmit = useCallback(
(aiPromptText: string) => {
intercomTrack(IntercomTrackingEvent.submittedNlPrompt);
onSubmitText(aiPromptText);
},
[onSubmitText]
);

const onTextInputKeyDown = useCallback(
(evt: React.KeyboardEvent<HTMLInputElement>) => {
if (evt.key === 'Enter') {
evt.preventDefault();
if (!aiPromptText) {
return;
}
onSubmitText(aiPromptText);
handleSubmit(aiPromptText);
} else if (evt.key === 'Escape') {
isFetching ? onCancelRequest() : onClose();
}
},
[aiPromptText, onClose, onSubmitText, isFetching, onCancelRequest]
[aiPromptText, onClose, handleSubmit, isFetching, onCancelRequest]
);

useEffect(() => {
Expand Down Expand Up @@ -299,7 +311,7 @@ function GenerativeAIInput({
disabled={!aiPromptText}
data-testid="ai-generate-button"
onClick={() =>
isFetching ? onCancelRequest() : onSubmitText(aiPromptText)
isFetching ? onCancelRequest() : handleSubmit(aiPromptText)
}
>
{isFetching ? (
Expand Down
6 changes: 6 additions & 0 deletions packages/compass-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,11 @@
"prettier": "^2.7.1",
"sinon": "^9.2.3",
"typescript": "^5.0.4"
},
"dependencies": {
"@mongodb-js/compass-logging": "^1.2.12"
},
"peerDependencies": {
"@mongodb-js/compass-logging": "^1.2.12"
}
}
1 change: 1 addition & 0 deletions packages/compass-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export {
isCancelError,
throwIfAborted,
} from './cancellable-promise';
export { intercomTrack, IntercomTrackingEvent } from './intercom-track';
38 changes: 38 additions & 0 deletions packages/compass-utils/src/intercom-track.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { createLoggerAndTelemetry } from '@mongodb-js/compass-logging';
const { debug } = createLoggerAndTelemetry('COMPASS-INTERCOM');

type WindowWithIntercomGlobals = Window &
typeof globalThis & {
Intercom?: (...args: any[]) => any;
attachEvent?: (...args: any[]) => any;
};

export enum IntercomTrackingEvent {
submittedNlPrompt = 'submitted-nl-prompt',
}

export function intercomTrack(
event: IntercomTrackingEvent,
metadata?: unknown
) {
const win = window as WindowWithIntercomGlobals;
if (typeof win === 'undefined') {
return;
}

if (
!win.Intercom ||
typeof win.Intercom !== 'function' ||
// the last check is because the packages might be embedded in an environment where an external Intercom lives
// this way we ensure we don't polute such external Intercom with events intended for Compass Intercom
!process.env.HADRON_METRICS_INTERCOM_APP_ID
) {
return;
}

try {
win.Intercom('track', event, metadata);
} catch (error) {
debug('intercom track error', error);
}
}

0 comments on commit 946f648

Please sign in to comment.