mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-07-24 17:31:52 +00:00
[ADF-5419][aca] support multiple search form (#2173)
* [ADF-5419][aca] support multiple search form * * revert app config and tests added * * removed unused key * * resolved conflicts and upgrade adf * * fix e2e * * update defalut name
This commit is contained in:
@@ -150,13 +150,13 @@ describe('Empty list views', () => {
|
||||
expect(await pagination.isNextButtonPresent()).toBe(false, 'Next button is present');
|
||||
});
|
||||
|
||||
it('[C279189] Search filters panel is not displayed on empty Search Results page', async () => {
|
||||
it('[C279189] Search filters panel is displayed on empty Search Results page', async () => {
|
||||
await searchInput.clickSearchButton();
|
||||
/* cspell:disable-next-line */
|
||||
await searchInput.searchFor('qwertyuiop');
|
||||
await dataTable.waitForBody();
|
||||
|
||||
expect(await searchResultsPage.filters.isSearchFiltersPanelDisplayed()).toBe(false, 'Search filters panel is present');
|
||||
expect(await searchResultsPage.filters.isSearchFiltersPanelDisplayed()).toBe(true, 'Search filters panel is not present');
|
||||
});
|
||||
|
||||
it('[C290020] Empty Search results - Libraries', async () => {
|
||||
|
@@ -189,7 +189,7 @@
|
||||
"multi-value-pipe-separator": ", ",
|
||||
"multi-value-chips": true
|
||||
},
|
||||
"search": {
|
||||
"search": [{
|
||||
"filterWithContains": true,
|
||||
"aca:fields": ["cm:name", "cm:title", "cm:description", "TEXT", "TAG"],
|
||||
"include": ["path", "allowableOperations", "properties"],
|
||||
@@ -372,8 +372,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
"name": "APP.BROWSE.SEARCH.DEFAULT_SEARCH",
|
||||
"default": true
|
||||
}],
|
||||
"search-headers": {
|
||||
"filterWithContains": true,
|
||||
"app:fields": [
|
||||
|
@@ -15,7 +15,7 @@
|
||||
#searchFilter
|
||||
[ngClass]="{
|
||||
'adf-search-filter--hidden':
|
||||
hideSearchFilter() || !(showFacetFilter$ | async)
|
||||
!(showFacetFilter$ | async)
|
||||
}"
|
||||
></adf-search-filter>
|
||||
<div class="adf-search-results__content">
|
||||
@@ -25,10 +25,8 @@
|
||||
mode="indeterminate"
|
||||
>
|
||||
</mat-progress-bar>
|
||||
<div
|
||||
class="adf-search-results__content-header content"
|
||||
*ngIf="data?.list.entries.length"
|
||||
>
|
||||
<div class="adf-search-results__content-header content">
|
||||
<adf-search-form (formChange)="onFormChange($event)"></adf-search-form>
|
||||
<div class="content__side--left">
|
||||
<div
|
||||
class="adf-search-results--info-text"
|
||||
|
@@ -81,6 +81,8 @@
|
||||
&__side--left {
|
||||
@include flex-column;
|
||||
height: unset;
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -23,17 +23,18 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
|
||||
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
import { SearchResultsComponent } from './search-results.component';
|
||||
import { AppTestingModule } from '../../../testing/app-testing.module';
|
||||
import { AppSearchResultsModule } from '../search-results.module';
|
||||
import { CoreModule, AppConfigService, AlfrescoApiService, TranslationService } from '@alfresco/adf-core';
|
||||
import { AlfrescoApiService, AppConfigService, CoreModule, TranslationService } from '@alfresco/adf-core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { NavigateToFolder, SnackbarErrorAction } from '@alfresco/aca-shared/store';
|
||||
import { Pagination, SearchRequest } from '@alfresco/js-api';
|
||||
import { SearchQueryBuilderService } from '@alfresco/adf-content-services';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
describe('SearchComponent', () => {
|
||||
let component: SearchResultsComponent;
|
||||
@@ -45,8 +46,10 @@ describe('SearchComponent', () => {
|
||||
let translate: TranslationService;
|
||||
let router: Router;
|
||||
const searchRequest = {} as SearchRequest;
|
||||
let params: BehaviorSubject<any>;
|
||||
|
||||
beforeEach(() => {
|
||||
params = new BehaviorSubject({ q: 'TYPE: "cm:folder" AND %28=cm: name: email OR cm: name: budget%29' });
|
||||
TestBed.configureTestingModule({
|
||||
imports: [TranslateModule.forRoot(), CoreModule.forRoot(), AppTestingModule, AppSearchResultsModule],
|
||||
providers: [
|
||||
@@ -58,11 +61,7 @@ describe('SearchComponent', () => {
|
||||
sortingPreferenceKey: ''
|
||||
}
|
||||
},
|
||||
params: [
|
||||
{
|
||||
q: 'TYPE: "cm:folder" AND %28=cm: name: email OR cm: name: budget%29'
|
||||
}
|
||||
]
|
||||
params: params.asObservable()
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -75,6 +74,10 @@ describe('SearchComponent', () => {
|
||||
translate = TestBed.inject(TranslationService);
|
||||
router = TestBed.inject(Router);
|
||||
|
||||
config.config = {
|
||||
search: {}
|
||||
};
|
||||
|
||||
fixture = TestBed.createComponent(SearchResultsComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
@@ -83,6 +86,10 @@ describe('SearchComponent', () => {
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
params.complete();
|
||||
});
|
||||
|
||||
it('should raise an error if search fails', fakeAsync(() => {
|
||||
spyOn(alfrescoApi.searchApi, 'search').and.returnValue(
|
||||
Promise.reject({
|
||||
@@ -165,47 +172,23 @@ describe('SearchComponent', () => {
|
||||
});
|
||||
|
||||
it('should format user input according to the configuration fields', () => {
|
||||
config.config = {
|
||||
search: {
|
||||
'aca:fields': ['cm:name', 'cm:title']
|
||||
}
|
||||
};
|
||||
|
||||
const query = component.formatSearchQuery('hello');
|
||||
const query = component.formatSearchQuery('hello', ['cm:name', 'cm:title']);
|
||||
expect(query).toBe(`(cm:name:"hello*" OR cm:title:"hello*")`);
|
||||
});
|
||||
|
||||
it('should format user input as cm:name if configuration not provided', () => {
|
||||
config.config = {
|
||||
search: {
|
||||
'aca:fields': undefined
|
||||
}
|
||||
};
|
||||
|
||||
const query = component.formatSearchQuery('hello');
|
||||
const query = component.formatSearchQuery('hello', undefined);
|
||||
expect(query).toBe(`(cm:name:"hello*")`);
|
||||
});
|
||||
|
||||
it('should use AND operator when conjunction has no operators', () => {
|
||||
config.config = {
|
||||
search: {
|
||||
'aca:fields': ['cm:name']
|
||||
}
|
||||
};
|
||||
|
||||
const query = component.formatSearchQuery('big yellow banana');
|
||||
const query = component.formatSearchQuery('big yellow banana', ['cm:name']);
|
||||
|
||||
expect(query).toBe(`(cm:name:"big*") AND (cm:name:"yellow*") AND (cm:name:"banana*")`);
|
||||
});
|
||||
|
||||
it('should support conjunctions with AND operator', () => {
|
||||
config.config = {
|
||||
search: {
|
||||
'aca:fields': ['cm:name', 'cm:title']
|
||||
}
|
||||
};
|
||||
|
||||
const query = component.formatSearchQuery('big AND yellow AND banana');
|
||||
const query = component.formatSearchQuery('big AND yellow AND banana', ['cm:name', 'cm:title']);
|
||||
|
||||
expect(query).toBe(
|
||||
`(cm:name:"big*" OR cm:title:"big*") AND (cm:name:"yellow*" OR cm:title:"yellow*") AND (cm:name:"banana*" OR cm:title:"banana*")`
|
||||
@@ -213,13 +196,7 @@ describe('SearchComponent', () => {
|
||||
});
|
||||
|
||||
it('should support conjunctions with OR operator', () => {
|
||||
config.config = {
|
||||
search: {
|
||||
'aca:fields': ['cm:name', 'cm:title']
|
||||
}
|
||||
};
|
||||
|
||||
const query = component.formatSearchQuery('big OR yellow OR banana');
|
||||
const query = component.formatSearchQuery('big OR yellow OR banana', ['cm:name', 'cm:title']);
|
||||
|
||||
expect(query).toBe(
|
||||
`(cm:name:"big*" OR cm:title:"big*") OR (cm:name:"yellow*" OR cm:title:"yellow*") OR (cm:name:"banana*" OR cm:title:"banana*")`
|
||||
@@ -227,25 +204,13 @@ describe('SearchComponent', () => {
|
||||
});
|
||||
|
||||
it('should support exact term matching with default fields', () => {
|
||||
config.config = {
|
||||
search: {
|
||||
'aca:fields': ['cm:name', 'cm:title']
|
||||
}
|
||||
};
|
||||
|
||||
const query = component.formatSearchQuery('=orange');
|
||||
const query = component.formatSearchQuery('=orange', ['cm:name', 'cm:title']);
|
||||
|
||||
expect(query).toBe(`(=cm:name:"orange" OR =cm:title:"orange")`);
|
||||
});
|
||||
|
||||
it('should support exact term matching with operators', () => {
|
||||
config.config = {
|
||||
search: {
|
||||
'aca:fields': ['cm:name', 'cm:title']
|
||||
}
|
||||
};
|
||||
|
||||
const query = component.formatSearchQuery('=test1.pdf or =test2.pdf');
|
||||
const query = component.formatSearchQuery('=test1.pdf or =test2.pdf', ['cm:name', 'cm:title']);
|
||||
|
||||
expect(query).toBe(`(=cm:name:"test1.pdf" OR =cm:title:"test1.pdf") or (=cm:name:"test2.pdf" OR =cm:title:"test2.pdf")`);
|
||||
});
|
||||
@@ -294,4 +259,17 @@ describe('SearchComponent', () => {
|
||||
});
|
||||
expect(queryBuilder.update).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should update the user query whenever param changed', () => {
|
||||
params.next({ q: '=orange' });
|
||||
expect(queryBuilder.userQuery).toBe(`((=cm:name:"orange"))`);
|
||||
expect(queryBuilder.update).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should update the user query whenever configuration changed', () => {
|
||||
params.next({ q: '=orange' });
|
||||
queryBuilder.configUpdated.next({ 'aca:fields': ['cm:tag'] } as any);
|
||||
expect(queryBuilder.userQuery).toBe(`((=cm:tag:"orange"))`);
|
||||
expect(queryBuilder.update).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
@@ -24,25 +24,26 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { Pagination, MinimalNodeEntity, ResultSetPaging } from '@alfresco/js-api';
|
||||
import { MinimalNodeEntity, Pagination, ResultSetPaging } from '@alfresco/js-api';
|
||||
import { ActivatedRoute, Params, Router } from '@angular/router';
|
||||
import { SearchQueryBuilderService, SearchFilterComponent } from '@alfresco/adf-content-services';
|
||||
import { SearchFilterComponent, SearchForm, SearchQueryBuilderService } from '@alfresco/adf-content-services';
|
||||
import { PageComponent } from '../../page.component';
|
||||
import { Store } from '@ngrx/store';
|
||||
import {
|
||||
AppStore,
|
||||
NavigateToFolder,
|
||||
SnackbarErrorAction,
|
||||
showFacetFilter,
|
||||
infoDrawerPreview,
|
||||
ShowInfoDrawerPreviewAction,
|
||||
NavigateToFolder,
|
||||
SetInfoDrawerPreviewStateAction,
|
||||
SetInfoDrawerStateAction,
|
||||
SetInfoDrawerPreviewStateAction
|
||||
showFacetFilter,
|
||||
ShowInfoDrawerPreviewAction,
|
||||
SnackbarErrorAction
|
||||
} from '@alfresco/aca-shared/store';
|
||||
import { ContentManagementService } from '../../../services/content-management.service';
|
||||
import { AppConfigService, TranslationService } from '@alfresco/adf-core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { TranslationService } from '@alfresco/adf-core';
|
||||
import { combineLatest, Observable } from 'rxjs';
|
||||
import { AppExtensionService } from '@alfresco/aca-shared';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'aca-search-results',
|
||||
@@ -68,7 +69,6 @@ export class SearchResultsComponent extends PageComponent implements OnInit {
|
||||
constructor(
|
||||
private queryBuilder: SearchQueryBuilderService,
|
||||
private route: ActivatedRoute,
|
||||
private config: AppConfigService,
|
||||
store: Store<AppStore>,
|
||||
extensions: AppExtensionService,
|
||||
content: ContentManagementService,
|
||||
@@ -84,11 +84,21 @@ export class SearchResultsComponent extends PageComponent implements OnInit {
|
||||
|
||||
this.showFacetFilter$ = store.select(showFacetFilter);
|
||||
this.infoDrawerPreview$ = store.select(infoDrawerPreview);
|
||||
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['aca:fields']);
|
||||
if (query) {
|
||||
this.queryBuilder.userQuery = decodeURIComponent(query);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
super.ngOnInit();
|
||||
|
||||
this.queryBuilder.resetToDefaults();
|
||||
this.sorting = this.getSorting();
|
||||
|
||||
this.subscriptions.push(
|
||||
@@ -114,10 +124,7 @@ export class SearchResultsComponent extends PageComponent implements OnInit {
|
||||
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 = decodeURIComponent(query);
|
||||
if (this.searchedWord) {
|
||||
this.queryBuilder.update();
|
||||
} else {
|
||||
this.queryBuilder.userQuery = null;
|
||||
@@ -165,7 +172,7 @@ export class SearchResultsComponent extends PageComponent implements OnInit {
|
||||
return '(' + fields.map((field) => `${prefix}${field}:"${term}${suffix}"`).join(' OR ') + ')';
|
||||
}
|
||||
|
||||
formatSearchQuery(userInput: string) {
|
||||
formatSearchQuery(userInput: string, fields = ['cm:name']) {
|
||||
if (!userInput) {
|
||||
return null;
|
||||
}
|
||||
@@ -176,7 +183,6 @@ export class SearchResultsComponent extends PageComponent implements OnInit {
|
||||
return userInput;
|
||||
}
|
||||
|
||||
const fields = this.config.get<string[]>('search.aca:fields', ['cm:name']);
|
||||
const words = userInput.split(' ');
|
||||
|
||||
if (words.length > 1) {
|
||||
@@ -247,8 +253,8 @@ export class SearchResultsComponent extends PageComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
hideSearchFilter() {
|
||||
return !this.totalResults && !this.hasSelectedFilters;
|
||||
onFormChange(form: SearchForm) {
|
||||
this.queryBuilder.updateSelectedConfiguration(form.index);
|
||||
}
|
||||
|
||||
onPreviewClosed() {
|
||||
|
@@ -167,6 +167,7 @@
|
||||
"TITLE": "About"
|
||||
},
|
||||
"SEARCH": {
|
||||
"DEFAULT_SEARCH": "Default",
|
||||
"TITLE": "Search Results",
|
||||
"FOUND_RESULTS": "{{ number }} results found",
|
||||
"FOUND_ONE_RESULT": "{{ number }} result found",
|
||||
|
Reference in New Issue
Block a user