From 3bea5b6df981f514f158fc530ee2e4428421b3e6 Mon Sep 17 00:00:00 2001 From: Etienne Rocheleau Date: Wed, 21 Aug 2024 09:58:35 -0400 Subject: [PATCH] feat(headless): Add locale to insight search (#4302) [SFINT-5668] Essentially, you can now set the `locale` parameter in the initialization options of the InsightEngine: ``` search: { locale: LOCALE, } ``` It is under `search` because this is a concept that already existed on the search engine that I am just bringing to the Insight Engine because we need it. It will be sent now as the `locale` parameter on the insight search requests. ![image](https://github.com/user-attachments/assets/3dd809ee-36e0-4025-84d6-41f55668dbde) I am re-using the existing Search Engine configuration action `engine.dispatch(updateSearchConfiguration(search));` to update the `engine.state.search.locale` value in the Insight Engine. [SFINT-5668]: https://coveord.atlassian.net/browse/SFINT-5668?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --- .../service/insight/query/query-request.ts | 2 ++ .../insight-engine-configuration.ts | 33 +++++++++++++++++-- .../app/insight-engine/insight-engine.test.ts | 11 ++++++- .../src/app/insight-engine/insight-engine.ts | 13 ++++++-- .../insight-search-request.test.ts | 1 + .../insight-search/insight-search-request.ts | 2 +- packages/headless/src/insight.index.ts | 1 + .../quanticInsightInterface.js | 4 +++ 8 files changed, 61 insertions(+), 6 deletions(-) diff --git a/packages/headless/src/api/service/insight/query/query-request.ts b/packages/headless/src/api/service/insight/query/query-request.ts index 3e365a326d8..4cc00a566b6 100644 --- a/packages/headless/src/api/service/insight/query/query-request.ts +++ b/packages/headless/src/api/service/insight/query/query-request.ts @@ -1,6 +1,7 @@ import { ContextParam, FoldingParam, + LocaleParam, NumberOfResultsParam, } from '../../../platform-service-params'; import { @@ -36,6 +37,7 @@ export type InsightQueryRequest = InsightParam & TabParam & FoldingParam & ContextParam & + LocaleParam & PipelineRuleParams; interface CaseContextParam { diff --git a/packages/headless/src/app/insight-engine/insight-engine-configuration.ts b/packages/headless/src/app/insight-engine/insight-engine-configuration.ts index 93a2204b62e..9e3353965dd 100644 --- a/packages/headless/src/app/insight-engine/insight-engine-configuration.ts +++ b/packages/headless/src/app/insight-engine/insight-engine-configuration.ts @@ -1,5 +1,8 @@ -import {Schema} from '@coveo/bueno'; -import {requiredNonEmptyString} from '../../utils/validate-payload'; +import {RecordValue, Schema} from '@coveo/bueno'; +import { + nonEmptyString, + requiredNonEmptyString, +} from '../../utils/validate-payload'; import { EngineConfiguration, engineConfigurationDefinitions, @@ -13,10 +16,36 @@ export interface InsightEngineConfiguration extends EngineConfiguration { * Specifies the unique identifier of the target insight configuration. */ insightId: string; + /** + * Specifies the configuration for the insight search. + */ + search?: InsightEngineSearchConfigurationOptions; +} + +/** + * The insight engine search configuration options. + */ +export interface InsightEngineSearchConfigurationOptions { + /** + * The locale of the current user. Must comply with IETF’s BCP 47 definition: https://www.rfc-editor.org/rfc/bcp/bcp47.txt. + * + * Notes: + * Coveo Machine Learning models use this information to provide contextually relevant output. + * Moreover, this information can be referred to in query expressions and QPL statements by using the $locale object. + */ + locale?: string; } export const insightEngineConfigurationSchema = new Schema({ ...engineConfigurationDefinitions, insightId: requiredNonEmptyString, + search: new RecordValue({ + options: { + required: false, + }, + values: { + locale: nonEmptyString, + }, + }), }); diff --git a/packages/headless/src/app/insight-engine/insight-engine.test.ts b/packages/headless/src/app/insight-engine/insight-engine.test.ts index 111415266c5..f703bad376b 100644 --- a/packages/headless/src/app/insight-engine/insight-engine.test.ts +++ b/packages/headless/src/app/insight-engine/insight-engine.test.ts @@ -23,7 +23,12 @@ describe('buildInsightEngine', () => { beforeEach(() => { options = { - configuration: getSampleInsightEngineConfiguration(), + configuration: { + ...getSampleInsightEngineConfiguration(), + search: { + locale: 'en-US', + }, + }, loggerOptions: {level: 'silent'}, }; @@ -41,6 +46,10 @@ describe('buildInsightEngine', () => { ); }); + it('sets the locale correctly', () => { + expect(engine.state.configuration?.search?.locale).toEqual('en-US'); + }); + it('exposes an #executeFirstSearch method', () => { expect(engine.executeFirstSearch).toBeTruthy(); }); diff --git a/packages/headless/src/app/insight-engine/insight-engine.ts b/packages/headless/src/app/insight-engine/insight-engine.ts index 12a191f632b..d18c542377b 100644 --- a/packages/headless/src/app/insight-engine/insight-engine.ts +++ b/packages/headless/src/app/insight-engine/insight-engine.ts @@ -5,6 +5,7 @@ import {NoopPreprocessRequest} from '../../api/preprocess-request'; import {InsightAPIClient} from '../../api/service/insight/insight-api-client'; import {interfaceLoad} from '../../features/analytics/analytics-actions'; import {LegacySearchAction} from '../../features/analytics/analytics-utils'; +import {updateSearchConfiguration} from '../../features/configuration/configuration-actions'; import {setInsightConfiguration} from '../../features/insight-configuration/insight-configuration-actions'; import {insightConfigurationReducer as insightConfiguration} from '../../features/insight-configuration/insight-configuration-slice'; import {insightInterfaceReducer as insightInterface} from '../../features/insight-interface/insight-interface-slice'; @@ -28,9 +29,13 @@ import {buildThunkExtraArguments} from '../thunk-extra-arguments'; import { InsightEngineConfiguration, insightEngineConfigurationSchema, + InsightEngineSearchConfigurationOptions, } from './insight-engine-configuration'; -export type {InsightEngineConfiguration}; +export type { + InsightEngineConfiguration, + InsightEngineSearchConfigurationOptions, +}; const insightEngineReducers = { insightConfiguration, @@ -99,7 +104,7 @@ export function buildInsightEngine( const engine = buildEngine(augmentedOptions, thunkArguments); - const {insightId} = options.configuration; + const {insightId, search} = options.configuration; engine.dispatch( setInsightConfiguration({ @@ -107,6 +112,10 @@ export function buildInsightEngine( }) ); + if (search) { + engine.dispatch(updateSearchConfiguration(search)); + } + return { ...engine, diff --git a/packages/headless/src/features/insight-search/insight-search-request.test.ts b/packages/headless/src/features/insight-search/insight-search-request.test.ts index f26b5cde06f..822db02d2a2 100644 --- a/packages/headless/src/features/insight-search/insight-search-request.test.ts +++ b/packages/headless/src/features/insight-search/insight-search-request.test.ts @@ -39,6 +39,7 @@ describe('insight search request', () => { expect(params.accessToken).toBe(state.configuration.accessToken); expect(params.organizationId).toBe(state.configuration.organizationId); expect(params.url).toBe(state.configuration.platformUrl); + expect(params.locale).toBe(state.configuration.search.locale); }); it('#buildInsightSearchRequest returns the state #insightId', async () => { diff --git a/packages/headless/src/features/insight-search/insight-search-request.ts b/packages/headless/src/features/insight-search/insight-search-request.ts index 527f9a2aa4e..eab2b7ddd7a 100644 --- a/packages/headless/src/features/insight-search/insight-search-request.ts +++ b/packages/headless/src/features/insight-search/insight-search-request.ts @@ -21,11 +21,11 @@ export const buildInsightBaseRequest = async ( ): Promise> => { const cq = buildConstantQuery(state); const facets = getAllFacets(state); - return mapSearchRequest({ accessToken: state.configuration.accessToken, organizationId: state.configuration.organizationId, url: state.configuration.platformUrl, + locale: state.configuration.search.locale, insightId: state.insightConfiguration.insightId, ...(state.configuration.analytics.enabled && (await fromAnalyticsStateToAnalyticsParams( diff --git a/packages/headless/src/insight.index.ts b/packages/headless/src/insight.index.ts index ed5effa583a..3c4d75589ad 100644 --- a/packages/headless/src/insight.index.ts +++ b/packages/headless/src/insight.index.ts @@ -11,6 +11,7 @@ export type { InsightEngine, InsightEngineOptions, InsightEngineConfiguration, + InsightEngineSearchConfigurationOptions, } from './app/insight-engine/insight-engine'; export {buildInsightEngine} from './app/insight-engine/insight-engine'; diff --git a/packages/quantic/force-app/main/default/lwc/quanticInsightInterface/quanticInsightInterface.js b/packages/quantic/force-app/main/default/lwc/quanticInsightInterface/quanticInsightInterface.js index 3cceb57b57c..b7835389f08 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticInsightInterface/quanticInsightInterface.js +++ b/packages/quantic/force-app/main/default/lwc/quanticInsightInterface/quanticInsightInterface.js @@ -1,5 +1,6 @@ // @ts-ignore import getHeadlessConfiguration from '@salesforce/apex/InsightController.getHeadlessConfiguration'; +import LOCALE from '@salesforce/i18n/locale'; import { getHeadlessBindings, loadDependencies, @@ -64,6 +65,9 @@ export default class QuanticInsightInterface extends LightningElement { configuration: { ...JSON.parse(data), insightId: this.insightId, + search: { + locale: LOCALE, + }, }, }; setEngineOptions(