diff --git a/docs/content-services/services/search-query-builder.service.md b/docs/content-services/services/search-query-builder.service.md index 8b0e6e1cea..7fc2ad66ef 100644 --- a/docs/content-services/services/search-query-builder.service.md +++ b/docs/content-services/services/search-query-builder.service.md @@ -131,6 +131,20 @@ constructor(queryBuilder: SearchQueryBuilderService) { > **Note:** From ADF 3.0.0, the query contains the `"facetFormat": "V2"` parameter so that all the responses have the same structure whether they come from search queries containing facetFields, facetQueries, grouped facetQueries or facetIntervals. +## Runtime Configuration + +You can provide search configuration at runtime using the `ADF_SEARCH_CONFIGURATION` injection token. +The value should expose the [SearchConfiguration](https://github.com/Alfresco/alfresco-ng2-components/blob/develop/lib/content-services/src/lib/search/models/search-configuration.interface.ts#L25) interface. + +```ts +@NgModule({ + providers: [ + { provide: ADF_SEARCH_CONFIGURATION, useValue: {/*...*/} } + ] +}) +class AppModule {} +``` + ## See also - [Search Configuration Guide](../../user-guide/search-configuration-guide.md) diff --git a/lib/content-services/src/lib/search/public-api.ts b/lib/content-services/src/lib/search/public-api.ts index 5045bdb593..08388cdd49 100644 --- a/lib/content-services/src/lib/search/public-api.ts +++ b/lib/content-services/src/lib/search/public-api.ts @@ -30,6 +30,8 @@ export * from './models/search-form.interface'; export * from './models/tabbed-facet-field.interface'; export * from './search-query-service.token'; +export * from './search-configuration.token'; + export * from './services/search-header-query-builder.service'; export * from './services/search-facet-filters.service'; export * from './services/search-filter.service'; diff --git a/lib/content-services/src/lib/search/search-configuration.token.ts b/lib/content-services/src/lib/search/search-configuration.token.ts new file mode 100644 index 0000000000..648920ec0a --- /dev/null +++ b/lib/content-services/src/lib/search/search-configuration.token.ts @@ -0,0 +1,21 @@ +/*! + * @license + * Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { InjectionToken } from '@angular/core'; +import { SearchConfiguration } from './models/search-configuration.interface'; + +export const ADF_SEARCH_CONFIGURATION = new InjectionToken('Custom search configuration settings'); diff --git a/lib/content-services/src/lib/search/services/search-query-builder.service.spec.ts b/lib/content-services/src/lib/search/services/search-query-builder.service.spec.ts index 2e3ffade73..9790086910 100644 --- a/lib/content-services/src/lib/search/services/search-query-builder.service.spec.ts +++ b/lib/content-services/src/lib/search/services/search-query-builder.service.spec.ts @@ -21,6 +21,45 @@ import { AlfrescoApiService, AppConfigService } from '@alfresco/adf-core'; import { FacetField } from '../models/facet-field.interface'; import { TestBed } from '@angular/core/testing'; import { ContentTestingModule } from '../../testing/content.testing.module'; +import { ADF_SEARCH_CONFIGURATION } from '../search-configuration.token'; + +describe('SearchQueryBuilder (runtime config)', () => { + const runtimeConfig: SearchConfiguration = {}; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ContentTestingModule], + providers: [ + { provide: ADF_SEARCH_CONFIGURATION, useValue: runtimeConfig } + ] + }); + }); + + const buildConfig = (searchSettings): AppConfigService => { + const config = TestBed.inject(AppConfigService); + config.config.search = searchSettings; + return config; + }; + + it('should use custom search configuration via dependency injection', () => { + const builder = TestBed.inject(SearchQueryBuilderService); + const currentConfig = builder.loadConfiguration(); + + expect(currentConfig).toEqual(runtimeConfig); + }); + + it('should prioritise runtime config over configuration file', () => { + const config: SearchConfiguration = { + categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any], + filterQueries: [{ query: 'query1' }, { query: 'query2' }] + }; + const alfrescoApiService = TestBed.inject(AlfrescoApiService); + const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService, runtimeConfig); + const currentConfig = builder.loadConfiguration(); + + expect(currentConfig).toEqual(runtimeConfig); + }); +}); describe('SearchQueryBuilder', () => { beforeEach(() => { @@ -29,7 +68,7 @@ describe('SearchQueryBuilder', () => { }); }); - const buildConfig = (searchSettings): AppConfigService => { + const buildConfig = (searchSettings = {}): AppConfigService => { const config = TestBed.inject(AppConfigService); config.config.search = searchSettings; return config; @@ -57,14 +96,14 @@ describe('SearchQueryBuilder', () => { it('should have empty user query by default', () => { const alfrescoApiService = TestBed.inject(AlfrescoApiService); - const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); + const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService); expect(builder.userQuery).toBe(''); }); it('should wrap user query with brackets', () => { const alfrescoApiService = TestBed.inject(AlfrescoApiService); - const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); + const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService); builder.userQuery = 'my query'; expect(builder.userQuery).toEqual('(my query)'); }); @@ -72,7 +111,7 @@ describe('SearchQueryBuilder', () => { it('should trim user query value', () => { const alfrescoApiService = TestBed.inject(AlfrescoApiService); - const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); + const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService); builder.userQuery = ' something '; expect(builder.userQuery).toEqual('(something)'); }); @@ -106,7 +145,7 @@ describe('SearchQueryBuilder', () => { it('should add new filter query', () => { const alfrescoApiService = TestBed.inject(AlfrescoApiService); - const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); + const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService); builder.addFilterQuery('q1'); @@ -117,7 +156,7 @@ describe('SearchQueryBuilder', () => { it('should not add empty filter query', () => { const alfrescoApiService = TestBed.inject(AlfrescoApiService); - const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); + const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService); builder.addFilterQuery(null); builder.addFilterQuery(''); @@ -128,7 +167,7 @@ describe('SearchQueryBuilder', () => { it('should not add duplicate filter query', () => { const alfrescoApiService = TestBed.inject(AlfrescoApiService); - const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); + const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService); builder.addFilterQuery('q1'); builder.addFilterQuery('q1'); @@ -141,7 +180,7 @@ describe('SearchQueryBuilder', () => { it('should remove filter query', () => { const alfrescoApiService = TestBed.inject(AlfrescoApiService); - const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); + const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService); builder.addFilterQuery('q1'); builder.addFilterQuery('q2'); @@ -155,7 +194,7 @@ describe('SearchQueryBuilder', () => { it('should not remove empty query', () => { const alfrescoApiService = TestBed.inject(AlfrescoApiService); - const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); + const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService); builder.addFilterQuery('q1'); builder.addFilterQuery('q2'); expect(builder.filterQueries.length).toBe(2); @@ -648,7 +687,7 @@ describe('SearchQueryBuilder', () => { it('should include contain the path and allowableOperations by default', () => { const alfrescoApiService = TestBed.inject(AlfrescoApiService); - const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); + const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService); builder.userQuery = 'nuka cola quantum'; const searchRequest = builder.buildQuery(); @@ -672,7 +711,7 @@ describe('SearchQueryBuilder', () => { it('should the query contain the pagination', () => { const alfrescoApiService = TestBed.inject(AlfrescoApiService); - const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); + const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService); builder.userQuery = 'nuka cola quantum'; const mockPagination = { maxItems: 10, @@ -687,7 +726,7 @@ describe('SearchQueryBuilder', () => { it('should the query contain the scope in case it is defined', () => { const alfrescoApiService = TestBed.inject(AlfrescoApiService); - const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); + const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService); const mockScope = { locations: 'mock-location' }; builder.userQuery = 'nuka cola quantum'; builder.setScope(mockScope); diff --git a/lib/content-services/src/lib/search/services/search-query-builder.service.ts b/lib/content-services/src/lib/search/services/search-query-builder.service.ts index 8897b7e698..9dbd7b2c21 100644 --- a/lib/content-services/src/lib/search/services/search-query-builder.service.ts +++ b/lib/content-services/src/lib/search/services/search-query-builder.service.ts @@ -15,23 +15,27 @@ * limitations under the License. */ -import { Injectable } from '@angular/core'; +import { Inject, Injectable, Optional } from '@angular/core'; import { AlfrescoApiService, AppConfigService } from '@alfresco/adf-core'; import { SearchConfiguration } from '../models/search-configuration.interface'; import { BaseQueryBuilderService } from './base-query-builder.service'; +import { ADF_SEARCH_CONFIGURATION } from '../search-configuration.token'; @Injectable() export class SearchQueryBuilderService extends BaseQueryBuilderService { - public isFilterServiceActive(): boolean { return false; } - constructor(appConfig: AppConfigService, alfrescoApiService: AlfrescoApiService) { + constructor( + appConfig: AppConfigService, + alfrescoApiService: AlfrescoApiService, + @Optional() @Inject(ADF_SEARCH_CONFIGURATION) private configuration?: SearchConfiguration + ) { super(appConfig, alfrescoApiService); } public loadConfiguration(): SearchConfiguration { - return this.appConfig.get('search'); + return this.configuration || this.appConfig.get('search'); } }