[ACS-7284] injectable search configuration (#9448)

* injectable search configuration

* update docs
This commit is contained in:
Denys Vuika 2024-03-18 13:22:38 -04:00 committed by GitHub
parent 9616b50319
commit a09d1cfe97
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 96 additions and 16 deletions

View File

@ -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. > **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 ## See also
- [Search Configuration Guide](../../user-guide/search-configuration-guide.md) - [Search Configuration Guide](../../user-guide/search-configuration-guide.md)

View File

@ -30,6 +30,8 @@ export * from './models/search-form.interface';
export * from './models/tabbed-facet-field.interface'; export * from './models/tabbed-facet-field.interface';
export * from './search-query-service.token'; export * from './search-query-service.token';
export * from './search-configuration.token';
export * from './services/search-header-query-builder.service'; export * from './services/search-header-query-builder.service';
export * from './services/search-facet-filters.service'; export * from './services/search-facet-filters.service';
export * from './services/search-filter.service'; export * from './services/search-filter.service';

View File

@ -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<SearchConfiguration>('Custom search configuration settings');

View File

@ -21,6 +21,45 @@ import { AlfrescoApiService, AppConfigService } from '@alfresco/adf-core';
import { FacetField } from '../models/facet-field.interface'; import { FacetField } from '../models/facet-field.interface';
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { ContentTestingModule } from '../../testing/content.testing.module'; 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', () => { describe('SearchQueryBuilder', () => {
beforeEach(() => { beforeEach(() => {
@ -29,7 +68,7 @@ describe('SearchQueryBuilder', () => {
}); });
}); });
const buildConfig = (searchSettings): AppConfigService => { const buildConfig = (searchSettings = {}): AppConfigService => {
const config = TestBed.inject(AppConfigService); const config = TestBed.inject(AppConfigService);
config.config.search = searchSettings; config.config.search = searchSettings;
return config; return config;
@ -57,14 +96,14 @@ describe('SearchQueryBuilder', () => {
it('should have empty user query by default', () => { it('should have empty user query by default', () => {
const alfrescoApiService = TestBed.inject(AlfrescoApiService); const alfrescoApiService = TestBed.inject(AlfrescoApiService);
const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
expect(builder.userQuery).toBe(''); expect(builder.userQuery).toBe('');
}); });
it('should wrap user query with brackets', () => { it('should wrap user query with brackets', () => {
const alfrescoApiService = TestBed.inject(AlfrescoApiService); const alfrescoApiService = TestBed.inject(AlfrescoApiService);
const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
builder.userQuery = 'my query'; builder.userQuery = 'my query';
expect(builder.userQuery).toEqual('(my query)'); expect(builder.userQuery).toEqual('(my query)');
}); });
@ -72,7 +111,7 @@ describe('SearchQueryBuilder', () => {
it('should trim user query value', () => { it('should trim user query value', () => {
const alfrescoApiService = TestBed.inject(AlfrescoApiService); const alfrescoApiService = TestBed.inject(AlfrescoApiService);
const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
builder.userQuery = ' something '; builder.userQuery = ' something ';
expect(builder.userQuery).toEqual('(something)'); expect(builder.userQuery).toEqual('(something)');
}); });
@ -106,7 +145,7 @@ describe('SearchQueryBuilder', () => {
it('should add new filter query', () => { it('should add new filter query', () => {
const alfrescoApiService = TestBed.inject(AlfrescoApiService); const alfrescoApiService = TestBed.inject(AlfrescoApiService);
const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
builder.addFilterQuery('q1'); builder.addFilterQuery('q1');
@ -117,7 +156,7 @@ describe('SearchQueryBuilder', () => {
it('should not add empty filter query', () => { it('should not add empty filter query', () => {
const alfrescoApiService = TestBed.inject(AlfrescoApiService); const alfrescoApiService = TestBed.inject(AlfrescoApiService);
const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
builder.addFilterQuery(null); builder.addFilterQuery(null);
builder.addFilterQuery(''); builder.addFilterQuery('');
@ -128,7 +167,7 @@ describe('SearchQueryBuilder', () => {
it('should not add duplicate filter query', () => { it('should not add duplicate filter query', () => {
const alfrescoApiService = TestBed.inject(AlfrescoApiService); const alfrescoApiService = TestBed.inject(AlfrescoApiService);
const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
builder.addFilterQuery('q1'); builder.addFilterQuery('q1');
builder.addFilterQuery('q1'); builder.addFilterQuery('q1');
@ -141,7 +180,7 @@ describe('SearchQueryBuilder', () => {
it('should remove filter query', () => { it('should remove filter query', () => {
const alfrescoApiService = TestBed.inject(AlfrescoApiService); const alfrescoApiService = TestBed.inject(AlfrescoApiService);
const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
builder.addFilterQuery('q1'); builder.addFilterQuery('q1');
builder.addFilterQuery('q2'); builder.addFilterQuery('q2');
@ -155,7 +194,7 @@ describe('SearchQueryBuilder', () => {
it('should not remove empty query', () => { it('should not remove empty query', () => {
const alfrescoApiService = TestBed.inject(AlfrescoApiService); const alfrescoApiService = TestBed.inject(AlfrescoApiService);
const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
builder.addFilterQuery('q1'); builder.addFilterQuery('q1');
builder.addFilterQuery('q2'); builder.addFilterQuery('q2');
expect(builder.filterQueries.length).toBe(2); expect(builder.filterQueries.length).toBe(2);
@ -648,7 +687,7 @@ describe('SearchQueryBuilder', () => {
it('should include contain the path and allowableOperations by default', () => { it('should include contain the path and allowableOperations by default', () => {
const alfrescoApiService = TestBed.inject(AlfrescoApiService); const alfrescoApiService = TestBed.inject(AlfrescoApiService);
const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
builder.userQuery = 'nuka cola quantum'; builder.userQuery = 'nuka cola quantum';
const searchRequest = builder.buildQuery(); const searchRequest = builder.buildQuery();
@ -672,7 +711,7 @@ describe('SearchQueryBuilder', () => {
it('should the query contain the pagination', () => { it('should the query contain the pagination', () => {
const alfrescoApiService = TestBed.inject(AlfrescoApiService); const alfrescoApiService = TestBed.inject(AlfrescoApiService);
const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
builder.userQuery = 'nuka cola quantum'; builder.userQuery = 'nuka cola quantum';
const mockPagination = { const mockPagination = {
maxItems: 10, maxItems: 10,
@ -687,7 +726,7 @@ describe('SearchQueryBuilder', () => {
it('should the query contain the scope in case it is defined', () => { it('should the query contain the scope in case it is defined', () => {
const alfrescoApiService = TestBed.inject(AlfrescoApiService); const alfrescoApiService = TestBed.inject(AlfrescoApiService);
const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService); const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
const mockScope = { locations: 'mock-location' }; const mockScope = { locations: 'mock-location' };
builder.userQuery = 'nuka cola quantum'; builder.userQuery = 'nuka cola quantum';
builder.setScope(mockScope); builder.setScope(mockScope);

View File

@ -15,23 +15,27 @@
* limitations under the License. * limitations under the License.
*/ */
import { Injectable } from '@angular/core'; import { Inject, Injectable, Optional } from '@angular/core';
import { AlfrescoApiService, AppConfigService } from '@alfresco/adf-core'; import { AlfrescoApiService, AppConfigService } from '@alfresco/adf-core';
import { SearchConfiguration } from '../models/search-configuration.interface'; import { SearchConfiguration } from '../models/search-configuration.interface';
import { BaseQueryBuilderService } from './base-query-builder.service'; import { BaseQueryBuilderService } from './base-query-builder.service';
import { ADF_SEARCH_CONFIGURATION } from '../search-configuration.token';
@Injectable() @Injectable()
export class SearchQueryBuilderService extends BaseQueryBuilderService { export class SearchQueryBuilderService extends BaseQueryBuilderService {
public isFilterServiceActive(): boolean { public isFilterServiceActive(): boolean {
return false; return false;
} }
constructor(appConfig: AppConfigService, alfrescoApiService: AlfrescoApiService) { constructor(
appConfig: AppConfigService,
alfrescoApiService: AlfrescoApiService,
@Optional() @Inject(ADF_SEARCH_CONFIGURATION) private configuration?: SearchConfiguration
) {
super(appConfig, alfrescoApiService); super(appConfig, alfrescoApiService);
} }
public loadConfiguration(): SearchConfiguration { public loadConfiguration(): SearchConfiguration {
return this.appConfig.get<SearchConfiguration>('search'); return this.configuration || this.appConfig.get<SearchConfiguration>('search');
} }
} }