Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(headless): expose user action controller in insight bundle and add logOpenUser analytics action #4296

Merged
merged 10 commits into from
Aug 30, 2024
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() {
SimonMilord marked this conversation as resolved.
Show resolved Hide resolved
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', () => {
SimonMilord marked this conversation as resolved.
Show resolved Hide resolved
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 =>
SimonMilord marked this conversation as resolved.
Show resolved Hide resolved
makeInsightAnalyticsActionFactory('openUserActions')({
prefix: 'analytics/insight/openUserActions',
__legacy__getBuilder: (client, state) => {
SimonMilord marked this conversation as resolved.
Show resolved Hide resolved
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
SimonMilord marked this conversation as resolved.
Show resolved Hide resolved
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
Loading