Skip to content

Commit

Permalink
feat(headless): expose user action controller in insight bundle and a…
Browse files Browse the repository at this point in the history
…dd logOpenUser analytics action (#4296)

[SFINT-5640](https://coveord.atlassian.net/browse/SFINT-5640)

### IN THIS PR:
- Added `logOpenUserActions` analytics event
- Exposed the User actions controller in the insight bundle
- Added unit tests for the `logOpenUserActions` action

Tests:

<img width="769" alt="image"
src="https://github.com/user-attachments/assets/89bd185f-a3de-46b8-a015-3d5099c04a8f">


[SFINT-5640]:
https://coveord.atlassian.net/browse/SFINT-5640?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
  • Loading branch information
SimonMilord authored Aug 30, 2024
1 parent fb1a93c commit 2299887
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 2 deletions.
3 changes: 3 additions & 0 deletions packages/headless/doc-parser/use-cases/insight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@ const actionLoaders: ActionLoaderConfiguration[] = [
{
initializer: 'loadGenericAnalyticsActions',
},
{
initializer: 'loadInsightUserActionsActions',
},
];

const engine: EngineConfiguration = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {configuration} from '../../../app/common-reducers';
import {logOpenUserActions} from '../../../features/insight-search/insight-analytics-actions';
import {
fetchUserActions,
registerUserActions,
Expand All @@ -19,6 +20,8 @@ jest.mock(
'../../../features/insight-user-actions/insight-user-actions-actions'
);

jest.mock('../../../features/insight-search/insight-analytics-actions');

describe('UserActions', () => {
let engine: MockedInsightEngine;

Expand Down Expand Up @@ -71,4 +74,9 @@ describe('UserActions', () => {
expect(fetchUserActions).toHaveBeenCalled();
expect(fetchUserActions).toHaveBeenCalledWith(exampleUserId);
});

it('#logOpenUserActions dispatches #logOpenUserActions', () => {
userActions.logOpenUserActions();
expect(logOpenUserActions).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {configuration} from '../../../app/common-reducers';
import {InsightEngine} from '../../../app/insight-engine/insight-engine';
import {logOpenUserActions} from '../../../features/insight-search/insight-analytics-actions';
import {
fetchUserActions,
registerUserActions,
Expand All @@ -16,8 +17,8 @@ import {
Controller,
} from '../../controller/headless-controller';

export type {UserActionsState} from '../../../features/insight-user-actions/insight-user-actions-state';
export type {
UserActionsState,
UserAction,
UserSession,
} from '../../../features/insight-user-actions/insight-user-actions-state';
Expand Down Expand Up @@ -50,6 +51,10 @@ export interface UserActions extends Controller {
* @param userId The user ID to which the user's actions belong.
*/
fetchUserActions(userId: string): void;
/**
* Emits an analytics event indicating that the user actions panel was opened.
*/
logOpenUserActions(): void;
/**
* The state of the UserActions controller.
*/
Expand Down Expand Up @@ -80,6 +85,10 @@ export function buildUserActions(
fetchUserActions(userId: string) {
dispatch(fetchUserActions(userId));
},

logOpenUserActions() {
dispatch(logOpenUserActions());
},
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {logNumericFacetBreadcrumb} from '../facets/range-facets/numeric-facet-se
import {
logInsightCreateArticle,
CreateArticleMetadata,
logOpenUserActions,
} from '../insight-search/insight-analytics-actions';
import {
logInsightInterfaceChange,
Expand Down Expand Up @@ -253,6 +254,13 @@ export interface InsightAnalyticsActionCreators {
* @returns A dispatchable action.
*/
logFeedItemTextPost(result: Result): InsightAction;

/**
* The event to log when opening the user actions panel.
*
* @returns A dispatchable action.
*/
logOpenUserActions(): InsightAction;
}

/**
Expand Down Expand Up @@ -289,5 +297,6 @@ export function loadInsightAnalyticsActions(
logCopyToClipboard,
logCaseSendEmail,
logFeedItemTextPost,
logOpenUserActions,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import {getConfigurationInitialState} from '../configuration/configuration-state
import {
logExpandToFullUI,
logInsightCreateArticle,
logOpenUserActions,
} from './insight-analytics-actions';

const mockLogCreateArticle = jest.fn();
const mockLogExpandtoFullUI = jest.fn();
const mockLogOpenUserActions = jest.fn();
const emit = jest.fn();

jest.mock('@coveo/relay');
Expand All @@ -21,6 +23,7 @@ jest.mock('coveo.analytics', () => {
disable: jest.fn(),
logExpandToFullUI: mockLogExpandtoFullUI,
logCreateArticle: mockLogCreateArticle,
logOpenUserActions: mockLogOpenUserActions,
}));

return {
Expand Down Expand Up @@ -104,6 +107,30 @@ describe('insight analytics actions', () => {
});
});

describe('logOpenUserActions', () => {
it('should call coveo.analytics.logOpenUserActions properly', async () => {
await logOpenUserActions()()(
engine.dispatch,
() => engine.state,
{} as ThunkExtraArguments
);

const expectedPayload = {
caseContext: {
Case_Subject: exampleSubject,
Case_Description: exampleDescription,
},
caseId: exampleCaseId,
caseNumber: exampleCaseNumber,
};

expect(mockLogOpenUserActions).toHaveBeenCalledTimes(1);
expect(mockLogOpenUserActions.mock.calls[0][0]).toStrictEqual(
expectedPayload
);
});
});

describe('logExpandToFullUI', () => {
it('should call coveo.analytics.logExpandToFullUI properly', async () => {
await logExpandToFullUI(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,13 @@ export const logInsightCreateArticle = (
};
},
});

export const logOpenUserActions = (): InsightAction =>
makeInsightAnalyticsActionFactory('openUserActions')({
prefix: 'analytics/insight/openUserActions',
__legacy__getBuilder: (client, state) => {
return client.logOpenUserActions(
getCaseContextAnalyticsMetadata(state.insightCaseContext)
);
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
import {nonEmptyString, validatePayload} from '../../utils/validate-payload';
import {buildFetchUserActionsRequest} from './insight-user-actions-request';

interface RegisterUserActionsPayload {
export interface RegisterUserActionsPayload {
ticketCreationDate: string;
excludedCustomActions?: string[];
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {PayloadAction, AsyncThunkAction} from '@reduxjs/toolkit';
import {AsyncThunkInsightOptions} from '../../api/service/insight/insight-api-client';
import {CoreEngine} from '../../app/engine';
import {insightUserActionsReducer as insightUserActions} from '../../features/insight-user-actions/insight-user-actions-slice';
import {
registerUserActions,
fetchUserActions,
RegisterUserActionsPayload,
StateNeededByFetchUserActions,
FetchUserActionsThunkReturn,
} from './insight-user-actions-actions';

export type {RegisterUserActionsPayload};
export interface InsightUserActionsActionCreators {
/**
* Registers the user actions for a given user ID, ticket creation date, and excluded custom actions.
*
* @param payload - The action creator payload.
* @returns A dispatchable action.
*/
registerUserActions(
payload: RegisterUserActionsPayload
): PayloadAction<RegisterUserActionsPayload>;

/**
* Fetches the user actions.
*
* @param userId - The user ID to fetch actions for.
* @returns A dispatchable action.
*/
fetchUserActions(
userId: string
): AsyncThunkAction<
FetchUserActionsThunkReturn,
string,
AsyncThunkInsightOptions<StateNeededByFetchUserActions>
>;
}

/**
* Loads the `InsightUserActions` reducer and returns possible action creators.
* @param engine - The headless engine.
* @returns An object holding the action creators.
*/
export function loadInsightUserActionsActions(
engine: CoreEngine
): InsightUserActionsActionCreators {
engine.addReducers({insightUserActions});

return {
registerUserActions,
fetchUserActions,
};
}
12 changes: 12 additions & 0 deletions packages/headless/src/insight.index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export * from './features/attached-results/attached-results-actions-loader';
export * from './features/analytics/generic-analytics-actions-loader';
export * from './features/question-answering/question-answering-actions-loader';
export * from './features/folding/folding-actions-loader';
export * from './features/insight-user-actions/insight-user-actions-loader';

// Controllers
export type {
Expand Down Expand Up @@ -325,6 +326,17 @@ export type {
} from './controllers/insight/generated-answer/headless-insight-interactive-citation';
export {buildInteractiveCitation} from './controllers/insight/generated-answer/headless-insight-interactive-citation';
export type {GeneratedAnswerStyle} from './features/generated-answer/generated-response-format';

export type {
UserActionsState,
UserActionsProps,
UserActionsOptions,
UserActions,
UserAction,
UserSession,
} from './controllers/insight/user-actions/headless-user-actions';
export {buildUserActions} from './controllers/insight/user-actions/headless-user-actions';

// Features
export type {
ResultTemplate,
Expand Down

0 comments on commit 2299887

Please sign in to comment.