From ba03c60adb960943ee5b779a1db3835090f7dd12 Mon Sep 17 00:00:00 2001 From: Dharan <14145706+dhrn@users.noreply.github.com> Date: Tue, 15 Jun 2021 18:22:46 +0530 Subject: [PATCH] [ADF-5417] Support multiple search configuration in app config json (#7096) * [ACS-1642] Support multiple search configuration in app config json * [ci:force] unit test added * adf component added * [ci:force] check compatibility * [ci:force] * run all e2e * * revert initvalue * [ci:force] revert app config * [ci:force] docs update --- demo-shell/resources/i18n/en.json | 3 + demo-shell/src/app.config.json | 8 +- .../search/search-result.component.html | 2 + .../search/search-result.component.scss | 4 +- .../search/search-result.component.ts | 41 +- .../components/search-form.component.md | 75 ++ .../images/search-form-component.png | Bin 0 -> 1960 bytes .../content-node-selector-panel.service.ts | 2 +- .../components/document-list.component.ts | 2 +- .../filter-header/filter-header.component.ts | 2 +- lib/content-services/src/lib/i18n/en.json | 2 + .../src/lib/mock/content-model.mock.ts | 2 +- .../lib/search/base-query-builder.service.ts | 78 +- .../search-check-list.component.spec.ts | 2 +- .../search-check-list.component.ts | 6 +- .../search-date-range.component.ts | 4 +- .../search-datetime-range.component.ts | 4 +- .../search-filter-container.component.spec.ts | 2 +- .../search-filter-container.component.ts | 2 +- .../search-filter.component.spec.ts | 6 +- .../search-filter/search-filter.component.ts | 6 +- .../search-form/search-form.component.html | 8 + .../search-form/search-form.component.spec.ts | 91 ++ .../search-form/search-form.component.ts | 44 + .../search-number-range.component.ts | 4 +- .../search-panel.component.spec.ts | 2 +- .../search-radio.component.spec.ts | 4 +- .../search-radio/search-radio.component.ts | 12 +- .../search-slider/search-slider.component.ts | 4 +- .../search-sorting-picker.component.spec.ts | 2 +- .../search-sorting-picker.component.ts | 2 +- .../search-text/search-text.component.ts | 4 +- .../facet-field-bucket.interface.ts | 0 .../{ => models}/facet-field.interface.ts | 2 +- .../{ => models}/facet-query.interface.ts | 0 .../{ => models}/filter-query.interface.ts | 0 .../{ => models}/filter-search.interface.ts | 0 .../models/response-facet-query-list.model.ts | 0 .../{ => models}/search-category.interface.ts | 0 .../search-configuration.interface.ts | 2 + .../models/search-filter-list.model.spec.ts | 0 .../models/search-filter-list.model.ts | 0 .../search/models/search-form.interface.ts | 23 + .../{ => models}/search-range.interface.ts | 0 .../search-sorting-definition.interface.ts | 0 .../search-widget-settings.interface.ts | 0 .../{ => models}/search-widget.interface.ts | 2 +- .../src/lib/search/public-api.ts | 23 +- ...earch-header-query-builder.service.spec.ts | 2 +- .../search-header-query-builder.service.ts | 8 +- .../search-query-builder.service.spec.ts | 91 +- .../search/search-query-builder.service.ts | 2 +- .../src/lib/search/search.module.ts | 7 +- lib/core/app-config/schema.json | 791 +++++++++--------- lib/testing/index.ts | 1 - 55 files changed, 909 insertions(+), 475 deletions(-) create mode 100644 docs/content-services/components/search-form.component.md create mode 100644 docs/docassets/images/search-form-component.png create mode 100644 lib/content-services/src/lib/search/components/search-form/search-form.component.html create mode 100644 lib/content-services/src/lib/search/components/search-form/search-form.component.spec.ts create mode 100644 lib/content-services/src/lib/search/components/search-form/search-form.component.ts rename lib/content-services/src/lib/search/{ => models}/facet-field-bucket.interface.ts (100%) rename lib/content-services/src/lib/search/{ => models}/facet-field.interface.ts (91%) rename lib/content-services/src/lib/search/{ => models}/facet-query.interface.ts (100%) rename lib/content-services/src/lib/search/{ => models}/filter-query.interface.ts (100%) rename lib/content-services/src/lib/search/{ => models}/filter-search.interface.ts (100%) rename lib/content-services/src/lib/search/{components/search-filter => }/models/response-facet-query-list.model.ts (100%) rename lib/content-services/src/lib/search/{ => models}/search-category.interface.ts (100%) rename lib/content-services/src/lib/search/{ => models}/search-configuration.interface.ts (97%) rename lib/content-services/src/lib/search/{components/search-filter => }/models/search-filter-list.model.spec.ts (100%) rename lib/content-services/src/lib/search/{components/search-filter => }/models/search-filter-list.model.ts (100%) create mode 100644 lib/content-services/src/lib/search/models/search-form.interface.ts rename lib/content-services/src/lib/search/{ => models}/search-range.interface.ts (100%) rename lib/content-services/src/lib/search/{ => models}/search-sorting-definition.interface.ts (100%) rename lib/content-services/src/lib/search/{ => models}/search-widget-settings.interface.ts (100%) rename lib/content-services/src/lib/search/{ => models}/search-widget.interface.ts (92%) diff --git a/demo-shell/resources/i18n/en.json b/demo-shell/resources/i18n/en.json index ffa0dc8927..a9b1c809e2 100644 --- a/demo-shell/resources/i18n/en.json +++ b/demo-shell/resources/i18n/en.json @@ -349,5 +349,8 @@ "PROCESS_ID": "Process Instance ID", "ACTION_TYPE": "Action Type" } + }, + "SEARCH_FORMS": { + "ALL": "All" } } diff --git a/demo-shell/src/app.config.json b/demo-shell/src/app.config.json index 806171d9a2..b509585865 100644 --- a/demo-shell/src/app.config.json +++ b/demo-shell/src/app.config.json @@ -34,7 +34,7 @@ "copyright": "© 2016 - 2021 Alfresco Software, Inc. All Rights Reserved." }, "notifications": true, - "search": { + "search": [{ "filterWithContains": true, "app:fields": [ "cm:name", @@ -365,8 +365,10 @@ "postfix": ")" } ] - } - }, + }, + "name": "SEARCH_FORMS.ALL", + "default": true + }], "search-headers": { "filterWithContains": true, "app:fields": [ diff --git a/demo-shell/src/app/components/search/search-result.component.html b/demo-shell/src/app/components/search/search-result.component.html index 2ddf5321cc..3d9907b5ed 100644 --- a/demo-shell/src/app/components/search/search-result.component.html +++ b/demo-shell/src/app/components/search/search-result.component.html @@ -9,6 +9,8 @@
+ +
(); constructor(public router: Router, - private config: AppConfigService, private preferences: UserPreferencesService, private queryBuilder: SearchQueryBuilderService, - @Optional() private route: ActivatedRoute) { + private route: ActivatedRoute) { + combineLatest([this.route.params, this.queryBuilder.configUpdated]) + .pipe(takeUntil(this.onDestroy$)) + .subscribe(([params, searchConfig]) => { + this.searchedWord = params.hasOwnProperty(this.queryParamName) ? params[this.queryParamName] : null; + const query = this.formatSearchQuery(this.searchedWord, searchConfig['app:fields']); + if (query) { + this.queryBuilder.userQuery = query; + } + }); + queryBuilder.paging = { maxItems: this.preferences.paginationSize, skipCount: 0 @@ -76,10 +86,7 @@ export class SearchResultComponent implements OnInit, OnDestroy { if (this.route) { this.route.params.forEach((params: Params) => { this.searchedWord = params.hasOwnProperty(this.queryParamName) ? params[this.queryParamName] : null; - const query = this.formatSearchQuery(this.searchedWord); - - if (query) { - this.queryBuilder.userQuery = query; + if (this.searchedWord) { this.queryBuilder.update(); } else { this.queryBuilder.userQuery = null; @@ -94,15 +101,11 @@ export class SearchResultComponent implements OnInit, OnDestroy { } } - private formatSearchQuery(userInput: string) { + private formatSearchQuery(userInput: string, fields = ['cm:name']) { if (!userInput) { return null; } - - const fields = this.config.get('search.app:fields', ['cm:name']); - const query = fields.map((field) => `${field}:"${userInput}*"`).join(' OR '); - - return query; + return fields.map((field) => `${field}:"${userInput}*"`).join(' OR '); } ngOnDestroy() { @@ -136,4 +139,8 @@ export class SearchResultComponent implements OnInit, OnDestroy { return ['name', 'asc']; } + + onFormChange(form: SearchForm) { + this.queryBuilder.updateSelectedConfiguration(form.index); + } } diff --git a/docs/content-services/components/search-form.component.md b/docs/content-services/components/search-form.component.md new file mode 100644 index 0000000000..b04762d71e --- /dev/null +++ b/docs/content-services/components/search-form.component.md @@ -0,0 +1,75 @@ +--- +Title: Search Form component +Added: v4.5.0 +Status: Active +Last reviewed: 2021-06-11 +--- + +# [Search Form component](../../../lib/content-services/src/lib/search/components/search-form/search-form.component.ts "Defined in search-form.component.ts") + +Selecting a configuration from a set of configured options. + +![Search Form screenshot](../../docassets/images/search-form-component.png) + +## Basic usage + +```json +{ + "search": [ + { + "categories": [ + { + "id": "queryName", + "name": "Name", + "enabled": true, + "expanded": true, + "component": { + "selector": "text", + "settings": { + "searchPrefix": "", + "searchSuffix": "", + "pattern": "cm:name:'(.*?)'", + "field": "cm:name", + "placeholder": "Enter the name", + "allowUpdateOnChange": true + } + } + } + ], + "name": "ALL", + "default": true + }, + { + "categories": [ + { + "id": "queryName", + "name": "Name", + "enabled": true, + "expanded": true, + "component": { + "selector": "text", + "settings": { + "searchPrefix": "", + "searchSuffix": "", + "pattern": "cm:name:'(.*?)'", + "field": "cm:name", + "placeholder": "Enter the name", + "allowUpdateOnChange": true + } + } + } + ], + "name": "Other" + } + ] +} +``` + + +## Details + +This component lets the user pick a configuration for a search. + +## See also + +- [Search Query Builder](../services/search-query-builder.service.md) diff --git a/docs/docassets/images/search-form-component.png b/docs/docassets/images/search-form-component.png new file mode 100644 index 0000000000000000000000000000000000000000..e8eeef330fe34f969a76d0f2c28f2dd722e94f45 GIT binary patch literal 1960 zcmZ`)X)qh=8dkOBYLOD^*h{KCmL7XsRcZ-Yib@fxYHur)DuP;Tsbfu1&AA9eN@|Hn zY^Syus*&cT>L_Z7^*Dq|YY8ePH+Sa#=**q-%zWSbvXqF3 zh%^jpj}*os;ei4~g|}sn!6{)l9%T!20{{Ti3oi2_B9eYEdmFd7@{Jh*LM24KZ}VOS zxcConX#`x0hmaU;^&^ouYa?*)oOhIt%=C9`Wccvm!YcCpqh|e``J*)c#(eTCKJ$(j z`93Pv;AgHB33c}D5NY#797PA+>T$Ce(M|bxVp-7N$x0VI$zN@QB$;E)c%@hDgbZ-c+CHpmZttSF(G*a zck}@YUfkoyS6nP(34!T4Obt9Im(AgDc6WDCv+J92?HwH@mAuDE2?y#}B64Ex6 zo+m!rj2xJnoHQz9opUa~(J-b{%-P>u(k+3%SiWznobS+f>w%9C-lKuFvaO<`Vma)s zuV@2AqtQWL1@tAQKpWtt0z?f`NKy5tH!xl=PT6{Udym|I9_*DhKq0!3JeY>pH&L!2 z6bd!UX=Mb}*VR>>M@L3ds;d{jZLf@tjb+=X)pGE7wLA*zZZ3UkGHm>Ai7rAdOtZ!@<9lYWX?`vJ z*AUgx+*}bLMxAV&SjXe>5I{cmztGNb(;Zu)V~IrK7&_)WXe-XL&J7M4WH1=lb>y?{ zYinzPwuR8Y%tFDJ>}#4lJsNm3ucHVA0wai8S64?OIguwMMW5UxI!CIWgCQd#B82Ij z2X#hsidc6MI>ja?CV(>~@DkSD;Yw?)QS#1e;bd5E+-CKoKcHZ(oB&71EC)hWhy@T} zYHrR|Z|&$f9oU$c{B3Jli1i6_V4j)`9e*YE`EpBdZ*NuAu`@46IjS=B5rQM{@!^{{ z8O-G(aL9uP2E`0}f@|*JpPxQKT|p4nto@xQ8c4J!2yz+!zM`VSUTgC&MzQdV1{7H; z&CuGKMx~|!7cV&j#qucB-+nszbnz$peN)|}HvvWkOBjvuAmb2I<&0;}L}rk2g2V=w z>#^&pw8UaLHH_7(5~);V(aRv?I#rwaW_S(qeHpr~)L&`&I_aSWUS3{aR^8IDj72X{ zGf~bL%oU5nQE1O1u!59$zC$3z^Om zwa_o_*#Xsy!79jP@%ell4o4VyHL+e3axhe=&ExT8HLMa3b~sa0Qy)GE%W8P_>bLUp z>%`HhsHil}&zGSH1aoF)roX?x<=!xNj#kNBhF88~hZ92{hlPcOhBB8n%Pr%nJ6HF2 zcA^cHg1kJ6z{?89HJxI%|8^>^6|5}fIS}rUWhK(}^z`(Z7z}1D+M;3XmWPMAwY5g> zpt7=ZqelZfd?h{^gBcGq7j9bCfX!&@`J9-T7{HmQ{^-!q(~62(g-|=YbViWwY{~FS zuvZg_WKb})ZAp(DY&Z#myuRH81Xy0Hg zdT#f6A6BYSs9%lUunuzj(dERp68`6|83f;iGkBU-mBKHP$Ss{5zB0?-`67An(Kv3x z-xX9+4-eBLdnvtEGgZZ_b~5EFRN}H060Ky=&?l?k`>MY35AE#i1W8@f8{D-uEu+Pwra;(a1fNUW zYw?{3d2{oNZy=3k1`BYW|IlNs`N+NM@M#+_cn-czx4sAiRMj_O>*?Wp+YhsO?B;XY z)$UbEnP<^=B_-v!F25KX+XDPI__VbxmqZE#jh=5-2-NaXn3_O+j=7oS8}U~DD$!BU za+YB1MT(B)wx~FX|1P&1{;-Q3-ockX>9*Ao{ZVkh-KIs-Rt0Ot?-ujLH`aVpzVU75 zzLff%kiFxvmD6^}8uBeoIp}7DKgY1qf>k>@IFQL?hGl3bWE2IVZ<+QA+&tHxetE)A4~<_vz5F)Zcx1~5~22Xf2u7s yE5<n@U?<$S#{i{8SO*KO66@fvV?VD`<(*6T?__BEb literal 0 HcmV?d00001 diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.service.ts b/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.service.ts index f2b07d1b99..fe56857a9a 100644 --- a/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.service.ts +++ b/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.service.ts @@ -16,7 +16,7 @@ */ import { Injectable } from '@angular/core'; -import { SearchCategory } from '../search/search-category.interface'; +import { SearchCategory } from '../search/models/search-category.interface'; @Injectable({ providedIn: 'root' diff --git a/lib/content-services/src/lib/document-list/components/document-list.component.ts b/lib/content-services/src/lib/document-list/components/document-list.component.ts index d128eb49eb..272d32320e 100644 --- a/lib/content-services/src/lib/document-list/components/document-list.component.ts +++ b/lib/content-services/src/lib/document-list/components/document-list.component.ts @@ -57,7 +57,7 @@ import { ContentActionModel } from './../models/content-action.model'; import { PermissionStyleModel } from './../models/permissions-style.model'; import { NodeEntityEvent, NodeEntryEvent } from './node.event'; import { NavigableComponentInterface } from '../../breadcrumb/navigable-component.interface'; -import { FilterSearch } from './../../search/filter-search.interface'; +import { FilterSearch } from './../../search/models/filter-search.interface'; import { RowFilter } from '../data/row-filter.model'; import { DocumentListService } from '../services/document-list.service'; import { DocumentLoaderNode } from '../models/document-folder.model'; diff --git a/lib/content-services/src/lib/document-list/components/filter-header/filter-header.component.ts b/lib/content-services/src/lib/document-list/components/filter-header/filter-header.component.ts index e0c7eefd16..0e25b5f662 100644 --- a/lib/content-services/src/lib/document-list/components/filter-header/filter-header.component.ts +++ b/lib/content-services/src/lib/document-list/components/filter-header/filter-header.component.ts @@ -20,7 +20,7 @@ import { PaginationModel, DataSorting } from '@alfresco/adf-core'; import { DocumentListComponent } from '../document-list.component'; import { SEARCH_QUERY_SERVICE_TOKEN } from '../../../search/search-query-service.token'; import { SearchHeaderQueryBuilderService } from '../../../search/search-header-query-builder.service'; -import { FilterSearch } from './../../../search/filter-search.interface'; +import { FilterSearch } from './../../../search/models/filter-search.interface'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { NodePaging, MinimalNode } from '@alfresco/js-api'; diff --git a/lib/content-services/src/lib/i18n/en.json b/lib/content-services/src/lib/i18n/en.json index d5f91d3c19..d0c6687cdf 100644 --- a/lib/content-services/src/lib/i18n/en.json +++ b/lib/content-services/src/lib/i18n/en.json @@ -290,6 +290,8 @@ } } }, + "FORMS": "Search Forms", + "UNKNOWN_FORM": "Unknown Configuration", "SEARCH_HEADER" : { "TITLE":"Filter", "TYPE": "Type", diff --git a/lib/content-services/src/lib/mock/content-model.mock.ts b/lib/content-services/src/lib/mock/content-model.mock.ts index d30ca8b34d..fc79b14f57 100644 --- a/lib/content-services/src/lib/mock/content-model.mock.ts +++ b/lib/content-services/src/lib/mock/content-model.mock.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { SearchCategory } from '../search/search-category.interface'; +import { SearchCategory } from '../search/models/search-category.interface'; export const mockContentModelTextProperty = { name: 'name', diff --git a/lib/content-services/src/lib/search/base-query-builder.service.ts b/lib/content-services/src/lib/search/base-query-builder.service.ts index 360aa162af..c886bb8064 100644 --- a/lib/content-services/src/lib/search/base-query-builder.service.ts +++ b/lib/content-services/src/lib/search/base-query-builder.service.ts @@ -27,24 +27,31 @@ import { RequestHighlight, RequestScope } from '@alfresco/js-api'; -import { SearchCategory } from './search-category.interface'; -import { FilterQuery } from './filter-query.interface'; -import { SearchRange } from './search-range.interface'; -import { SearchConfiguration } from './search-configuration.interface'; -import { FacetQuery } from './facet-query.interface'; -import { SearchSortingDefinition } from './search-sorting-definition.interface'; -import { FacetField } from './facet-field.interface'; -import { FacetFieldBucket } from './facet-field-bucket.interface'; +import { SearchCategory } from './models/search-category.interface'; +import { FilterQuery } from './models/filter-query.interface'; +import { SearchRange } from './models/search-range.interface'; +import { SearchConfiguration } from './models/search-configuration.interface'; +import { FacetQuery } from './models/facet-query.interface'; +import { SearchSortingDefinition } from './models/search-sorting-definition.interface'; +import { FacetField } from './models/facet-field.interface'; +import { FacetFieldBucket } from './models/facet-field-bucket.interface'; +import { SearchForm } from './models/search-form.interface'; @Injectable({ providedIn: 'root' }) export abstract class BaseQueryBuilderService { - private _userQuery = ''; + /* Stream that emits the search configuration whenever the user change the search forms */ + configUpdated = new Subject(); + /* Stream that emits the query before search whenever user search */ updated = new Subject(); + + /* Stream that emits the results whenever user search */ executed = new Subject(); + + /* Stream that emits the error whenever user search */ error = new Subject(); categories: SearchCategory[] = []; @@ -54,6 +61,8 @@ export abstract class BaseQueryBuilderService { sorting: SearchSortingDefinition[] = []; sortingOptions: SearchSortingDefinition[] = []; private scope: RequestScope; + private selectedConfiguration: number; + private _userQuery = ''; protected userFacetBuckets: { [key: string]: FacetFieldBucket[] } = {}; @@ -77,15 +86,62 @@ export abstract class BaseQueryBuilderService { this.resetToDefaults(); } - public abstract loadConfiguration(): SearchConfiguration; + public abstract loadConfiguration(): SearchConfiguration | SearchConfiguration[]; public abstract isFilterServiceActive(): boolean; public resetToDefaults() { - const currentConfig = this.loadConfiguration(); + const currentConfig = this.getDefaultConfiguration(); + this.configUpdated.next(currentConfig); this.setUpSearchConfiguration(currentConfig); } + public getDefaultConfiguration(): SearchConfiguration | undefined { + const configurations = this.loadConfiguration(); + + if (this.selectedConfiguration >= 0) { + return configurations[this.selectedConfiguration]; + } + + if (Array.isArray(configurations)) { + return configurations.find((configuration) => configuration.default); + } + return configurations; + } + + public updateSelectedConfiguration(index: number): void { + const currentConfig = this.loadConfiguration(); + if (Array.isArray(currentConfig) && currentConfig[index] !== undefined) { + this.configUpdated.next(currentConfig[index]); + this.selectedConfiguration = index; + this.resetSearchOptions(); + this.setUpSearchConfiguration(currentConfig[index]); + this.update(); + } + } + + private resetSearchOptions(): void { + this.categories = []; + this.queryFragments = {}; + this.filterQueries = []; + this.sorting = []; + this.sortingOptions = []; + this.scope = null; + } + + public getSearchConfigurationDetails(): SearchForm[] { + const configurations = this.loadConfiguration(); + if (Array.isArray(configurations)) { + return configurations.map((configuration, index) => ({ + index, + name: configuration.name || 'SEARCH.UNKNOWN_FORM', + default: configuration.default || false, + selected: this.selectedConfiguration !== undefined ? index === this.selectedConfiguration : configuration.default + })); + } + return []; + } + private setUpSearchConfiguration(currentConfiguration: SearchConfiguration) { if (currentConfiguration) { this.config = JSON.parse(JSON.stringify(currentConfiguration)); diff --git a/lib/content-services/src/lib/search/components/search-check-list/search-check-list.component.spec.ts b/lib/content-services/src/lib/search/components/search-check-list/search-check-list.component.spec.ts index 65e5151542..00b3fa51d5 100644 --- a/lib/content-services/src/lib/search/components/search-check-list/search-check-list.component.spec.ts +++ b/lib/content-services/src/lib/search/components/search-check-list/search-check-list.component.spec.ts @@ -16,7 +16,7 @@ */ import { SearchCheckListComponent, SearchListOption } from './search-check-list.component'; -import { SearchFilterList } from '../search-filter/models/search-filter-list.model'; +import { SearchFilterList } from '../../models/search-filter-list.model'; import { setupTestBed } from '@alfresco/adf-core'; import { ContentTestingModule } from '../../../testing/content.testing.module'; import { ComponentFixture, TestBed } from '@angular/core/testing'; diff --git a/lib/content-services/src/lib/search/components/search-check-list/search-check-list.component.ts b/lib/content-services/src/lib/search/components/search-check-list/search-check-list.component.ts index 809cd388ea..f69c001b46 100644 --- a/lib/content-services/src/lib/search/components/search-check-list/search-check-list.component.ts +++ b/lib/content-services/src/lib/search/components/search-check-list/search-check-list.component.ts @@ -17,10 +17,10 @@ import { Component, ViewEncapsulation, OnInit } from '@angular/core'; import { MatCheckboxChange } from '@angular/material/checkbox'; -import { SearchWidget } from '../../search-widget.interface'; -import { SearchWidgetSettings } from '../../search-widget-settings.interface'; +import { SearchWidget } from '../../models/search-widget.interface'; +import { SearchWidgetSettings } from '../../models/search-widget-settings.interface'; import { SearchQueryBuilderService } from '../../search-query-builder.service'; -import { SearchFilterList } from '../search-filter/models/search-filter-list.model'; +import { SearchFilterList } from '../../models/search-filter-list.model'; export interface SearchListOption { name: string; diff --git a/lib/content-services/src/lib/search/components/search-date-range/search-date-range.component.ts b/lib/content-services/src/lib/search/components/search-date-range/search-date-range.component.ts index 785455151b..e2f692712c 100644 --- a/lib/content-services/src/lib/search/components/search-date-range/search-date-range.component.ts +++ b/lib/content-services/src/lib/search/components/search-date-range/search-date-range.component.ts @@ -20,8 +20,8 @@ import { FormControl, Validators, FormGroup } from '@angular/forms'; import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core'; import { MomentDateAdapter, MOMENT_DATE_FORMATS, UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core'; -import { SearchWidget } from '../../search-widget.interface'; -import { SearchWidgetSettings } from '../../search-widget-settings.interface'; +import { SearchWidget } from '../../models/search-widget.interface'; +import { SearchWidgetSettings } from '../../models/search-widget-settings.interface'; import { SearchQueryBuilderService } from '../../search-query-builder.service'; import { LiveErrorStateMatcher } from '../../forms/live-error-state-matcher'; import { Moment } from 'moment'; diff --git a/lib/content-services/src/lib/search/components/search-datetime-range/search-datetime-range.component.ts b/lib/content-services/src/lib/search/components/search-datetime-range/search-datetime-range.component.ts index 728597bc65..eca4c1d111 100644 --- a/lib/content-services/src/lib/search/components/search-datetime-range/search-datetime-range.component.ts +++ b/lib/content-services/src/lib/search/components/search-datetime-range/search-datetime-range.component.ts @@ -19,8 +19,8 @@ import { OnInit, Component, ViewEncapsulation, OnDestroy } from '@angular/core'; import { FormControl, Validators, FormGroup } from '@angular/forms'; import { UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core'; -import { SearchWidget } from '../../search-widget.interface'; -import { SearchWidgetSettings } from '../../search-widget-settings.interface'; +import { SearchWidget } from '../../models/search-widget.interface'; +import { SearchWidgetSettings } from '../../models/search-widget-settings.interface'; import { SearchQueryBuilderService } from '../../search-query-builder.service'; import { LiveErrorStateMatcher } from '../../forms/live-error-state-matcher'; import { Moment } from 'moment'; diff --git a/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.spec.ts b/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.spec.ts index de259e60f3..01f28e695e 100644 --- a/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.spec.ts +++ b/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.spec.ts @@ -25,7 +25,7 @@ import { SEARCH_QUERY_SERVICE_TOKEN } from '../../search-query-service.token'; import { By } from '@angular/platform-browser'; import { SearchFilterContainerComponent } from './search-filter-container.component'; import { MatMenuTrigger } from '@angular/material/menu'; -import { SearchCategory } from '../../search-category.interface'; +import { SearchCategory } from '../../models/search-category.interface'; const mockCategory: SearchCategory = { 'id': 'queryName', diff --git a/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.ts b/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.ts index dd34f78e34..3ed55315a3 100644 --- a/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.ts +++ b/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.ts @@ -31,7 +31,7 @@ import { ConfigurableFocusTrapFactory, ConfigurableFocusTrap } from '@angular/cd import { DataColumn, TranslationService } from '@alfresco/adf-core'; import { SearchWidgetContainerComponent } from '../search-widget-container/search-widget-container.component'; import { SearchHeaderQueryBuilderService } from '../../search-header-query-builder.service'; -import { SearchCategory } from '../../search-category.interface'; +import { SearchCategory } from '../../models/search-category.interface'; import { SEARCH_QUERY_SERVICE_TOKEN } from '../../search-query-service.token'; import { Subject } from 'rxjs'; import { MatMenuTrigger } from '@angular/material/menu'; diff --git a/lib/content-services/src/lib/search/components/search-filter/search-filter.component.spec.ts b/lib/content-services/src/lib/search/components/search-filter/search-filter.component.spec.ts index 84dd85f50f..f87f4ab3bb 100644 --- a/lib/content-services/src/lib/search/components/search-filter/search-filter.component.spec.ts +++ b/lib/content-services/src/lib/search/components/search-filter/search-filter.component.spec.ts @@ -19,9 +19,9 @@ import { SearchFilterComponent } from './search-filter.component'; import { SearchQueryBuilderService } from '../../search-query-builder.service'; import { AppConfigService, SearchService, setupTestBed, TranslationService } from '@alfresco/adf-core'; import { Subject } from 'rxjs'; -import { FacetFieldBucket } from '../../facet-field-bucket.interface'; -import { FacetField } from '../../facet-field.interface'; -import { SearchFilterList } from './models/search-filter-list.model'; +import { FacetFieldBucket } from '../../models/facet-field-bucket.interface'; +import { FacetField } from '../../models/facet-field.interface'; +import { SearchFilterList } from '../../models/search-filter-list.model'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { ContentTestingModule } from '../../../testing/content.testing.module'; diff --git a/lib/content-services/src/lib/search/components/search-filter/search-filter.component.ts b/lib/content-services/src/lib/search/components/search-filter/search-filter.component.ts index e59225309c..83e5ae7af0 100644 --- a/lib/content-services/src/lib/search/components/search-filter/search-filter.component.ts +++ b/lib/content-services/src/lib/search/components/search-filter/search-filter.component.ts @@ -19,9 +19,9 @@ import { Component, ViewEncapsulation, OnInit, OnDestroy, Inject, Input } from ' import { MatCheckboxChange } from '@angular/material/checkbox'; import { TranslationService, SearchService } from '@alfresco/adf-core'; import { SearchQueryBuilderService } from '../../search-query-builder.service'; -import { FacetFieldBucket } from '../../facet-field-bucket.interface'; -import { FacetField } from '../../facet-field.interface'; -import { SearchFilterList } from './models/search-filter-list.model'; +import { FacetFieldBucket } from '../../models/facet-field-bucket.interface'; +import { FacetField } from '../../models/facet-field.interface'; +import { SearchFilterList } from '../../models/search-filter-list.model'; import { takeUntil } from 'rxjs/operators'; import { GenericBucket, GenericFacetResponse, ResultSetContext, ResultSetPaging } from '@alfresco/js-api'; import { Subject } from 'rxjs'; diff --git a/lib/content-services/src/lib/search/components/search-form/search-form.component.html b/lib/content-services/src/lib/search/components/search-form/search-form.component.html new file mode 100644 index 0000000000..ebfc225a4c --- /dev/null +++ b/lib/content-services/src/lib/search/components/search-form/search-form.component.html @@ -0,0 +1,8 @@ + + {{ 'SEARCH.FORMS' | translate }} + + + {{form.name | translate}} + + + diff --git a/lib/content-services/src/lib/search/components/search-form/search-form.component.spec.ts b/lib/content-services/src/lib/search/components/search-form/search-form.component.spec.ts new file mode 100644 index 0000000000..e97486662d --- /dev/null +++ b/lib/content-services/src/lib/search/components/search-form/search-form.component.spec.ts @@ -0,0 +1,91 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * 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 { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SearchFormComponent } from './search-form.component'; +import { setupTestBed } from '@alfresco/adf-core'; +import { TranslateModule } from '@ngx-translate/core'; +import { ContentTestingModule } from '../../../testing/content.testing.module'; +import { SEARCH_QUERY_SERVICE_TOKEN } from '../../search-query-service.token'; +import { SearchHeaderQueryBuilderService } from '../../search-header-query-builder.service'; +import { SearchForm } from '../../models/search-form.interface'; +import { By } from '@angular/platform-browser'; + +describe('SearchFormComponent', () => { + let fixture: ComponentFixture; + let component: SearchFormComponent; + let queryBuilder: SearchHeaderQueryBuilderService; + const mockSearchForms: SearchForm[] = [ + { default: false, index: 0, name: 'All', selected: false }, + { default: true, index: 1, name: 'First', selected: true }, + { default: false, index: 2, name: 'Second', selected: false } + ]; + + setupTestBed({ + imports: [ + TranslateModule.forRoot(), + ContentTestingModule + ], + providers: [ + { provide: SEARCH_QUERY_SERVICE_TOKEN, useClass: SearchHeaderQueryBuilderService } + ] + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchFormComponent); + component = fixture.componentInstance; + queryBuilder = TestBed.inject(SEARCH_QUERY_SERVICE_TOKEN); + spyOn(queryBuilder, 'getSearchConfigurationDetails').and.returnValue(mockSearchForms); + fixture.detectChanges(); + }); + + it('should show search forms', async () => { + await fixture.whenStable(); + fixture.detectChanges(); + expect(component.selected).toBe(1); + const label = fixture.debugElement.query(By.css('.mat-form-field mat-label')); + expect(label.nativeElement.innerText).toContain('SEARCH.FORMS'); + const selectValue = fixture.debugElement.query(By.css('.mat-select-value')); + expect(selectValue.nativeElement.innerText).toContain('First'); + }); + + it('should emit on form change', async (done) => { + component.formChange.subscribe((form) => { + expect(form).toEqual(mockSearchForms[2]); + done(); + }); + + await fixture.whenStable(); + fixture.detectChanges(); + + const matSelect = fixture.debugElement.query(By.css('.mat-select-trigger')).nativeElement; + matSelect.click(); + fixture.detectChanges(); + + const matOption = fixture.debugElement.queryAll(By.css('.mat-option'))[2].nativeElement; + matOption.click(); + }); + + it('should not display search form if no form configured', async () => { + component.searchForms = []; + await fixture.whenStable(); + fixture.detectChanges(); + const field = fixture.debugElement.query(By.css('.mat-form-field')); + expect(field).toEqual(null, 'search form displayed for empty configuration'); + }); +}); diff --git a/lib/content-services/src/lib/search/components/search-form/search-form.component.ts b/lib/content-services/src/lib/search/components/search-form/search-form.component.ts new file mode 100644 index 0000000000..181fb56d71 --- /dev/null +++ b/lib/content-services/src/lib/search/components/search-form/search-form.component.ts @@ -0,0 +1,44 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * 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 { Component, EventEmitter, Inject, OnInit, Output } from '@angular/core'; +import { SearchQueryBuilderService } from '../../search-query-builder.service'; +import { SearchForm } from '../../models/search-form.interface'; +import { SEARCH_QUERY_SERVICE_TOKEN } from '../../search-query-service.token'; + +@Component({ + selector: 'adf-search-form', + templateUrl: './search-form.component.html' +}) +export class SearchFormComponent implements OnInit { + @Output() + formChange: EventEmitter = new EventEmitter(); + + selected: number; + searchForms: SearchForm[] = []; + + constructor(@Inject(SEARCH_QUERY_SERVICE_TOKEN) private queryBuilder: SearchQueryBuilderService) {} + + ngOnInit(): void { + this.searchForms = this.queryBuilder.getSearchConfigurationDetails(); + this.selected = this.searchForms.find(form => form.selected)?.index; + } + + onSelectionChange(index: number) { + this.formChange.emit(this.searchForms[index]); + } +} diff --git a/lib/content-services/src/lib/search/components/search-number-range/search-number-range.component.ts b/lib/content-services/src/lib/search/components/search-number-range/search-number-range.component.ts index 993ae92ef6..0e40423bc6 100644 --- a/lib/content-services/src/lib/search/components/search-number-range/search-number-range.component.ts +++ b/lib/content-services/src/lib/search/components/search-number-range/search-number-range.component.ts @@ -17,8 +17,8 @@ import { OnInit, Component, ViewEncapsulation } from '@angular/core'; import { FormControl, Validators, FormGroup } from '@angular/forms'; -import { SearchWidget } from '../../search-widget.interface'; -import { SearchWidgetSettings } from '../../search-widget-settings.interface'; +import { SearchWidget } from '../../models/search-widget.interface'; +import { SearchWidgetSettings } from '../../models/search-widget-settings.interface'; import { SearchQueryBuilderService } from '../../search-query-builder.service'; import { LiveErrorStateMatcher } from '../../forms/live-error-state-matcher'; diff --git a/lib/content-services/src/lib/search/components/search-panel/search-panel.component.spec.ts b/lib/content-services/src/lib/search/components/search-panel/search-panel.component.spec.ts index 0927170e33..fd7f015d9b 100644 --- a/lib/content-services/src/lib/search/components/search-panel/search-panel.component.spec.ts +++ b/lib/content-services/src/lib/search/components/search-panel/search-panel.component.spec.ts @@ -16,7 +16,7 @@ */ import { SearchCheckListComponent, SearchListOption } from '../search-check-list/search-check-list.component'; -import { SearchFilterList } from '../search-filter/models/search-filter-list.model'; +import { SearchFilterList } from '../../models/search-filter-list.model'; import { setupTestBed } from '@alfresco/adf-core'; import { ContentTestingModule } from '../../../testing/content.testing.module'; import { ComponentFixture, TestBed } from '@angular/core/testing'; diff --git a/lib/content-services/src/lib/search/components/search-radio/search-radio.component.spec.ts b/lib/content-services/src/lib/search/components/search-radio/search-radio.component.spec.ts index e942a6f43b..9b93bbfa68 100644 --- a/lib/content-services/src/lib/search/components/search-radio/search-radio.component.spec.ts +++ b/lib/content-services/src/lib/search/components/search-radio/search-radio.component.spec.ts @@ -91,8 +91,8 @@ describe('SearchRadioComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const optionElements = fixture.debugElement.query(By.css('mat-radio-button')); - optionElements.triggerEventHandler('change', { checked: true }); + const optionElements = fixture.debugElement.query(By.css('mat-radio-group')); + optionElements.triggerEventHandler('change', { value: sizeOptions[0].value }); fixture.detectChanges(); expect(component.context.update).toHaveBeenCalled(); diff --git a/lib/content-services/src/lib/search/components/search-radio/search-radio.component.ts b/lib/content-services/src/lib/search/components/search-radio/search-radio.component.ts index 30df70c983..a1e55dd7b2 100644 --- a/lib/content-services/src/lib/search/components/search-radio/search-radio.component.ts +++ b/lib/content-services/src/lib/search/components/search-radio/search-radio.component.ts @@ -18,10 +18,10 @@ import { Component, ViewEncapsulation, OnInit, Input } from '@angular/core'; import { MatRadioChange } from '@angular/material/radio'; -import { SearchWidget } from '../../search-widget.interface'; -import { SearchWidgetSettings } from '../../search-widget-settings.interface'; +import { SearchWidget } from '../../models/search-widget.interface'; +import { SearchWidgetSettings } from '../../models/search-widget-settings.interface'; import { SearchQueryBuilderService } from '../../search-query-builder.service'; -import { SearchFilterList } from '../search-filter/models/search-filter-list.model'; +import { SearchFilterList } from '../../models/search-filter-list.model'; export interface SearchRadioOption { name: string; @@ -67,9 +67,11 @@ export class SearchRadioComponent implements SearchWidget, OnInit { const initialValue = this.getSelectedValue(); if (initialValue !== null) { - this.setValue(initialValue); + this.value = initialValue; + this.context.queryFragments[this.id] = initialValue; } else if (this.startValue !== null) { - this.setValue(initialValue); + this.value = initialValue; + this.context.queryFragments[this.id] = initialValue; } } diff --git a/lib/content-services/src/lib/search/components/search-slider/search-slider.component.ts b/lib/content-services/src/lib/search/components/search-slider/search-slider.component.ts index a76397dc05..da53ee455b 100644 --- a/lib/content-services/src/lib/search/components/search-slider/search-slider.component.ts +++ b/lib/content-services/src/lib/search/components/search-slider/search-slider.component.ts @@ -16,8 +16,8 @@ */ import { Component, ViewEncapsulation, OnInit, Input } from '@angular/core'; -import { SearchWidget } from '../../search-widget.interface'; -import { SearchWidgetSettings } from '../../search-widget-settings.interface'; +import { SearchWidget } from '../../models/search-widget.interface'; +import { SearchWidgetSettings } from '../../models/search-widget-settings.interface'; import { SearchQueryBuilderService } from '../../search-query-builder.service'; import { MatSliderChange } from '@angular/material/slider'; diff --git a/lib/content-services/src/lib/search/components/search-sorting-picker/search-sorting-picker.component.spec.ts b/lib/content-services/src/lib/search/components/search-sorting-picker/search-sorting-picker.component.spec.ts index 272faed301..5fca98dd6d 100644 --- a/lib/content-services/src/lib/search/components/search-sorting-picker/search-sorting-picker.component.spec.ts +++ b/lib/content-services/src/lib/search/components/search-sorting-picker/search-sorting-picker.component.spec.ts @@ -18,7 +18,7 @@ import { SearchSortingPickerComponent } from './search-sorting-picker.component'; import { SearchQueryBuilderService } from '../../search-query-builder.service'; import { AppConfigService } from '@alfresco/adf-core'; -import { SearchConfiguration } from '../../search-configuration.interface'; +import { SearchConfiguration } from '../../models/search-configuration.interface'; import { TestBed } from '@angular/core/testing'; import { ContentTestingModule } from '../../../testing/content.testing.module'; diff --git a/lib/content-services/src/lib/search/components/search-sorting-picker/search-sorting-picker.component.ts b/lib/content-services/src/lib/search/components/search-sorting-picker/search-sorting-picker.component.ts index 397e1f44ce..02fe1c0c3b 100644 --- a/lib/content-services/src/lib/search/components/search-sorting-picker/search-sorting-picker.component.ts +++ b/lib/content-services/src/lib/search/components/search-sorting-picker/search-sorting-picker.component.ts @@ -17,7 +17,7 @@ import { Component, OnInit, ViewEncapsulation, Inject } from '@angular/core'; import { SearchQueryBuilderService } from '../../search-query-builder.service'; -import { SearchSortingDefinition } from '../../search-sorting-definition.interface'; +import { SearchSortingDefinition } from '../../models/search-sorting-definition.interface'; import { SEARCH_QUERY_SERVICE_TOKEN } from '../../search-query-service.token'; @Component({ diff --git a/lib/content-services/src/lib/search/components/search-text/search-text.component.ts b/lib/content-services/src/lib/search/components/search-text/search-text.component.ts index dda4c4d454..88dbbe7850 100644 --- a/lib/content-services/src/lib/search/components/search-text/search-text.component.ts +++ b/lib/content-services/src/lib/search/components/search-text/search-text.component.ts @@ -16,8 +16,8 @@ */ import { Component, ViewEncapsulation, OnInit, Input } from '@angular/core'; -import { SearchWidget } from '../../search-widget.interface'; -import { SearchWidgetSettings } from '../../search-widget-settings.interface'; +import { SearchWidget } from '../../models/search-widget.interface'; +import { SearchWidgetSettings } from '../../models/search-widget-settings.interface'; import { SearchQueryBuilderService } from '../../search-query-builder.service'; @Component({ diff --git a/lib/content-services/src/lib/search/facet-field-bucket.interface.ts b/lib/content-services/src/lib/search/models/facet-field-bucket.interface.ts similarity index 100% rename from lib/content-services/src/lib/search/facet-field-bucket.interface.ts rename to lib/content-services/src/lib/search/models/facet-field-bucket.interface.ts diff --git a/lib/content-services/src/lib/search/facet-field.interface.ts b/lib/content-services/src/lib/search/models/facet-field.interface.ts similarity index 91% rename from lib/content-services/src/lib/search/facet-field.interface.ts rename to lib/content-services/src/lib/search/models/facet-field.interface.ts index 22d6f78742..961634c07d 100644 --- a/lib/content-services/src/lib/search/facet-field.interface.ts +++ b/lib/content-services/src/lib/search/models/facet-field.interface.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { SearchFilterList } from './components/search-filter/models/search-filter-list.model'; +import { SearchFilterList } from './search-filter-list.model'; import { FacetFieldBucket } from './facet-field-bucket.interface'; export interface FacetField { diff --git a/lib/content-services/src/lib/search/facet-query.interface.ts b/lib/content-services/src/lib/search/models/facet-query.interface.ts similarity index 100% rename from lib/content-services/src/lib/search/facet-query.interface.ts rename to lib/content-services/src/lib/search/models/facet-query.interface.ts diff --git a/lib/content-services/src/lib/search/filter-query.interface.ts b/lib/content-services/src/lib/search/models/filter-query.interface.ts similarity index 100% rename from lib/content-services/src/lib/search/filter-query.interface.ts rename to lib/content-services/src/lib/search/models/filter-query.interface.ts diff --git a/lib/content-services/src/lib/search/filter-search.interface.ts b/lib/content-services/src/lib/search/models/filter-search.interface.ts similarity index 100% rename from lib/content-services/src/lib/search/filter-search.interface.ts rename to lib/content-services/src/lib/search/models/filter-search.interface.ts diff --git a/lib/content-services/src/lib/search/components/search-filter/models/response-facet-query-list.model.ts b/lib/content-services/src/lib/search/models/response-facet-query-list.model.ts similarity index 100% rename from lib/content-services/src/lib/search/components/search-filter/models/response-facet-query-list.model.ts rename to lib/content-services/src/lib/search/models/response-facet-query-list.model.ts diff --git a/lib/content-services/src/lib/search/search-category.interface.ts b/lib/content-services/src/lib/search/models/search-category.interface.ts similarity index 100% rename from lib/content-services/src/lib/search/search-category.interface.ts rename to lib/content-services/src/lib/search/models/search-category.interface.ts diff --git a/lib/content-services/src/lib/search/search-configuration.interface.ts b/lib/content-services/src/lib/search/models/search-configuration.interface.ts similarity index 97% rename from lib/content-services/src/lib/search/search-configuration.interface.ts rename to lib/content-services/src/lib/search/models/search-configuration.interface.ts index 3bbca813b3..f4ca9fec19 100644 --- a/lib/content-services/src/lib/search/search-configuration.interface.ts +++ b/lib/content-services/src/lib/search/models/search-configuration.interface.ts @@ -49,4 +49,6 @@ export interface SearchConfiguration { defaults: SearchSortingDefinition[]; }; highlight?: RequestHighlight; + name?: string; + default?: boolean; } diff --git a/lib/content-services/src/lib/search/components/search-filter/models/search-filter-list.model.spec.ts b/lib/content-services/src/lib/search/models/search-filter-list.model.spec.ts similarity index 100% rename from lib/content-services/src/lib/search/components/search-filter/models/search-filter-list.model.spec.ts rename to lib/content-services/src/lib/search/models/search-filter-list.model.spec.ts diff --git a/lib/content-services/src/lib/search/components/search-filter/models/search-filter-list.model.ts b/lib/content-services/src/lib/search/models/search-filter-list.model.ts similarity index 100% rename from lib/content-services/src/lib/search/components/search-filter/models/search-filter-list.model.ts rename to lib/content-services/src/lib/search/models/search-filter-list.model.ts diff --git a/lib/content-services/src/lib/search/models/search-form.interface.ts b/lib/content-services/src/lib/search/models/search-form.interface.ts new file mode 100644 index 0000000000..e24320b9b1 --- /dev/null +++ b/lib/content-services/src/lib/search/models/search-form.interface.ts @@ -0,0 +1,23 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * 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. + */ + +export interface SearchForm { + index: number; + name: string; + default: boolean; + selected: boolean; +} diff --git a/lib/content-services/src/lib/search/search-range.interface.ts b/lib/content-services/src/lib/search/models/search-range.interface.ts similarity index 100% rename from lib/content-services/src/lib/search/search-range.interface.ts rename to lib/content-services/src/lib/search/models/search-range.interface.ts diff --git a/lib/content-services/src/lib/search/search-sorting-definition.interface.ts b/lib/content-services/src/lib/search/models/search-sorting-definition.interface.ts similarity index 100% rename from lib/content-services/src/lib/search/search-sorting-definition.interface.ts rename to lib/content-services/src/lib/search/models/search-sorting-definition.interface.ts diff --git a/lib/content-services/src/lib/search/search-widget-settings.interface.ts b/lib/content-services/src/lib/search/models/search-widget-settings.interface.ts similarity index 100% rename from lib/content-services/src/lib/search/search-widget-settings.interface.ts rename to lib/content-services/src/lib/search/models/search-widget-settings.interface.ts diff --git a/lib/content-services/src/lib/search/search-widget.interface.ts b/lib/content-services/src/lib/search/models/search-widget.interface.ts similarity index 92% rename from lib/content-services/src/lib/search/search-widget.interface.ts rename to lib/content-services/src/lib/search/models/search-widget.interface.ts index 6ec816e522..f4666ef416 100644 --- a/lib/content-services/src/lib/search/search-widget.interface.ts +++ b/lib/content-services/src/lib/search/models/search-widget.interface.ts @@ -16,7 +16,7 @@ */ import { SearchWidgetSettings } from './search-widget-settings.interface'; -import { SearchQueryBuilderService } from './search-query-builder.service'; +import { SearchQueryBuilderService } from '../search-query-builder.service'; export interface SearchWidget { id: string; diff --git a/lib/content-services/src/lib/search/public-api.ts b/lib/content-services/src/lib/search/public-api.ts index e4389a6008..e013d31306 100644 --- a/lib/content-services/src/lib/search/public-api.ts +++ b/lib/content-services/src/lib/search/public-api.ts @@ -15,17 +15,19 @@ * limitations under the License. */ -export * from './facet-field-bucket.interface'; -export * from './facet-field.interface'; -export * from './facet-query.interface'; -export * from './filter-query.interface'; -export * from './filter-search.interface'; -export * from './search-category.interface'; -export * from './search-widget-settings.interface'; -export * from './search-widget.interface'; -export * from './search-configuration.interface'; +export * from './models/facet-field-bucket.interface'; +export * from './models/facet-field.interface'; +export * from './models/facet-query.interface'; +export * from './models/filter-query.interface'; +export * from './models/filter-search.interface'; +export * from './models/search-category.interface'; +export * from './models/search-widget-settings.interface'; +export * from './models/search-widget.interface'; +export * from './models/search-configuration.interface'; export * from './search-query-builder.service'; -export * from './search-range.interface'; +export * from './models/search-range.interface'; +export * from './models/search-form.interface'; + export * from './search-query-service.token'; export * from './search-header-query-builder.service'; @@ -49,5 +51,6 @@ export * from './components/search-sorting-picker/search-sorting-picker.componen export * from './components/search-text/search-text.component'; export * from './components/search-widget-container/search-widget-container.component'; export * from './components/search-datetime-range/search-datetime-range.component'; +export * from './components/search-form/search-form.component'; export * from './search.module'; diff --git a/lib/content-services/src/lib/search/search-header-query-builder.service.spec.ts b/lib/content-services/src/lib/search/search-header-query-builder.service.spec.ts index b3716aea72..1def5e126b 100644 --- a/lib/content-services/src/lib/search/search-header-query-builder.service.spec.ts +++ b/lib/content-services/src/lib/search/search-header-query-builder.service.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { SearchConfiguration } from './search-configuration.interface'; +import { SearchConfiguration } from './models/search-configuration.interface'; import { AppConfigService } from '@alfresco/adf-core'; import { SearchHeaderQueryBuilderService } from './search-header-query-builder.service'; import { TestBed } from '@angular/core/testing'; diff --git a/lib/content-services/src/lib/search/search-header-query-builder.service.ts b/lib/content-services/src/lib/search/search-header-query-builder.service.ts index 249eb8eeb0..07e6d88104 100644 --- a/lib/content-services/src/lib/search/search-header-query-builder.service.ts +++ b/lib/content-services/src/lib/search/search-header-query-builder.service.ts @@ -17,14 +17,14 @@ import { Injectable } from '@angular/core'; import { AlfrescoApiService, AppConfigService, NodesApiService, DataSorting } from '@alfresco/adf-core'; -import { SearchConfiguration } from './search-configuration.interface'; +import { SearchConfiguration } from './models/search-configuration.interface'; import { BaseQueryBuilderService } from './base-query-builder.service'; -import { SearchCategory } from './search-category.interface'; +import { SearchCategory } from './models/search-category.interface'; import { MinimalNode, QueryBody } from '@alfresco/js-api'; import { filter } from 'rxjs/operators'; import { Observable } from 'rxjs'; -import { SearchSortingDefinition } from './search-sorting-definition.interface'; -import { FilterSearch } from './filter-search.interface'; +import { SearchSortingDefinition } from './models/search-sorting-definition.interface'; +import { FilterSearch } from './models/filter-search.interface'; @Injectable({ providedIn: 'root' diff --git a/lib/content-services/src/lib/search/search-query-builder.service.spec.ts b/lib/content-services/src/lib/search/search-query-builder.service.spec.ts index f0257f5b82..79396f15cb 100644 --- a/lib/content-services/src/lib/search/search-query-builder.service.spec.ts +++ b/lib/content-services/src/lib/search/search-query-builder.service.spec.ts @@ -16,9 +16,9 @@ */ import { SearchQueryBuilderService } from './search-query-builder.service'; -import { SearchConfiguration } from './search-configuration.interface'; +import { SearchConfiguration } from './models/search-configuration.interface'; import { AppConfigService } from '@alfresco/adf-core'; -import { FacetField } from './facet-field.interface'; +import { FacetField } from './models/facet-field.interface'; import { TestBed } from '@angular/core/testing'; import { ContentTestingModule } from '../testing/content.testing.module'; @@ -669,4 +669,91 @@ describe('SearchQueryBuilder', () => { expect(queryBody.scope).toEqual(mockScope); }); + + it('should return empty if array of search config not found', () => { + const builder = new SearchQueryBuilderService(buildConfig({}), null); + const forms = builder.getSearchConfigurationDetails(); + expect(forms).toEqual([]); + }); + + describe('Multiple search configuration', () => { + let configs: SearchConfiguration[]; + let builder: SearchQueryBuilderService; + beforeEach(() => { + configs = [ + { + categories: [ + { id: 'cat1', enabled: true }, + { id: 'cat2', enabled: true } + ], + filterQueries: [ + { query: 'query1' }, + { query: 'query2' } + ], + name: 'config1', + default: true + }, + { + categories: [ + { id: 'mouse', enabled: true } + ], + filterQueries: [ + { query: 'query1' }, + { query: 'query2' } + ], + name: 'config2', + default: false + }, + { + categories: [ + { id: 'cat_and_mouse', enabled: true } + ], + default: false + } + ]; + builder = new SearchQueryBuilderService(buildConfig(configs), null); + }); + + it('should pick the default configuration from list', () => { + builder.categories = []; + builder.filterQueries = []; + + expect(builder.categories.length).toBe(0); + expect(builder.filterQueries.length).toBe(0); + + builder.resetToDefaults(); + + expect(builder.categories.length).toBe(2); + expect(builder.categories.length).toBe(2); + expect(builder.filterQueries.length).toBe(2); + }); + + it('should list available search form names', () => { + const forms = builder.getSearchConfigurationDetails(); + + expect(forms).toEqual([ + { index: 0, name: 'config1', default: true, selected: true }, + { index: 1, name: 'config2', default: false, selected: false }, + { index: 2, name: 'SEARCH.UNKNOWN_FORM', default: false, selected: false } + ]); + }); + + it('should allow the user switch the form', () => { + builder.updateSelectedConfiguration(1); + + expect(builder.categories.length).toBe(1); + expect(builder.filterQueries.length).toBe(2); + }); + + it('should keep the selected configuration value', () => { + builder.updateSelectedConfiguration(1); + const forms = builder.getSearchConfigurationDetails(); + + expect(forms).toEqual([ + { index: 0, name: 'config1', default: true, selected: false }, + { index: 1, name: 'config2', default: false, selected: true }, + { index: 2, name: 'SEARCH.UNKNOWN_FORM', default: false, selected: false } + ]); + }); + }); }); diff --git a/lib/content-services/src/lib/search/search-query-builder.service.ts b/lib/content-services/src/lib/search/search-query-builder.service.ts index c87f45219a..a8b88a663a 100644 --- a/lib/content-services/src/lib/search/search-query-builder.service.ts +++ b/lib/content-services/src/lib/search/search-query-builder.service.ts @@ -17,7 +17,7 @@ import { Injectable } from '@angular/core'; import { AlfrescoApiService, AppConfigService } from '@alfresco/adf-core'; -import { SearchConfiguration } from './search-configuration.interface'; +import { SearchConfiguration } from './models/search-configuration.interface'; import { BaseQueryBuilderService } from './base-query-builder.service'; @Injectable() diff --git a/lib/content-services/src/lib/search/search.module.ts b/lib/content-services/src/lib/search/search.module.ts index bc509a9082..9e6add039a 100644 --- a/lib/content-services/src/lib/search/search.module.ts +++ b/lib/content-services/src/lib/search/search.module.ts @@ -40,6 +40,7 @@ import { SEARCH_QUERY_SERVICE_TOKEN } from './search-query-service.token'; import { SearchQueryBuilderService } from './search-query-builder.service'; import { SearchFilterContainerComponent } from './components/search-filter-container/search-filter-container.component'; import { SearchDatetimeRangeComponent } from './components/search-datetime-range/search-datetime-range.component'; +import { SearchFormComponent } from './components/search-form/search-form.component'; @NgModule({ imports: [ @@ -65,7 +66,8 @@ import { SearchDatetimeRangeComponent } from './components/search-datetime-range SearchDateRangeComponent, SearchDatetimeRangeComponent, SearchSortingPickerComponent, - SearchFilterContainerComponent + SearchFilterContainerComponent, + SearchFormComponent ], exports: [ SearchComponent, @@ -83,7 +85,8 @@ import { SearchDatetimeRangeComponent } from './components/search-datetime-range SearchDateRangeComponent, SearchDatetimeRangeComponent, SearchSortingPickerComponent, - SearchFilterContainerComponent + SearchFilterContainerComponent, + SearchFormComponent ], providers: [ { provide: SEARCH_QUERY_SERVICE_TOKEN, useExisting: SearchQueryBuilderService }, diff --git a/lib/core/app-config/schema.json b/lib/core/app-config/schema.json index 9fa3e22d30..2028c987bf 100644 --- a/lib/core/app-config/schema.json +++ b/lib/core/app-config/schema.json @@ -498,6 +498,404 @@ } } ] + }, + "search-configuration": { + "description": "Search configuration parameters", + "type": "object", + "required": [ + "categories" + ], + "properties": { + "include": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "fields": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "filterQueries": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": [ + "query" + ], + "properties": { + "query": { + "type": "string" + } + } + } + }, + "filterWithContains": { + "type": "boolean" + }, + "resetButton": { + "type": "boolean" + }, + "facetFields": { + "type": "object", + "required": [ + "fields" + ], + "properties": { + "expanded": { + "description": "Toggles expanded state of the facet field", + "type": "boolean" + }, + "fields": { + "description": "List of custom facet fields", + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": [ + "field", + "mincount", + "label" + ], + "properties": { + "field": { + "type": "string", + "description": "This specifies the facet field." + }, + "mincount": { + "type": "number", + "description": "This specifies the minimum count required for a facet field to be included in the response. The default value is 1." + }, + "label": { + "type": "string", + "description": "This specifies the label to include in place of the facet field." + }, + "prefix": { + "type": "string", + "description": "This restricts the possible constraints to only indexed values with a specified prefix." + }, + "limit": { + "type": "number", + "description": "Maximum number of results" + }, + "pageSize": { + "type": "number", + "description": "Display page size" + }, + "offset": { + "type": "integer" + } + } + } + } + } + }, + "facetIntervals": { + "type": "object", + "required": [ + "intervals" + ], + "properties": { + "intervals": { + "description": "List of facet intervals", + "type": "array", + "items": { + "type": "object", + "required": [ + "label", + "field", + "sets" + ], + "properties": { + "label": { + "description": "This specifies the label to use to identify the field facet.", + "type": "string" + }, + "field": { + "description": "This specifies the field to facet on.", + "type": "string" + }, + "sets": { + "type": "array", + "items": { + "type": "object", + "required": [ + "label", + "start", + "end" + ], + "properties": { + "label": { + "description": "This specifies the label to use to identify the set.", + "type": "string" + }, + "start": { + "description": "This specifies the start of the range.", + "type": "string" + }, + "end": { + "description": "This specifies the end of the range.", + "type": "string" + }, + "startInclusive": { + "description": "When true, the set will include values greater or equal to 'start'. The default value is true.", + "type": "boolean" + }, + "endInclusive": { + "description": "When true, the set will include values less than or equal to 'end'. The default value is true.", + "type": "boolean" + } + } + } + }, + "pageSize": { + "type": "number", + "description": "Display page size" + }, + "mincount": { + "type": "number", + "description": "This specifies the minimum count required for a facet interval to be displayed. The default value is 1." + } + } + } + }, + "expanded": { + "description": "Toggles expanded state of the facet intervals", + "type": "boolean" + } + } + }, + "facetQueries": { + "type": "object", + "required": [ + "label", + "queries" + ], + "properties": { + "label": { + "description": "Label text for the default facet queries group", + "type": "string" + }, + "pageSize": { + "description": "Default page size for the facet queries groups", + "type": "number" + }, + "expanded": { + "description": "Toggles expanded state of the facet queries groups", + "type": "boolean" + }, + "mincount": { + "description": "This specifies the minimum count required for a facet query to be displayed. The default value is 1.", + "type": "number" + }, + "queries": { + "description": "List of custom facet queries", + "type": "array", + "items": { + "type": "object", + "required": [ + "query", + "label" + ], + "properties": { + "query": { + "type": "string" + }, + "label": { + "description": "Unique identifier for the query", + "type": "string" + }, + "group": { + "description": "The group that the facet query belongs to. If no group is defined, the facet query will appear under the default facet queries group label", + "type": "string" + } + } + } + } + } + }, + "categories": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id", + "name" + ], + "properties": { + "id": {}, + "name": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "expanded": { + "type": "boolean" + }, + "component": { + "type": "object", + "required": [ + "selector", + "settings" + ], + "properties": { + "selector": { + "description": "Unique component runtime identifier", + "type": "string" + }, + "settings": { + "description": "Component-specific settings", + "type": "object" + } + } + } + } + } + }, + "highlight": { + "type": "object", + "description": " Request that highlight fragments to be added to result set rows The properties reflect SOLR highlighting parameters.", + "properties": { + "prefix": { + "description": "The string used to mark the start of a highlight in a fragment", + "type": "string" + }, + "postfix": { + "description": "The string used to mark the end of a highlight in a fragment", + "type": "string" + }, + "snippetCount": { + "description": "The maximum number of distinct highlight snippets to return for each highlight field", + "type": "number" + }, + "fragmentSize": { + "description": "The character length of each snippet", + "type": "number" + }, + "maxAnalyzedChars": { + "description": "The number of characters to be considered for highlighting. Matches after this count will not be shown", + "type": "number" + }, + "mergeContiguous": { + "description": "If fragments over lap they can be merged into one larger fragment", + "type": "boolean" + }, + "usePhraseHighlighter": { + "description": "Should phrases be identified", + "type": "boolean" + }, + "fields": { + "type": "array", + "minItems": 1, + "items": { + "description": "The fields to highlight and field specific configuration properties for each field", + "type": "object", + "properties": { + "field": { + "description": "The name of the field to highlight", + "type": "string" + }, + "snippetCount": { + "type": "number" + }, + "fragmentSize": { + "type": "number" + }, + "mergeContiguous": { + "type": "boolean" + }, + "prefix": { + "type": "string" + }, + "postfix": { + "type": "string" + } + } + } + } + } + }, + "sorting": { + "type" : "object", + "description": "Sorting options and defaults", + "required": [ + "options" + ], + "properties": { + "options": { + "type": "array", + "minItems": 1, + "items": { + "description": "Sorting options available for users to choose from", + "type": "object", + "required": [ + "key", + "label", + "type", + "field", + "ascending" + ], + "properties": { + "key": { + "type": "string" + }, + "label": { + "type": "string" + }, + "type": { + "type": "string" + }, + "field": { + "type": "string" + }, + "ascending": { + "type": "boolean" + } + } + } + }, + "defaults": { + "description": "Predefined sorting to execute by default", + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "label": { + "type": "string" + }, + "type": { + "type": "string" + }, + "field": { + "type": "string" + }, + "ascending": { + "type": "boolean" + } + } + } + } + } + }, + "name": { + "description": "The name of search configuration", + "type": "string" + }, + "default": { + "description": "Apply current search configuration by default", + "type": "boolean" + } + } } }, "type": "object", @@ -1123,394 +1521,19 @@ } }, "search": { - "description": "Search configuration parameters", - "type": "object", - "required": [ - "categories" - ], - "properties": { - "include": { + "anyOf": [ + { + "description": "Search configuration", + "$ref": "#/definitions/search-configuration" + }, + { "type": "array", - "minItems": 1, + "description": "Multiple search configuration", "items": { - "type": "string" - } - }, - "fields": { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - }, - "filterQueries": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "required": [ - "query" - ], - "properties": { - "query": { - "type": "string" - } - } - } - }, - "filterWithContains": { - "type": "boolean" - }, - "resetButton": { - "type": "boolean" - }, - "facetFields": { - "type": "object", - "required": [ - "fields" - ], - "properties": { - "expanded": { - "description": "Toggles expanded state of the facet field", - "type": "boolean" - }, - "fields": { - "description": "List of custom facet fields", - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "required": [ - "field", - "mincount", - "label" - ], - "properties": { - "field": { - "type": "string", - "description": "This specifies the facet field." - }, - "mincount": { - "type": "number", - "description": "This specifies the minimum count required for a facet field to be included in the response. The default value is 1." - }, - "label": { - "type": "string", - "description": "This specifies the label to include in place of the facet field." - }, - "prefix": { - "type": "string", - "description": "This restricts the possible constraints to only indexed values with a specified prefix." - }, - "limit": { - "type": "number", - "description": "Maximum number of results" - }, - "pageSize": { - "type": "number", - "description": "Display page size" - }, - "offset": { - "type": "integer" - } - } - } - } - } - }, - "facetIntervals": { - "type": "object", - "required": [ - "intervals" - ], - "properties": { - "intervals": { - "description": "List of facet intervals", - "type": "array", - "items": { - "type": "object", - "required": [ - "label", - "field", - "sets" - ], - "properties": { - "label": { - "description": "This specifies the label to use to identify the field facet.", - "type": "string" - }, - "field": { - "description": "This specifies the field to facet on.", - "type": "string" - }, - "sets": { - "type": "array", - "items": { - "type": "object", - "required": [ - "label", - "start", - "end" - ], - "properties": { - "label": { - "description": "This specifies the label to use to identify the set.", - "type": "string" - }, - "start": { - "description": "This specifies the start of the range.", - "type": "string" - }, - "end": { - "description": "This specifies the end of the range.", - "type": "string" - }, - "startInclusive": { - "description": "When true, the set will include values greater or equal to 'start'. The default value is true.", - "type": "boolean" - }, - "endInclusive": { - "description": "When true, the set will include values less than or equal to 'end'. The default value is true.", - "type": "boolean" - } - } - } - }, - "pageSize": { - "type": "number", - "description": "Display page size" - }, - "mincount": { - "type": "number", - "description": "This specifies the minimum count required for a facet interval to be displayed. The default value is 1." - } - } - } - }, - "expanded": { - "description": "Toggles expanded state of the facet intervals", - "type": "boolean" - } - } - }, - "facetQueries": { - "type": "object", - "required": [ - "label", - "queries" - ], - "properties": { - "label": { - "description": "Label text for the default facet queries group", - "type": "string" - }, - "pageSize": { - "description": "Default page size for the facet queries groups", - "type": "number" - }, - "expanded": { - "description": "Toggles expanded state of the facet queries groups", - "type": "boolean" - }, - "mincount": { - "description": "This specifies the minimum count required for a facet query to be displayed. The default value is 1.", - "type": "number" - }, - "queries": { - "description": "List of custom facet queries", - "type": "array", - "items": { - "type": "object", - "required": [ - "query", - "label" - ], - "properties": { - "query": { - "type": "string" - }, - "label": { - "description": "Unique identifier for the query", - "type": "string" - }, - "group": { - "description": "The group that the facet query belongs to. If no group is defined, the facet query will appear under the default facet queries group label", - "type": "string" - } - } - } - } - } - }, - "categories": { - "type": "array", - "items": { - "type": "object", - "required": [ - "id", - "name" - ], - "properties": { - "id": {}, - "name": { - "type": "string" - }, - "enabled": { - "type": "boolean" - }, - "expanded": { - "type": "boolean" - }, - "component": { - "type": "object", - "required": [ - "selector", - "settings" - ], - "properties": { - "selector": { - "description": "Unique component runtime identifier", - "type": "string" - }, - "settings": { - "description": "Component-specific settings", - "type": "object" - } - } - } - } - } - }, - "highlight": { - "type": "object", - "description": " Request that highlight fragments to be added to result set rows The properties reflect SOLR highlighting parameters.", - "properties": { - "prefix": { - "description": "The string used to mark the start of a highlight in a fragment", - "type": "string" - }, - "postfix": { - "description": "The string used to mark the end of a highlight in a fragment", - "type": "string" - }, - "snippetCount": { - "description": "The maximum number of distinct highlight snippets to return for each highlight field", - "type": "number" - }, - "fragmentSize": { - "description": "The character length of each snippet", - "type": "number" - }, - "maxAnalyzedChars": { - "description": "The number of characters to be considered for highlighting. Matches after this count will not be shown", - "type": "number" - }, - "mergeContiguous": { - "description": "If fragments over lap they can be merged into one larger fragment", - "type": "boolean" - }, - "usePhraseHighlighter": { - "description": "Should phrases be identified", - "type": "boolean" - }, - "fields": { - "type": "array", - "minItems": 1, - "items": { - "description": "The fields to highlight and field specific configuration properties for each field", - "type": "object", - "properties": { - "field": { - "description": "The name of the field to highlight", - "type": "string" - }, - "snippetCount": { - "type": "number" - }, - "fragmentSize": { - "type": "number" - }, - "mergeContiguous": { - "type": "boolean" - }, - "prefix": { - "type": "string" - }, - "postfix": { - "type": "string" - } - } - } - } - } - }, - "sorting": { - "type" : "object", - "description": "Sorting options and defaults", - "required": [ - "options" - ], - "properties": { - "options": { - "type": "array", - "minItems": 1, - "items": { - "description": "Sorting options available for users to choose from", - "type": "object", - "required": [ - "key", - "label", - "type", - "field", - "ascending" - ], - "properties": { - "key": { - "type": "string" - }, - "label": { - "type": "string" - }, - "type": { - "type": "string" - }, - "field": { - "type": "string" - }, - "ascending": { - "type": "boolean" - } - } - } - }, - "defaults": { - "description": "Predefined sorting to execute by default", - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "key": { - "type": "string" - }, - "label": { - "type": "string" - }, - "type": { - "type": "string" - }, - "field": { - "type": "string" - }, - "ascending": { - "type": "boolean" - } - } - } - } + "$ref": "#/definitions/search-configuration" } } - } + ] }, "adf-viewer": { "description": "Viewer default properties", diff --git a/lib/testing/index.ts b/lib/testing/index.ts index eb9b46c8bc..a7d78e665c 100644 --- a/lib/testing/index.ts +++ b/lib/testing/index.ts @@ -14,5 +14,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - export * from './src/public-api';