-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(headless): creation of the new headless insight user actions con…
…troller (#4192) # [SFINT-5613](https://coveord.atlassian.net/browse/SFINT-5613) ## Overview about the user actions feature: The user actions feature allows the agent using the Insight Panel to check all the actions that have beed made by a user who created a case, these knowledge about the actions performed by the user should help the agent to understand the context of the case and issue the user is facing and help him solve the case more quickly. From a UI perspective, that's what this feature look like: <img width="250" alt="Screenshot 2024-07-16 at 9 21 10 AM" src="https://github.com/user-attachments/assets/5f326d08-9750-4f27-99a3-331193ade5a0"> ## From where we get the user actions data: We get the user action data from the the following machine learning API: [/rest/organizations/{organizationId}/machinelearning/user/actions]( https://platformdev.cloud.coveo.com/docs?urls.primaryName=Machine%20Learning#/User%20Profiles/rest_organizations_paramId_machinelearning_user_actions_post) ## Example request: ``` curl -X 'POST' \ 'https://platform.cloud.coveo.com/rest/organizations/MyOrgId/machinelearning/user/actions' \ -H 'accept: */*' \ -H 'Authorization: Bearer XXXXXXX' \ -H 'Content-Type: application/json' \ -d '{ "objectId": "MyUserId" }' ``` ## Example response: ``` { "executionTime":0.011054937, "modelSubType":"userActionHistory", "modelType":"Profile", "responseTime":1721136841424, "value":[ { "name":"SEARCH", "value":"{\"cause\":\"userActionLoad\",\"origin_level_1\":\"coveoLightningInsightPanel\",\"origin_level_2\":\"default\"}", "time":"1721012966908" }, { "name":"CUSTOM", "value":"{\"event_type\":\"User Actions\",\"event_value\":\"openUserActions\",\"origin_level_1\":\"coveoLightningInsightPanel\",\"origin_level_2\":\"default\"}", "time":"1721012966186" }, .... ] ``` ## What is being done in the Headless library: ### In this first iteration(this PR): - Created the Headless user actions controller. - Created the Headless user actions dispatchable actions. - Created the Headless user actions slice. - Created the Headless user actions state. - Updated the the insight API client to target the correct user actions endpoint. - Unit tests created. ### In a future iteration(a following PR): - Will add the logic that preprocess the data returned by the API, this logic will organize and filter the data to make it ready to display by the future UI components: https://coveord.atlassian.net/browse/SFINT-5639 - Expose the Headless user actions controller. - Add the and expose the headless user action actions loader. - Add more unit tests. [SFINT-5613]: https://coveord.atlassian.net/browse/SFINT-5613?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
- Loading branch information
Showing
17 changed files
with
631 additions
and
97 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 8 additions & 41 deletions
49
packages/headless/src/api/service/insight/user-actions/user-actions-request.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,55 +1,22 @@ | ||
import { | ||
baseInsightRequest, | ||
InsightParam, | ||
pickNonInsightParams, | ||
} from '../insight-params'; | ||
import {BaseParam} from '../../../platform-service-params'; | ||
import {baseInsightUserActionRequest} from '../insight-params'; | ||
|
||
export type InsightUserActionsRequest = InsightParam & | ||
TicketCreationDateParam & | ||
NumberSessionsBeforeParam & | ||
NumberSessionsAfterParam & | ||
MaximumSessionInactivityMinutesParam & | ||
ExcludedCustomActionsParam; | ||
export type InsightUserActionsRequest = BaseParam & UserIdParam; | ||
|
||
interface TicketCreationDateParam { | ||
interface UserIdParam { | ||
/** | ||
* The ticket creation date in the [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. | ||
* Identifier of the user from which Clicked Documents are shown. | ||
*/ | ||
ticketCreationDate: string; | ||
} | ||
|
||
interface NumberSessionsBeforeParam { | ||
numberSessionsBefore?: number; | ||
} | ||
|
||
interface NumberSessionsAfterParam { | ||
numberSessionsAfter?: number; | ||
} | ||
|
||
interface MaximumSessionInactivityMinutesParam { | ||
maximumSessionInactivityMinutes?: number; | ||
} | ||
|
||
interface ExcludedCustomActionsParam { | ||
excludedCustomActions?: string[]; | ||
userId: string; | ||
} | ||
|
||
export const buildInsightUserActionsRequest = ( | ||
req: InsightUserActionsRequest | ||
) => { | ||
const params = pickNonInsightParams( | ||
req | ||
) as Partial<InsightUserActionsRequest>; | ||
|
||
return { | ||
...baseInsightRequest(req, 'POST', 'application/json', '/useractions'), | ||
...baseInsightUserActionRequest(req, 'POST', 'application/json'), | ||
requestParams: { | ||
ticketCreationDate: params.ticketCreationDate, | ||
numberSessionsBefore: params.numberSessionsBefore ?? 50, | ||
numberSessionsAfter: params.numberSessionsAfter ?? 50, | ||
maximumSessionInactivityMinutes: | ||
params.maximumSessionInactivityMinutes ?? 30, | ||
excludedCustomActions: params.excludedCustomActions ?? [], | ||
objectId: req.userId, | ||
}, | ||
}; | ||
}; |
24 changes: 6 additions & 18 deletions
24
packages/headless/src/api/service/insight/user-actions/user-actions-response.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,11 @@ | ||
export interface InsightUserActionsResponse { | ||
timeline?: UserActionTimeline; | ||
} | ||
import {UserActionType} from '../../../../features/insight-user-actions/insight-user-actions-state'; | ||
|
||
interface UserActionTimeline { | ||
sessions: UserSession[]; | ||
} | ||
|
||
interface UserSession { | ||
start: Date; | ||
end: Date; | ||
actions: UserAction[]; | ||
export interface InsightUserActionsResponse { | ||
value: Array<UserAction>; | ||
} | ||
|
||
type UserActionType = 'SEARCH' | 'CLICK' | 'VIEW' | 'CUSTOM'; | ||
interface UserAction { | ||
actionType: UserActionType; | ||
timestamp: Date; | ||
raw: Record<string, string>; | ||
searchHub?: string; | ||
document?: string; | ||
query?: string; | ||
name: UserActionType; | ||
time: string; | ||
value: string; | ||
} |
74 changes: 74 additions & 0 deletions
74
packages/headless/src/controllers/insight/user-actions/headless-user-actions.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import {configuration} from '../../../app/common-reducers'; | ||
import { | ||
fetchUserActions, | ||
registerUserActions, | ||
} from '../../../features/insight-user-actions/insight-user-actions-actions'; | ||
import {insightUserActionsReducer} from '../../../features/insight-user-actions/insight-user-actions-slice'; | ||
import { | ||
buildMockInsightEngine, | ||
MockedInsightEngine, | ||
} from '../../../test/mock-engine-v2'; | ||
import {buildMockInsightState} from '../../../test/mock-insight-state'; | ||
import { | ||
UserActions, | ||
UserActionsOptions, | ||
buildUserActions, | ||
} from './headless-user-actions'; | ||
|
||
jest.mock( | ||
'../../../features/insight-user-actions/insight-user-actions-actions' | ||
); | ||
|
||
describe('UserActions', () => { | ||
let engine: MockedInsightEngine; | ||
|
||
let options: UserActionsOptions; | ||
let userActions: UserActions; | ||
|
||
function initUserActions() { | ||
userActions = buildUserActions(engine, {options}); | ||
} | ||
|
||
const exampleUserId = 'John Doe'; | ||
const exampleTicketCreationDate = '2024-07-16T21:00:42.741Z'; | ||
const exampleExcludedCustomActions = ['badAction']; | ||
|
||
beforeEach(() => { | ||
options = { | ||
ticketCreationDate: exampleTicketCreationDate, | ||
excludedCustomActions: exampleExcludedCustomActions, | ||
}; | ||
engine = buildMockInsightEngine(buildMockInsightState()); | ||
|
||
initUserActions(); | ||
}); | ||
|
||
it('initializes', () => { | ||
expect(userActions).toBeTruthy(); | ||
}); | ||
|
||
it('it adds the correct reducers to the engine', () => { | ||
expect(engine.addReducers).toHaveBeenCalledWith({ | ||
configuration, | ||
insightuserActions: insightUserActionsReducer, | ||
}); | ||
}); | ||
|
||
it('exposes a subscribe method', () => { | ||
expect(userActions.subscribe).toBeTruthy(); | ||
}); | ||
|
||
it('registers and updates the state with the given options', () => { | ||
expect(registerUserActions).toHaveBeenCalled(); | ||
expect(registerUserActions).toHaveBeenCalledWith({ | ||
ticketCreationDate: exampleTicketCreationDate, | ||
excludedCustomActions: exampleExcludedCustomActions, | ||
}); | ||
}); | ||
|
||
it('#fetchUserActions dispatches #fetchUserActions', () => { | ||
userActions.fetchUserActions(exampleUserId); | ||
expect(fetchUserActions).toHaveBeenCalled(); | ||
expect(fetchUserActions).toHaveBeenCalledWith(exampleUserId); | ||
}); | ||
}); |
Oops, something went wrong.