mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
[ACA-3507] [ACA-3523] Fix Filters (#5821)
* fix search one letter fix navigation add new property search text prefix and suffix * fix unit test * fix unit test * fix failing test
This commit is contained in:
parent
0183f9e7f7
commit
5180493aa8
@ -459,7 +459,8 @@
|
||||
"settings": {
|
||||
"pattern": "cm:name:'(.*?)'",
|
||||
"field": "cm:name",
|
||||
"placeholder": "Enter the name"
|
||||
"placeholder": "Enter the name",
|
||||
"searchSuffix" : "*"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -25,6 +25,8 @@ Implements a text input [widget](../../../lib/testing/src/lib/core/pages/form/wi
|
||||
"component": {
|
||||
"selector": "text",
|
||||
"settings": {
|
||||
"searchPrefix": "",
|
||||
"searchSuffix": "",
|
||||
"pattern": "cm:name:'(.*?)'",
|
||||
"field": "cm:name",
|
||||
"placeholder": "Enter the name"
|
||||
@ -43,6 +45,8 @@ Implements a text input [widget](../../../lib/testing/src/lib/core/pages/form/wi
|
||||
| field | string | Field to apply the query fragment to. Required value |
|
||||
| pattern | string | Regular expression pattern to restrict the format of the input text |
|
||||
| placeholder | string | Text displayed in the [widget](../../../lib/testing/src/lib/core/pages/form/widgets/widget.ts) when the input string is empty |
|
||||
| searchSuffix | string | Text to append always in the search of a string|
|
||||
| searchPrefix | string | Text to prepend always in the search of a string|
|
||||
|
||||
## Details
|
||||
|
||||
|
@ -43,6 +43,7 @@ export class SearchCheckListComponent implements SearchWidget, OnInit {
|
||||
options: SearchFilterList<SearchListOption>;
|
||||
operator: string = 'OR';
|
||||
pageSize = 5;
|
||||
isActive = false;
|
||||
|
||||
constructor() {
|
||||
this.options = new SearchFilterList<SearchListOption>();
|
||||
@ -60,6 +61,7 @@ export class SearchCheckListComponent implements SearchWidget, OnInit {
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.isActive = false;
|
||||
this.options.items.forEach((opt) => {
|
||||
opt.checked = false;
|
||||
});
|
||||
@ -80,6 +82,8 @@ export class SearchCheckListComponent implements SearchWidget, OnInit {
|
||||
.filter((option) => option.checked)
|
||||
.map((option) => option.value);
|
||||
|
||||
this.isActive = !!checkedValues.length;
|
||||
|
||||
const query = checkedValues.join(` ${this.operator} `);
|
||||
|
||||
if (this.id && this.context) {
|
||||
|
@ -56,6 +56,8 @@ export class SearchDateRangeComponent implements SearchWidget, OnInit, OnDestroy
|
||||
context?: SearchQueryBuilderService;
|
||||
datePickerDateFormat = DEFAULT_FORMAT_DATE;
|
||||
maxDate: any;
|
||||
isActive = false;
|
||||
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(private dateAdapter: DateAdapter<Moment>,
|
||||
@ -117,6 +119,8 @@ export class SearchDateRangeComponent implements SearchWidget, OnInit, OnDestroy
|
||||
|
||||
apply(model: { from: string, to: string }, isValid: boolean) {
|
||||
if (isValid && this.id && this.context && this.settings && this.settings.field) {
|
||||
this.isActive = true;
|
||||
|
||||
const start = moment(model.from).startOf('day').format();
|
||||
const end = moment(model.to).endOf('day').format();
|
||||
|
||||
@ -130,6 +134,7 @@ export class SearchDateRangeComponent implements SearchWidget, OnInit, OnDestroy
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.isActive = false;
|
||||
this.form.reset({
|
||||
from: '',
|
||||
to: ''
|
||||
|
@ -7,10 +7,10 @@
|
||||
class="adf-filter-button"
|
||||
[matTooltip]="getTooltipTranslation(col?.title)">
|
||||
<adf-icon value="adf:filter"
|
||||
[ngClass]="{ 'adf-icon-active': isActive || menuTrigger.menuOpen }"
|
||||
[ngClass]="{ 'adf-icon-active': isActive()|| menuTrigger.menuOpen }"
|
||||
matBadge="filter"
|
||||
matBadgeColor="warn"
|
||||
[matBadgeHidden]="!isActive"></adf-icon>
|
||||
[matBadgeHidden]="!isActive()"></adf-icon>
|
||||
</button>
|
||||
|
||||
<mat-menu #filter="matMenu" class="adf-filter-menu">
|
||||
|
@ -95,6 +95,7 @@ describe('SearchHeaderComponent', () => {
|
||||
menuButton.click();
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
component.widgetContainer.componentRef.instance.value = 'searchText';
|
||||
const applyButton = fixture.debugElement.query(By.css('#apply-filter-button'));
|
||||
applyButton.triggerEventHandler('click', {});
|
||||
fixture.detectChanges();
|
||||
|
@ -15,7 +15,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, Input, Output, OnInit, OnChanges, EventEmitter, SimpleChanges, ViewEncapsulation, ViewChild, Inject, OnDestroy } from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
Input,
|
||||
Output,
|
||||
OnInit,
|
||||
OnChanges,
|
||||
EventEmitter,
|
||||
SimpleChanges,
|
||||
ViewEncapsulation,
|
||||
ViewChild,
|
||||
Inject,
|
||||
OnDestroy
|
||||
} from '@angular/core';
|
||||
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';
|
||||
@ -60,8 +72,6 @@ export class SearchHeaderComponent implements OnInit, OnChanges, OnDestroy {
|
||||
@ViewChild(SearchWidgetContainerComponent)
|
||||
widgetContainer: SearchWidgetContainerComponent;
|
||||
|
||||
public isActive: boolean;
|
||||
|
||||
category: SearchCategory;
|
||||
isFilterServiceActive: boolean;
|
||||
|
||||
@ -85,15 +95,9 @@ export class SearchHeaderComponent implements OnInit, OnChanges, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (changes['currentFolderNodeId'] && changes['currentFolderNodeId'].currentValue) {
|
||||
const currentIdValue = changes['currentFolderNodeId'].currentValue;
|
||||
const previousIdValue = changes['currentFolderNodeId'].previousValue;
|
||||
this.searchHeaderQueryBuilder.setCurrentRootFolderId(
|
||||
currentIdValue,
|
||||
previousIdValue
|
||||
);
|
||||
|
||||
this.isActive = false;
|
||||
if (changes['currentFolderNodeId'] && changes['currentFolderNodeId'].currentValue !== changes['currentFolderNodeId'].previousValue) {
|
||||
this.searchHeaderQueryBuilder.setCurrentRootFolderId(changes['currentFolderNodeId'].currentValue);
|
||||
this.clearHeader();
|
||||
}
|
||||
|
||||
if (changes['maxItems'] || changes['skipCount']) {
|
||||
@ -125,7 +129,12 @@ export class SearchHeaderComponent implements OnInit, OnChanges, OnDestroy {
|
||||
}
|
||||
|
||||
onApplyButtonClick() {
|
||||
this.isActive = true;
|
||||
// TODO Move this piece of code in the search text widget
|
||||
if (this.widgetContainer.selector === 'text' && this.widgetContainer.componentRef.instance.value === '') {
|
||||
this.clearHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
this.widgetContainer.applyInnerWidget();
|
||||
this.searchHeaderQueryBuilder.setActiveFilter(this.category.columnKey);
|
||||
this.searchHeaderQueryBuilder.execute();
|
||||
@ -133,13 +142,14 @@ export class SearchHeaderComponent implements OnInit, OnChanges, OnDestroy {
|
||||
|
||||
onClearButtonClick(event: Event) {
|
||||
event.stopPropagation();
|
||||
this.clearHeader();
|
||||
}
|
||||
|
||||
clearHeader() {
|
||||
if (this.widgetContainer) {
|
||||
this.widgetContainer.resetInnerWidget();
|
||||
this.isActive = false;
|
||||
this.searchHeaderQueryBuilder.removeActiveFilter(this.category.columnKey);
|
||||
if (this.searchHeaderQueryBuilder.isNoFilterActive()) {
|
||||
this.clear.emit();
|
||||
} else {
|
||||
this.searchHeaderQueryBuilder.execute();
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,6 +157,10 @@ export class SearchHeaderComponent implements OnInit, OnChanges, OnDestroy {
|
||||
if (!columnTitle) {
|
||||
columnTitle = 'SEARCH.SEARCH_HEADER.TYPE';
|
||||
}
|
||||
return this.translationService.instant('SEARCH.SEARCH_HEADER.FILTER_BY', {category: this.translationService.instant(columnTitle)});
|
||||
return this.translationService.instant('SEARCH.SEARCH_HEADER.FILTER_BY', { category: this.translationService.instant(columnTitle) });
|
||||
}
|
||||
|
||||
isActive(): boolean {
|
||||
return this.widgetContainer && this.widgetContainer.componentRef && this.widgetContainer.componentRef.instance.isActive;
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,8 @@ export class SearchNumberRangeComponent implements SearchWidget, OnInit {
|
||||
field: string;
|
||||
format = '[{FROM} TO {TO}]';
|
||||
|
||||
isActive = false;
|
||||
|
||||
validators: Validators;
|
||||
|
||||
ngOnInit(): void {
|
||||
@ -74,6 +76,8 @@ export class SearchNumberRangeComponent implements SearchWidget, OnInit {
|
||||
|
||||
apply(model: { from: string, to: string }, isValid: boolean) {
|
||||
if (isValid && this.id && this.context && this.field) {
|
||||
this.isActive = true;
|
||||
|
||||
const map = new Map<string, string>();
|
||||
map.set('FROM', model.from);
|
||||
map.set('TO', model.to);
|
||||
@ -97,6 +101,8 @@ export class SearchNumberRangeComponent implements SearchWidget, OnInit {
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.isActive = false;
|
||||
|
||||
this.form.reset({
|
||||
from: '',
|
||||
to: ''
|
||||
|
@ -46,6 +46,7 @@ export class SearchRadioComponent implements SearchWidget, OnInit {
|
||||
context: SearchQueryBuilderService;
|
||||
options: SearchFilterList<SearchRadioOption>;
|
||||
pageSize = 5;
|
||||
isActive = false;
|
||||
|
||||
constructor() {
|
||||
this.options = new SearchFilterList<SearchRadioOption>();
|
||||
@ -71,6 +72,8 @@ export class SearchRadioComponent implements SearchWidget, OnInit {
|
||||
private getSelectedValue(): string {
|
||||
const options: any[] = this.settings['options'] || [];
|
||||
if (options && options.length > 0) {
|
||||
this.isActive = true;
|
||||
|
||||
let selected = options.find((opt) => opt.default);
|
||||
if (!selected) {
|
||||
selected = options[0];
|
||||
@ -91,6 +94,8 @@ export class SearchRadioComponent implements SearchWidget, OnInit {
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.isActive = false;
|
||||
|
||||
const initialValue = this.getSelectedValue();
|
||||
if (initialValue !== null) {
|
||||
this.setValue(initialValue);
|
||||
|
@ -36,6 +36,7 @@ export class SearchTextComponent implements SearchWidget, OnInit {
|
||||
id: string;
|
||||
settings: SearchWidgetSettings;
|
||||
context: SearchQueryBuilderService;
|
||||
isActive = false;
|
||||
|
||||
ngOnInit() {
|
||||
if (this.context && this.settings && this.settings.pattern) {
|
||||
@ -49,6 +50,8 @@ export class SearchTextComponent implements SearchWidget, OnInit {
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.isActive = false;
|
||||
|
||||
this.value = '';
|
||||
this.updateQuery(null);
|
||||
}
|
||||
@ -59,10 +62,21 @@ export class SearchTextComponent implements SearchWidget, OnInit {
|
||||
}
|
||||
|
||||
private updateQuery(value: string) {
|
||||
this.isActive = !!value;
|
||||
|
||||
if (this.context && this.settings && this.settings.field) {
|
||||
this.context.queryFragments[this.id] = value ? `${this.settings.field}:'${value}'` : '';
|
||||
this.context.queryFragments[this.id] = value ? `${this.settings.field}:'${this.getSearchPrefix()}${value}${this.getSearchSuffix()}'` : '';
|
||||
this.context.update();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private getSearchPrefix(): string {
|
||||
return this.settings.searchPrefix ? this.settings.searchPrefix : '';
|
||||
}
|
||||
|
||||
private getSearchSuffix(): string {
|
||||
return this.settings.searchSuffix ? this.settings.searchSuffix : '';
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ export class SearchWidgetContainerComponent implements OnInit, OnDestroy {
|
||||
@Input()
|
||||
config: any;
|
||||
|
||||
private componentRef: ComponentRef<any>;
|
||||
componentRef: ComponentRef<any>;
|
||||
|
||||
constructor(
|
||||
private searchFilterService: SearchFilterService,
|
||||
|
@ -94,8 +94,6 @@ describe('SearchHeaderQueryBuilder', () => {
|
||||
};
|
||||
|
||||
const expectedResult = [
|
||||
{ query: 'query1' },
|
||||
{ query: 'query2' },
|
||||
{ query: 'PARENT:"workspace://SpacesStore/fake-node-id"' }
|
||||
];
|
||||
|
||||
@ -105,7 +103,7 @@ describe('SearchHeaderQueryBuilder', () => {
|
||||
null
|
||||
);
|
||||
|
||||
searchHeaderService.setCurrentRootFolderId('fake-node-id', undefined);
|
||||
searchHeaderService.setCurrentRootFolderId('fake-node-id');
|
||||
|
||||
expect(searchHeaderService.filterQueries).toEqual(expectedResult, 'Filters are not as expected');
|
||||
});
|
||||
@ -113,9 +111,7 @@ describe('SearchHeaderQueryBuilder', () => {
|
||||
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' }
|
||||
{ query: 'PARENT:"workspace://SpacesStore/fake-node-id"' }
|
||||
];
|
||||
|
||||
const config: SearchConfiguration = {
|
||||
@ -132,7 +128,7 @@ describe('SearchHeaderQueryBuilder', () => {
|
||||
null
|
||||
);
|
||||
|
||||
searchHeaderService.setCurrentRootFolderId('fake-node-id', undefined);
|
||||
searchHeaderService.setCurrentRootFolderId('fake-node-id');
|
||||
|
||||
expect(searchHeaderService.filterQueries).toEqual(
|
||||
expectedResult,
|
||||
@ -142,8 +138,6 @@ describe('SearchHeaderQueryBuilder', () => {
|
||||
|
||||
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"' }
|
||||
];
|
||||
|
||||
@ -153,8 +147,6 @@ describe('SearchHeaderQueryBuilder', () => {
|
||||
<any> { id: 'cat2', enabled: true }
|
||||
],
|
||||
filterQueries: [
|
||||
{ query: 'query1' },
|
||||
{ query: 'query2' },
|
||||
{ query: 'PARENT:"workspace://SpacesStore/fake-node-id' }
|
||||
]
|
||||
};
|
||||
@ -165,9 +157,10 @@ describe('SearchHeaderQueryBuilder', () => {
|
||||
null
|
||||
);
|
||||
|
||||
searchHeaderService.currentParentFolderId = 'fake-node-id';
|
||||
|
||||
searchHeaderService.setCurrentRootFolderId(
|
||||
'fake-next-node-id',
|
||||
'fake-node-id'
|
||||
'fake-next-node-id'
|
||||
);
|
||||
|
||||
expect(searchHeaderService.filterQueries).toEqual(
|
||||
|
@ -30,7 +30,7 @@ export class SearchHeaderQueryBuilderService extends BaseQueryBuilderService {
|
||||
private customSources = ['-trashcan-', '-sharedlinks-', '-sites-', '-mysites-', '-favorites-', '-recent-', '-my-'];
|
||||
|
||||
activeFilters: string[] = [];
|
||||
currentParentFolderID: string;
|
||||
currentParentFolderId: string;
|
||||
|
||||
constructor(appConfig: AppConfigService, alfrescoApiService: AlfrescoApiService, private nodeApiService: NodesApiService) {
|
||||
super(appConfig, alfrescoApiService);
|
||||
@ -78,41 +78,31 @@ export class SearchHeaderQueryBuilderService extends BaseQueryBuilderService {
|
||||
return foundCategory;
|
||||
}
|
||||
|
||||
setCurrentRootFolderId(currentFolderId: string, previousFolderId: string) {
|
||||
setCurrentRootFolderId(currentFolderId: string) {
|
||||
if (currentFolderId !== this.currentParentFolderId) {
|
||||
if (this.customSources.includes(currentFolderId)) {
|
||||
if (currentFolderId !== this.currentParentFolderID) {
|
||||
this.nodeApiService.getNode(currentFolderId).subscribe((nodeEntity: MinimalNode) => {
|
||||
this.updateCurrentParentFilter(nodeEntity.id, previousFolderId);
|
||||
this.updateCurrentParentFilter(nodeEntity.id);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.updateCurrentParentFilter(currentFolderId, previousFolderId);
|
||||
this.currentParentFolderId = currentFolderId;
|
||||
this.updateCurrentParentFilter(currentFolderId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private updateCurrentParentFilter(currentFolderId: string, previousFolderId: string) {
|
||||
private updateCurrentParentFilter(currentFolderId: 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}"`
|
||||
});
|
||||
}
|
||||
if (alreadyAddedFilter !== undefined) {
|
||||
this.filterQueries = [];
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
this.filterQueries = [{
|
||||
query: `PARENT:"workspace://SpacesStore/${currentFolderId}"`
|
||||
}];
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,5 +22,6 @@ export interface SearchWidget {
|
||||
id: string;
|
||||
settings?: SearchWidgetSettings;
|
||||
context?: SearchQueryBuilderService;
|
||||
isActive?: boolean;
|
||||
reset();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user