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 34e28137c4..532f157c11 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
@@ -15,9 +15,10 @@
* limitations under the License.
*/
-import { Component, OnInit, ViewEncapsulation } from '@angular/core';
+import { Component, OnInit, ViewEncapsulation, Inject } from '@angular/core';
import { SearchQueryBuilderService } from '../../search-query-builder.service';
import { SearchSortingDefinition } from '../../search-sorting-definition.interface';
+import { SEARCH_QUERY_SERVICE_TOKEN } from '../../search-query-service.token';
@Component({
selector: 'adf-search-sorting-picker',
@@ -32,7 +33,7 @@ export class SearchSortingPickerComponent implements OnInit {
value: string;
ascending: boolean;
- constructor(private queryBuilder: SearchQueryBuilderService) {}
+ constructor(@Inject(SEARCH_QUERY_SERVICE_TOKEN) private queryBuilder: SearchQueryBuilderService) {}
ngOnInit() {
this.options = this.queryBuilder.getSortingOptions();
diff --git a/lib/content-services/src/lib/search/components/search-widget-container/search-widget-container.component.ts b/lib/content-services/src/lib/search/components/search-widget-container/search-widget-container.component.ts
index 3ace735e27..d9ebd80f19 100644
--- a/lib/content-services/src/lib/search/components/search-widget-container/search-widget-container.component.ts
+++ b/lib/content-services/src/lib/search/components/search-widget-container/search-widget-container.component.ts
@@ -15,9 +15,10 @@
* limitations under the License.
*/
-import { Component, Input, ViewChild, ViewContainerRef, OnInit, OnDestroy, ComponentRef, ComponentFactoryResolver } from '@angular/core';
-import { SearchQueryBuilderService } from '../../search-query-builder.service';
+import { Component, Input, ViewChild, ViewContainerRef, OnInit, OnDestroy, ComponentRef, ComponentFactoryResolver, Inject } from '@angular/core';
import { SearchFilterService } from '../search-filter/search-filter.service';
+import { BaseQueryBuilderService } from '../../base-query-builder.service';
+import { SEARCH_QUERY_SERVICE_TOKEN } from '../../search-query-service.token';
@Component({
selector: 'adf-search-widget-container',
@@ -44,7 +45,7 @@ export class SearchWidgetContainerComponent implements OnInit, OnDestroy {
constructor(
private searchFilterService: SearchFilterService,
- private queryBuilder: SearchQueryBuilderService,
+ @Inject(SEARCH_QUERY_SERVICE_TOKEN) private queryBuilder: BaseQueryBuilderService,
private componentFactoryResolver: ComponentFactoryResolver) {
}
@@ -75,4 +76,15 @@ export class SearchWidgetContainerComponent implements OnInit, OnDestroy {
}
}
+ applyInnerWidget() {
+ if (this.selector === 'date-range' && this.componentRef && this.componentRef.instance) {
+ this.componentRef.instance.applyCurrentForm();
+ }
+ }
+
+ resetInnerWidget() {
+ if (this.componentRef && this.componentRef.instance) {
+ this.componentRef.instance.reset();
+ }
+ }
}
diff --git a/lib/content-services/src/lib/search/public-api.ts b/lib/content-services/src/lib/search/public-api.ts
index 3b3fa1770a..f62498360b 100644
--- a/lib/content-services/src/lib/search/public-api.ts
+++ b/lib/content-services/src/lib/search/public-api.ts
@@ -25,6 +25,8 @@ export * from './search-widget.interface';
export * from './search-configuration.interface';
export * from './search-query-builder.service';
export * from './search-range.interface';
+export * from './search-query-service.token';
+export * from './search-header-query-builder.service';
export * from './components/search.component';
export * from './components/search-control.component';
diff --git a/lib/content-services/src/lib/search/search-category.interface.ts b/lib/content-services/src/lib/search/search-category.interface.ts
index cd6975bf0c..4c54c46f76 100644
--- a/lib/content-services/src/lib/search/search-category.interface.ts
+++ b/lib/content-services/src/lib/search/search-category.interface.ts
@@ -20,6 +20,7 @@ import { SearchWidgetSettings } from './search-widget-settings.interface';
export interface SearchCategory {
id: string;
name: string;
+ columnKey?: string;
enabled: boolean;
expanded: boolean;
component: {
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
new file mode 100644
index 0000000000..62a9dee851
--- /dev/null
+++ b/lib/content-services/src/lib/search/search-header-query-builder.service.spec.ts
@@ -0,0 +1,178 @@
+/*!
+ * @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 { SearchConfiguration } from './search-configuration.interface';
+import { AppConfigService } from '@alfresco/adf-core';
+import { SearchHeaderQueryBuilderService } from './search-header-query-builder.service';
+
+describe('SearchHeaderQueryBuilder', () => {
+
+ const buildConfig = (searchSettings): AppConfigService => {
+ const config = new AppConfigService(null);
+ config.config['search-headers'] = searchSettings;
+ return config;
+ };
+
+ it('should load the configuration from app config', () => {
+ const config: SearchConfiguration = {
+ categories: [
+
{ id: 'cat1', enabled: true },
+ { id: 'cat2', enabled: true }
+ ],
+ filterQueries: [{ query: 'query1' }, { query: 'query2' }]
+ };
+
+ const builder = new SearchHeaderQueryBuilderService(
+ buildConfig(config),
+ null,
+ null
+ );
+
+ builder.categories = [];
+ builder.filterQueries = [];
+
+ expect(builder.categories.length).toBe(0);
+ expect(builder.filterQueries.length).toBe(0);
+
+ builder.setUpConfiguration();
+
+ expect(builder.categories.length).toBe(2);
+ expect(builder.filterQueries.length).toBe(2);
+ });
+
+ it('should return the category assigned to a column key', () => {
+ const config: SearchConfiguration = {
+ categories: [
+ { id: 'cat1', columnKey: 'fake-key-1', enabled: true },
+ { id: 'cat2', columnKey: 'fake-key-2', enabled: true }
+ ],
+ filterQueries: [{ query: 'query1' }, { query: 'query2' }]
+ };
+
+ const service = new SearchHeaderQueryBuilderService(
+ buildConfig(config),
+ null,
+ null
+ );
+
+ const category = service.getCategoryForColumn('fake-key-1');
+ expect(category).not.toBeNull();
+ expect(category).not.toBeUndefined();
+ expect(category.columnKey).toBe('fake-key-1');
+ });
+
+ it('should have empty user query by default', () => {
+ const builder = new SearchHeaderQueryBuilderService(
+ buildConfig({}),
+ null,
+ null
+ );
+ expect(builder.userQuery).toBe('');
+ });
+
+ it('should add the extra filter for the parent node', () => {
+ const config: SearchConfiguration = {
+ categories: [
+ { id: 'cat1', enabled: true },
+ { id: 'cat2', enabled: true }
+ ],
+ filterQueries: [{ query: 'query1' }, { query: 'query2' }]
+ };
+
+ const expectedResult = [
+ { query: 'query1' },
+ { query: 'query2' },
+ { query: 'PARENT:"workspace://SpacesStore/fake-node-id"' }
+ ];
+
+ const searchHeaderService = new SearchHeaderQueryBuilderService(
+ buildConfig(config),
+ null,
+ null
+ );
+
+ searchHeaderService.setCurrentRootFolderId('fake-node-id', undefined);
+
+ expect(searchHeaderService.filterQueries).toEqual(expectedResult, 'Filters are not as expected');
+ });
+
+ it('should not add again the parent filter if that node is already added', () => {
+
+ const expectedResult = [
+ { query: 'query1' },
+ { query: 'query2' },
+ { query: 'PARENT:"workspace://SpacesStore/fake-node-id' }
+ ];
+
+ const config: SearchConfiguration = {
+ categories: [
+ { id: 'cat1', enabled: true },
+ { id: 'cat2', enabled: true }
+ ],
+ filterQueries: expectedResult
+ };
+
+ const searchHeaderService = new SearchHeaderQueryBuilderService(
+ buildConfig(config),
+ null,
+ null
+ );
+
+ searchHeaderService.setCurrentRootFolderId('fake-node-id', undefined);
+
+ expect(searchHeaderService.filterQueries).toEqual(
+ expectedResult,
+ 'Filters are not as expected'
+ );
+ });
+
+ it('should replace the new query filter for the old parent node with the new one', () => {
+ const expectedResult = [
+ { query: 'query1' },
+ { query: 'query2' },
+ { query: 'PARENT:"workspace://SpacesStore/fake-next-node-id"' }
+ ];
+
+ const config: SearchConfiguration = {
+ categories: [
+ { id: 'cat1', enabled: true },
+ { id: 'cat2', enabled: true }
+ ],
+ filterQueries: [
+ { query: 'query1' },
+ { query: 'query2' },
+ { query: 'PARENT:"workspace://SpacesStore/fake-node-id' }
+ ]
+ };
+
+ const searchHeaderService = new SearchHeaderQueryBuilderService(
+ buildConfig(config),
+ null,
+ null
+ );
+
+ searchHeaderService.setCurrentRootFolderId(
+ 'fake-next-node-id',
+ 'fake-node-id'
+ );
+
+ expect(searchHeaderService.filterQueries).toEqual(
+ expectedResult,
+ 'Filters are not as expected'
+ );
+ });
+});
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
new file mode 100644
index 0000000000..46e3bc5b54
--- /dev/null
+++ b/lib/content-services/src/lib/search/search-header-query-builder.service.ts
@@ -0,0 +1,116 @@
+/*!
+ * @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 { Injectable } from '@angular/core';
+import { AlfrescoApiService, AppConfigService, NodesApiService } from '@alfresco/adf-core';
+import { SearchConfiguration } from './search-configuration.interface';
+import { BaseQueryBuilderService } from './base-query-builder.service';
+import { SearchCategory } from './search-category.interface';
+import { MinimalNode } from '@alfresco/js-api';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class SearchHeaderQueryBuilderService extends BaseQueryBuilderService {
+
+ private customSources = ['-trashcan-', '-sharedlinks-', '-sites-', '-mysites-', '-favorites-', '-recent-', '-my-'];
+
+ activeFilters: string[] = [];
+ currentParentFolderID: string;
+
+ constructor(appConfig: AppConfigService, alfrescoApiService: AlfrescoApiService, private nodeApiService: NodesApiService) {
+ super(appConfig, alfrescoApiService);
+ }
+
+ public isFilterServiceActive(): boolean {
+ return true;
+ }
+
+ loadConfiguration(): SearchConfiguration {
+ return this.appConfig.get('search-headers');
+ }
+
+ setupCurrentPagination(maxItems: number, skipCount: number) {
+ if (!this.paging ||
+ (this.paging &&
+ this.paging.maxItems !== maxItems || this.paging.skipCount !== skipCount)) {
+ this.paging = { maxItems, skipCount };
+ this.execute();
+ }
+ }
+
+ setActiveFilter(columnActivated: string) {
+ this.activeFilters.push(columnActivated);
+ }
+
+ isNoFilterActive(): boolean {
+ return this.activeFilters.length === 0;
+ }
+
+ removeActiveFilter(columnRemoved: string) {
+ const removeIndex = this.activeFilters.findIndex((column) => column === columnRemoved);
+ this.activeFilters.splice(removeIndex, 1);
+ }
+
+ getCategoryForColumn(columnKey: string): SearchCategory {
+ let foundCategory = null;
+ if (this.categories !== null) {
+ foundCategory = this.categories.find(
+ category => category.columnKey === columnKey
+ );
+ }
+ return foundCategory;
+ }
+
+ setCurrentRootFolderId(currentFolderId: string, previousFolderId: string) {
+ if (this.customSources.includes(currentFolderId)) {
+ if (currentFolderId !== this.currentParentFolderID) {
+ this.nodeApiService.getNode(currentFolderId).subscribe((nodeEntity: MinimalNode) => {
+ this.updateCurrentParentFilter(nodeEntity.id, previousFolderId);
+ });
+ }
+ } else {
+ this.updateCurrentParentFilter(currentFolderId, previousFolderId);
+ }
+ }
+
+ private updateCurrentParentFilter(currentFolderId: string, previousFolderId: string) {
+ const alreadyAddedFilter = this.filterQueries.find(filterQueries =>
+ filterQueries.query.includes(currentFolderId)
+ );
+
+ if (!alreadyAddedFilter) {
+ this.removeOldFolderFiltering(previousFolderId, this.currentParentFolderID);
+ this.currentParentFolderID = currentFolderId;
+ this.filterQueries.push({
+ query: `PARENT:"workspace://SpacesStore/${currentFolderId}"`
+ });
+ }
+ }
+
+ private removeOldFolderFiltering(previousFolderId: string, actualSetFolderId: string) {
+ if (previousFolderId || actualSetFolderId) {
+ const folderIdToRetrieve = previousFolderId ? previousFolderId : actualSetFolderId;
+ const oldFilterIndex = this.filterQueries.findIndex(filterQueries =>
+ filterQueries.query.includes(folderIdToRetrieve)
+ );
+ if (oldFilterIndex) {
+ this.filterQueries.splice(oldFilterIndex, 1);
+ }
+ }
+ }
+}
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 ad63444bee..4c09fa064b 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
@@ -47,7 +47,7 @@ describe('SearchQueryBuilder', () => {
expect(builder.categories.length).toBe(0);
expect(builder.filterQueries.length).toBe(0);
- builder.resetToDefaults();
+ builder.setUpConfiguration();
expect(builder.categories.length).toBe(2);
expect(builder.filterQueries.length).toBe(2);
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 872847c66c..640cdc8176 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
@@ -16,417 +16,24 @@
*/
import { Injectable } from '@angular/core';
-import { Subject } from 'rxjs';
import { AlfrescoApiService, AppConfigService } from '@alfresco/adf-core';
-import {
- QueryBody,
- RequestFacetFields,
- RequestFacetField,
- RequestSortDefinitionInner,
- ResultSetPaging,
- RequestHighlight
-} 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 { BaseQueryBuilderService } from './base-query-builder.service';
@Injectable({
providedIn: 'root'
})
-export class SearchQueryBuilderService {
+export class SearchQueryBuilderService extends BaseQueryBuilderService {
- private _userQuery = '';
-
- updated = new Subject();
- executed = new Subject();
- error = new Subject();
-
- categories: Array = [];
- queryFragments: { [id: string]: string } = {};
- filterQueries: FilterQuery[] = [];
- paging: { maxItems?: number; skipCount?: number } = null;
- sorting: Array = [];
-
- protected userFacetBuckets: { [key: string]: Array } = {};
-
- get userQuery(): string {
- return this._userQuery;
- }
-
- set userQuery(value: string) {
- value = (value || '').trim();
- this._userQuery = value ? `(${value})` : '';
- }
-
- config: SearchConfiguration = {
- categories: []
- };
-
- // TODO: to be supported in future iterations
- ranges: { [id: string]: SearchRange } = {};
-
- constructor(private appConfig: AppConfigService, private alfrescoApiService: AlfrescoApiService) {
- this.resetToDefaults();
- }
-
- /**
- * Resets the query to the defaults specified in the app config.
- */
- resetToDefaults() {
- const template = this.appConfig.get('search');
- if (template) {
- this.config = JSON.parse(JSON.stringify(template));
- this.categories = (this.config.categories || []).filter((category) => category.enabled);
- this.filterQueries = this.config.filterQueries || [];
- this.userFacetBuckets = {};
- if (this.config.sorting) {
- this.sorting = this.config.sorting.defaults || [];
- }
- }
- }
-
- /**
- * Adds a facet bucket to a field.
- * @param field The target field
- * @param bucket Bucket to add
- */
- addUserFacetBucket(field: FacetField, bucket: FacetFieldBucket) {
- if (field && field.field && bucket) {
- const buckets = this.userFacetBuckets[field.field] || [];
- const existing = buckets.find((facetBucket) => facetBucket.label === bucket.label);
- if (!existing) {
- buckets.push(bucket);
- }
- this.userFacetBuckets[field.field] = buckets;
- }
- }
-
- /**
- * Gets the buckets currently added to a field
- * @param field The target fields
- * @returns Bucket array
- */
- getUserFacetBuckets(field: string) {
- return this.userFacetBuckets[field] || [];
- }
-
- /**
- * Removes an existing bucket from a field.
- * @param field The target field
- * @param bucket Bucket to remove
- */
- removeUserFacetBucket(field: FacetField, bucket: FacetFieldBucket) {
- if (field && field.field && bucket) {
- const buckets = this.userFacetBuckets[field.field] || [];
- this.userFacetBuckets[field.field] = buckets
- .filter((facetBucket) => facetBucket.label !== bucket.label);
- }
- }
-
- /**
- * Adds a filter query to the current query.
- * @param query Query string to add
- */
- addFilterQuery(query: string): void {
- if (query) {
- const existing = this.filterQueries.find((filterQuery) => filterQuery.query === query);
- if (!existing) {
- this.filterQueries.push({ query: query });
- }
- }
- }
-
- /**
- * Removes an existing filter query.
- * @param query The query to remove
- */
- removeFilterQuery(query: string): void {
- if (query) {
- this.filterQueries = this.filterQueries
- .filter((filterQuery) => filterQuery.query !== query);
- }
- }
-
- /**
- * Gets a facet query by label.
- * @param label Label of the query
- * @returns Facet query data
- */
- getFacetQuery(label: string): FacetQuery {
- if (label && this.hasFacetQueries) {
- const result = this.config.facetQueries.queries.find((query) => query.label === label);
- if (result) {
- return { ...result };
- }
- }
- return null;
- }
-
- /**
- * Gets a facet field by label.
- * @param label Label of the facet field
- * @returns Facet field data
- */
- getFacetField(label: string): FacetField {
- if (label) {
- const fields = this.config.facetFields.fields || [];
- const result = fields.find((field) => field.label === label);
- if (result) {
- result.label = this.getSupportedLabel(result.label);
- return { ...result };
- }
- }
- return null;
- }
-
- /**
- * Builds the current query and triggers the `updated` event.
- */
- update(): void {
- const query = this.buildQuery();
- this.updated.next(query);
- }
-
- /**
- * Builds and executes the current query.
- * @returns Nothing
- */
- async execute() {
- try {
- const query = this.buildQuery();
- if (query) {
- const resultSetPaging: ResultSetPaging = await this.alfrescoApiService.searchApi.search(query);
- this.executed.next(resultSetPaging);
- }
- } catch (error) {
- this.error.next(error);
-
- this.executed.next({
- list: {
- pagination: {
- totalItems: 0
- },
- entries: []
- }
- });
- }
- }
-
- /**
- * Builds the current query.
- * @returns The finished query
- */
- buildQuery(): QueryBody {
- const query = this.getFinalQuery();
-
- const include = this.config.include || [];
- if (include.length === 0) {
- include.push('path', 'allowableOperations');
- }
-
- if (query) {
- const result: QueryBody = {
- query: {
- query: query,
- language: 'afts'
- },
- include: include,
- paging: this.paging,
- fields: this.config.fields,
- filterQueries: this.filterQueries,
- facetQueries: this.facetQueries,
- facetIntervals: this.facetIntervals,
- facetFields: this.facetFields,
- sort: this.sort,
- highlight: this.highlight
- };
-
- result['facetFormat'] = 'V2';
- return result;
- }
-
- return null;
- }
-
- /**
- * Gets the primary sorting definition.
- * @returns The primary sorting definition
- */
- getPrimarySorting(): SearchSortingDefinition {
- if (this.sorting && this.sorting.length > 0) {
- return this.sorting[0];
- }
- return null;
- }
-
- /**
- * Gets all pre-configured sorting options that users can choose from.
- * @returns Pre-configured sorting options
- */
- getSortingOptions(): SearchSortingDefinition[] {
- if (this.config && this.config.sorting) {
- return this.config.sorting.options || [];
- }
- return [];
- }
-
- /**
- * Gets the query group.
- * @param query Target query
- * @returns Query group
- */
- getQueryGroup(query) {
- return query.group || this.config.facetQueries.label || 'Facet Queries';
- }
-
- /**
- * Checks if FacetQueries has been defined
- * @returns True if defined, false otherwise
- */
- get hasFacetQueries(): boolean {
- if (this.config
- && this.config.facetQueries
- && this.config.facetQueries.queries
- && this.config.facetQueries.queries.length > 0) {
- return true;
- }
+ public isFilterServiceActive(): boolean {
return false;
}
- /**
- * Checks if FacetIntervals has been defined
- * @returns True if defined, false otherwise
- */
- get hasFacetIntervals(): boolean {
- if (this.config
- && this.config.facetIntervals
- && this.config.facetIntervals.intervals
- && this.config.facetIntervals.intervals.length > 0) {
- return true;
- }
- return false;
+ constructor(appConfig: AppConfigService, alfrescoApiService: AlfrescoApiService) {
+ super(appConfig, alfrescoApiService);
}
- get hasFacetHighlight(): boolean {
- return this.config && this.config.highlight ? true : false;
- }
-
- protected get sort(): RequestSortDefinitionInner[] {
- return this.sorting.map((def) => {
- return new RequestSortDefinitionInner({
- type: def.type,
- field: def.field,
- ascending: def.ascending
- });
- });
- }
-
- protected get facetQueries(): FacetQuery[] {
- if (this.hasFacetQueries) {
- return this.config.facetQueries.queries.map((query) => {
- query.group = this.getQueryGroup(query);
- return { ...query };
- });
- }
-
- return null;
- }
-
- protected get facetIntervals(): any {
- if (this.hasFacetIntervals) {
- const configIntervals = this.config.facetIntervals;
-
- return {
- intervals: configIntervals.intervals.map((interval) => {
- label: this.getSupportedLabel(interval.label),
- field: interval.field,
- sets: interval.sets.map((set) => {
- label: this.getSupportedLabel(set.label),
- start: set.start,
- end: set.end,
- startInclusive: set.startInclusive,
- endInclusive: set.endInclusive
- })
- })
- };
- }
-
- return null;
- }
-
- protected get highlight(): RequestHighlight {
- return this.hasFacetHighlight ? this.config.highlight : null;
- }
-
- protected getFinalQuery(): string {
- let query = '';
-
- this.categories.forEach((facet) => {
- const customQuery = this.queryFragments[facet.id];
- if (customQuery) {
- if (query.length > 0) {
- query += ' AND ';
- }
- query += `(${customQuery})`;
- }
- });
-
- let result = [this.userQuery, query]
- .filter((entry) => entry)
- .join(' AND ');
-
- if (this.userFacetBuckets) {
- Object.keys(this.userFacetBuckets).forEach((key) => {
- const subQuery = (this.userFacetBuckets[key] || [])
- .filter((bucket) => bucket.filterQuery)
- .map((bucket) => bucket.filterQuery)
- .join(' OR ');
- if (subQuery) {
- if (result.length > 0) {
- result += ' AND ';
- }
- result += `(${subQuery})`;
- }
- });
- }
-
- return result;
- }
-
- protected get facetFields(): RequestFacetFields {
- const facetFields = this.config.facetFields && this.config.facetFields.fields;
-
- if (facetFields && facetFields.length > 0) {
- return {
- facets: facetFields.map((facet) => {
- field: facet.field,
- mincount: facet.mincount,
- label: this.getSupportedLabel(facet.label),
- limit: facet.limit,
- offset: facet.offset,
- prefix: facet.prefix
- })
- };
- }
-
- return null;
- }
-
- /**
- * Encloses a label name with double quotes if it contains whitespace characters.
- * @param configLabel Original label text
- * @returns Label, possibly with quotes if it contains spaces
- */
- getSupportedLabel(configLabel: string): string {
- const spaceInsideLabelIndex = configLabel.search(/\s/g);
- if (spaceInsideLabelIndex > -1) {
- return `"${configLabel}"`;
- }
- return configLabel;
+ public loadConfiguration(): SearchConfiguration {
+ return this.appConfig.get('search');
}
}
diff --git a/lib/content-services/src/lib/search/search-query-service.token.ts b/lib/content-services/src/lib/search/search-query-service.token.ts
new file mode 100644
index 0000000000..13a2584d81
--- /dev/null
+++ b/lib/content-services/src/lib/search/search-query-service.token.ts
@@ -0,0 +1,21 @@
+/*!
+ * @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 { InjectionToken } from '@angular/core';
+import { BaseQueryBuilderService } from './base-query-builder.service';
+
+export const SEARCH_QUERY_SERVICE_TOKEN = new InjectionToken('QueryService');
diff --git a/lib/content-services/src/lib/search/search-widget.interface.ts b/lib/content-services/src/lib/search/search-widget.interface.ts
index 4415d979ca..883a4249e1 100644
--- a/lib/content-services/src/lib/search/search-widget.interface.ts
+++ b/lib/content-services/src/lib/search/search-widget.interface.ts
@@ -22,4 +22,5 @@ export interface SearchWidget {
id: string;
settings?: SearchWidgetSettings;
context?: SearchQueryBuilderService;
+ reset();
}
diff --git a/lib/content-services/src/lib/search/search.module.ts b/lib/content-services/src/lib/search/search.module.ts
index 8bb1c18413..b7044cda3d 100644
--- a/lib/content-services/src/lib/search/search.module.ts
+++ b/lib/content-services/src/lib/search/search.module.ts
@@ -35,6 +35,9 @@ import { SearchNumberRangeComponent } from './components/search-number-range/sea
import { SearchCheckListComponent } from './components/search-check-list/search-check-list.component';
import { SearchDateRangeComponent } from './components/search-date-range/search-date-range.component';
import { SearchSortingPickerComponent } from './components/search-sorting-picker/search-sorting-picker.component';
+import { SearchHeaderComponent } from './components/search-header/search-header.component';
+import { SEARCH_QUERY_SERVICE_TOKEN } from './search-query-service.token';
+import { SearchQueryBuilderService } from './search-query-builder.service';
@NgModule({
imports: [
@@ -57,7 +60,8 @@ import { SearchSortingPickerComponent } from './components/search-sorting-picker
SearchNumberRangeComponent,
SearchCheckListComponent,
SearchDateRangeComponent,
- SearchSortingPickerComponent
+ SearchSortingPickerComponent,
+ SearchHeaderComponent
],
exports: [
SearchComponent,
@@ -72,7 +76,8 @@ import { SearchSortingPickerComponent } from './components/search-sorting-picker
SearchNumberRangeComponent,
SearchCheckListComponent,
SearchDateRangeComponent,
- SearchSortingPickerComponent
+ SearchSortingPickerComponent,
+ SearchHeaderComponent
],
entryComponents: [
SearchWidgetContainerComponent,
@@ -82,6 +87,9 @@ import { SearchSortingPickerComponent } from './components/search-sorting-picker
SearchNumberRangeComponent,
SearchCheckListComponent,
SearchDateRangeComponent
+ ],
+ providers: [
+ { provide: SEARCH_QUERY_SERVICE_TOKEN, useClass: SearchQueryBuilderService }
]
})
export class SearchModule {}
diff --git a/lib/content-services/src/lib/styles/_index.scss b/lib/content-services/src/lib/styles/_index.scss
index 907b4c534c..072808b855 100644
--- a/lib/content-services/src/lib/styles/_index.scss
+++ b/lib/content-services/src/lib/styles/_index.scss
@@ -13,6 +13,7 @@
@import '../search/components/search-sorting-picker/search-sorting-picker.component';
@import '../search/components/search-filter/search-filter.component';
@import '../search/components/search-chip-list/search-chip-list.component';
+@import '../search/components/search-header/search-header.component';
@import '../dialogs/folder.dialog';
@@ -39,6 +40,7 @@
@include adf-search-control-theme($theme);
@include adf-search-autocomplete-theme($theme);
@include adf-search-sorting-picker-theme($theme);
+ @include adf-filter-menu-theme($theme);
@include adf-dialog-theme($theme);
@include adf-content-node-selector-dialog-theme($theme);
@include adf-content-metadata-module-theme($theme);
diff --git a/lib/core/datatable/components/datatable/datatable.component.html b/lib/core/datatable/components/datatable/datatable.component.html
index e99cbb91b9..89bcb7836f 100644
--- a/lib/core/datatable/components/datatable/datatable.component.html
+++ b/lib/core/datatable/components/datatable/datatable.component.html
@@ -4,11 +4,12 @@
[class.adf-datatable-card]="display === 'gallery'"
[class.adf-datatable-list]="display === 'list'"
[class.adf-sticky-header]="isStickyHeaderEnabled()"
- [class.adf-datatable--empty]="!isHeaderVisible()">
-