mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-31 17:38:48 +00:00
Update search component to work with 0.4.0 JS API
- Use new search (query) methods - Allow search parameters to be overridden by component - Fix up tests Refs #555
This commit is contained in:
@@ -1,5 +1,12 @@
|
|||||||
<alfresco-search-control *ngIf="isLoggedIn()" [searchTerm]="searchTerm" [autocomplete]="false"
|
<alfresco-search-control *ngIf="isLoggedIn()"
|
||||||
(searchSubmit)="onSearchSubmit($event);" (searchChange)="onSearchTermChange($event);" (expand)="onExpandToggle($event);" (fileSelect)="onFileClicked($event)"></alfresco-search-control>
|
[searchTerm]="searchTerm"
|
||||||
|
[autocomplete]="false"
|
||||||
|
[liveSearchResultType]="'cm:content'"
|
||||||
|
(searchSubmit)="onSearchSubmit($event);"
|
||||||
|
(searchChange)="onSearchTermChange($event);"
|
||||||
|
(expand)="onExpandToggle($event);"
|
||||||
|
(fileSelect)="onFileClicked($event)">
|
||||||
|
</alfresco-search-control>
|
||||||
|
|
||||||
<alfresco-viewer [(showViewer)]="fileShowed"
|
<alfresco-viewer [(showViewer)]="fileShowed"
|
||||||
[fileNodeId]="fileNodeId"
|
[fileNodeId]="fileNodeId"
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<div class="search-results-container">
|
<div class="search-results-container">
|
||||||
<h1>Search results</h1>
|
<h1>Search results</h1>
|
||||||
<alfresco-search (preview)="onFileClicked($event)"></alfresco-search>
|
<alfresco-search [resultType]="'cm:content'" (preview)="onFileClicked($event)"></alfresco-search>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<alfresco-viewer [(showViewer)]="fileShowed" [fileNodeId]="fileNodeId" [overlayMode]="true">
|
<alfresco-viewer [(showViewer)]="fileShowed" [fileNodeId]="fileNodeId" [overlayMode]="true">
|
||||||
|
@@ -180,9 +180,13 @@ bootstrap(SearchDemo, [
|
|||||||
|
|
||||||
**searchTerm**: {string} (optional) default "". Search term to pre-populate the field with<br />
|
**searchTerm**: {string} (optional) default "". Search term to pre-populate the field with<br />
|
||||||
**inputType**: {string} (optional) default "text". Type of the input field to render, e.g. "search" or "text" (default)<br />
|
**inputType**: {string} (optional) default "text". Type of the input field to render, e.g. "search" or "text" (default)<br />
|
||||||
**expandable** {boolean} (optional) default true. Whether to use an expanding search control, if false then a regular input is used.
|
**expandable** {boolean} (optional) default true. Whether to use an expanding search control, if false then a regular input is used.<br />
|
||||||
**autocomplete** {boolean} (optional) default true. Whether the browser should offer field auto-completion for the input field to the user.
|
**autocomplete** {boolean} (optional) default true. Whether the browser should offer field auto-completion for the input field to the user.<br />
|
||||||
**autocompleteEnabled** {boolean} (optional) default true. Whether find-as-you-type suggestions should be offered for matching content items. Set to false to disable.
|
**liveSearchEnabled** {boolean} (optional) default true. Whether find-as-you-type suggestions should be offered for matching content items. Set to false to disable.<br />
|
||||||
|
**liveSearchRoot** {boolean} (optional) default "-root-". NodeRef or node name where the search should start.<br />
|
||||||
|
**liveSearchResultType** {boolean} (optional) default (none). Node type to filter live search results by, e.g. 'cm:content'.<br />
|
||||||
|
**liveSearchMaxResults** {boolean} (optional) default 5. Maximum number of results to show in the live search.<br />
|
||||||
|
**liveSearchResultSort** {boolean} (optional) default (none). Criteria to sort live search results by, must be one of "name" , "modifiedAt" or "createdAt"
|
||||||
|
|
||||||
### Search results
|
### Search results
|
||||||
|
|
||||||
@@ -337,6 +341,10 @@ None
|
|||||||
|
|
||||||
**searchTerm**: {string} (optional) default "". Search term to use when executing the search. Updating this value will
|
**searchTerm**: {string} (optional) default "". Search term to use when executing the search. Updating this value will
|
||||||
run a new search and update the results.<br />
|
run a new search and update the results.<br />
|
||||||
|
**rootNodeId** {boolean} (optional) default "-root-". NodeRef or node name where the search should start.<br />
|
||||||
|
**resultType** {boolean} (optional) default (none). Node type to filter search results by, e.g. 'cm:content'.<br />
|
||||||
|
**maxResults** {boolean} (optional) default 20. Maximum number of results to show in the search.<br />
|
||||||
|
**resultSort** {boolean} (optional) default (none). Criteria to sort search results by, must be one of "name" , "modifiedAt" or "createdAt"
|
||||||
|
|
||||||
## Build from sources
|
## Build from sources
|
||||||
|
|
||||||
|
@@ -56,8 +56,8 @@ export var fakeError = {
|
|||||||
|
|
||||||
export var fakeApi = {
|
export var fakeApi = {
|
||||||
core: {
|
core: {
|
||||||
searchApi: {
|
queriesApi: {
|
||||||
liveSearchNodes: (term, opts) => Promise.resolve(fakeSearch)
|
findNodes: (term, opts) => Promise.resolve(fakeSearch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -80,7 +80,7 @@ describe('AlfrescoSearchAutocompleteComponent', () => {
|
|||||||
|
|
||||||
it('should clear results straight away when a new search term is entered', async(() => {
|
it('should clear results straight away when a new search term is entered', async(() => {
|
||||||
|
|
||||||
spyOn(searchService, 'getSearchNodesPromise')
|
spyOn(searchService, 'getQueryNodesPromise')
|
||||||
.and.returnValue(Promise.resolve(result));
|
.and.returnValue(Promise.resolve(result));
|
||||||
|
|
||||||
component.searchTerm = 'searchTerm';
|
component.searchTerm = 'searchTerm';
|
||||||
@@ -97,7 +97,7 @@ describe('AlfrescoSearchAutocompleteComponent', () => {
|
|||||||
|
|
||||||
it('should display the returned search results', (done) => {
|
it('should display the returned search results', (done) => {
|
||||||
|
|
||||||
spyOn(searchService, 'getSearchNodesPromise')
|
spyOn(searchService, 'getQueryNodesPromise')
|
||||||
.and.returnValue(Promise.resolve(result));
|
.and.returnValue(Promise.resolve(result));
|
||||||
|
|
||||||
component.resultsLoad.subscribe(() => {
|
component.resultsLoad.subscribe(() => {
|
||||||
@@ -112,7 +112,7 @@ describe('AlfrescoSearchAutocompleteComponent', () => {
|
|||||||
|
|
||||||
it('should limit the number of returned search results to the configured maximum', (done) => {
|
it('should limit the number of returned search results to the configured maximum', (done) => {
|
||||||
|
|
||||||
spyOn(searchService, 'getSearchNodesPromise')
|
spyOn(searchService, 'getQueryNodesPromise')
|
||||||
.and.returnValue(Promise.resolve(results));
|
.and.returnValue(Promise.resolve(results));
|
||||||
|
|
||||||
component.resultsLoad.subscribe(() => {
|
component.resultsLoad.subscribe(() => {
|
||||||
@@ -127,7 +127,7 @@ describe('AlfrescoSearchAutocompleteComponent', () => {
|
|||||||
|
|
||||||
it('should display the correct thumbnail for result items', (done) => {
|
it('should display the correct thumbnail for result items', (done) => {
|
||||||
|
|
||||||
spyOn(searchService, 'getSearchNodesPromise')
|
spyOn(searchService, 'getQueryNodesPromise')
|
||||||
.and.returnValue(Promise.resolve(result));
|
.and.returnValue(Promise.resolve(result));
|
||||||
|
|
||||||
component.baseComponentPath = 'http://localhost';
|
component.baseComponentPath = 'http://localhost';
|
||||||
@@ -150,7 +150,7 @@ describe('AlfrescoSearchAutocompleteComponent', () => {
|
|||||||
|
|
||||||
it('should display no result if no result are returned', (done) => {
|
it('should display no result if no result are returned', (done) => {
|
||||||
|
|
||||||
spyOn(searchService, 'getSearchNodesPromise')
|
spyOn(searchService, 'getQueryNodesPromise')
|
||||||
.and.returnValue(Promise.resolve(noResult));
|
.and.returnValue(Promise.resolve(noResult));
|
||||||
|
|
||||||
component.resultsLoad.subscribe(() => {
|
component.resultsLoad.subscribe(() => {
|
||||||
@@ -170,7 +170,7 @@ describe('AlfrescoSearchAutocompleteComponent', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
||||||
spyOn(searchService, 'getSearchNodesPromise')
|
spyOn(searchService, 'getQueryNodesPromise')
|
||||||
.and.returnValue(Promise.reject(errorJson));
|
.and.returnValue(Promise.reject(errorJson));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -215,7 +215,7 @@ describe('AlfrescoSearchAutocompleteComponent', () => {
|
|||||||
|
|
||||||
it('should emit file select when file item clicked', (done) => {
|
it('should emit file select when file item clicked', (done) => {
|
||||||
|
|
||||||
spyOn(searchService, 'getSearchNodesPromise')
|
spyOn(searchService, 'getQueryNodesPromise')
|
||||||
.and.returnValue(Promise.resolve(result));
|
.and.returnValue(Promise.resolve(result));
|
||||||
|
|
||||||
component.resultsLoad.subscribe(() => {
|
component.resultsLoad.subscribe(() => {
|
||||||
@@ -232,7 +232,7 @@ describe('AlfrescoSearchAutocompleteComponent', () => {
|
|||||||
|
|
||||||
it('should not emit preview if a non-file item is clicked', (done) => {
|
it('should not emit preview if a non-file item is clicked', (done) => {
|
||||||
|
|
||||||
spyOn(searchService, 'getSearchNodesPromise')
|
spyOn(searchService, 'getQueryNodesPromise')
|
||||||
.and.returnValue(Promise.resolve(folderResult));
|
.and.returnValue(Promise.resolve(folderResult));
|
||||||
|
|
||||||
spyOn(component.fileSelect, 'emit');
|
spyOn(component.fileSelect, 'emit');
|
||||||
@@ -254,7 +254,7 @@ describe('AlfrescoSearchAutocompleteComponent', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
||||||
spyOn(searchService, 'getSearchNodesPromise')
|
spyOn(searchService, 'getQueryNodesPromise')
|
||||||
.and.returnValue(Promise.resolve(results));
|
.and.returnValue(Promise.resolve(results));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -366,7 +366,7 @@ describe('AlfrescoSearchAutocompleteComponent', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
||||||
spyOn(searchService, 'getSearchNodesPromise')
|
spyOn(searchService, 'getQueryNodesPromise')
|
||||||
.and.returnValue(Promise.resolve(result));
|
.and.returnValue(Promise.resolve(result));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, ElementRef, EventEmitter, Input, OnInit, OnChanges, Output, ViewChild } from '@angular/core';
|
import { Component, ElementRef, EventEmitter, Input, OnInit, OnChanges, Output, ViewChild } from '@angular/core';
|
||||||
import { AlfrescoSearchService } from './../services/alfresco-search.service';
|
import { AlfrescoSearchService, SearchOptions } from './../services/alfresco-search.service';
|
||||||
import { AlfrescoThumbnailService } from './../services/alfresco-thumbnail.service';
|
import { AlfrescoThumbnailService } from './../services/alfresco-thumbnail.service';
|
||||||
import { AlfrescoTranslationService } from 'ng2-alfresco-core';
|
import { AlfrescoTranslationService } from 'ng2-alfresco-core';
|
||||||
|
|
||||||
@@ -43,6 +43,15 @@ export class AlfrescoSearchAutocompleteComponent implements OnInit, OnChanges {
|
|||||||
@Input()
|
@Input()
|
||||||
maxResults: number = 5;
|
maxResults: number = 5;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
resultSort: string = null;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
rootNodeId: string = '-root';
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
resultType: string = null;
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
fileSelect: EventEmitter<any> = new EventEmitter();
|
fileSelect: EventEmitter<any> = new EventEmitter();
|
||||||
|
|
||||||
@@ -84,9 +93,16 @@ export class AlfrescoSearchAutocompleteComponent implements OnInit, OnChanges {
|
|||||||
* @param searchTerm Search query entered by user
|
* @param searchTerm Search query entered by user
|
||||||
*/
|
*/
|
||||||
private displaySearchResults(searchTerm) {
|
private displaySearchResults(searchTerm) {
|
||||||
|
let searchOpts: SearchOptions = {
|
||||||
|
include: ['path'],
|
||||||
|
rootNodeId: this.rootNodeId,
|
||||||
|
nodeType: this.resultType,
|
||||||
|
maxItems: this.maxResults,
|
||||||
|
orderBy: this.resultSort
|
||||||
|
};
|
||||||
if (searchTerm !== null && searchTerm !== '') {
|
if (searchTerm !== null && searchTerm !== '') {
|
||||||
this.alfrescoSearchService
|
this.alfrescoSearchService
|
||||||
.getLiveSearchResults(searchTerm)
|
.getNodeQueryResults(searchTerm, searchOpts)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
results => {
|
results => {
|
||||||
this.results = results.list.entries.slice(0, this.maxResults);
|
this.results = results.list.entries.slice(0, this.maxResults);
|
||||||
|
@@ -22,8 +22,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<alfresco-search-autocomplete #autocomplete *ngIf="autocompleteEnabled"
|
<alfresco-search-autocomplete #autocomplete *ngIf="liveSearchEnabled"
|
||||||
[searchTerm]="autocompleteSearchTerm" [ngClass]="{active: searchActive, valid: searchValid}"
|
[searchTerm]="liveSearchTerm"
|
||||||
|
[rootNodeId]="liveSearchRoot"
|
||||||
|
[resultType]="liveSearchResultType"
|
||||||
|
[resultSort]="liveSearchResultSort"
|
||||||
|
[maxResults]="liveSearchMaxResults"
|
||||||
|
[ngClass]="{active: searchActive, valid: searchValid}"
|
||||||
(fileSelect)="onFileClicked($event)"
|
(fileSelect)="onFileClicked($event)"
|
||||||
(searchFocus)="onAutoCompleteFocus($event)"
|
(searchFocus)="onAutoCompleteFocus($event)"
|
||||||
(scrollBack)="onAutoCompleteReturn($event)"
|
(scrollBack)="onAutoCompleteReturn($event)"
|
||||||
|
@@ -176,7 +176,7 @@ describe('AlfrescoSearchControlComponent', () => {
|
|||||||
|
|
||||||
it('should keep find-as-you-type control visible when user tabs into results', (done) => {
|
it('should keep find-as-you-type control visible when user tabs into results', (done) => {
|
||||||
let searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
let searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
||||||
spyOn(searchService, 'getSearchNodesPromise')
|
spyOn(searchService, 'getQueryNodesPromise')
|
||||||
.and.returnValue(Promise.resolve(result));
|
.and.returnValue(Promise.resolve(result));
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@@ -219,7 +219,7 @@ describe('AlfrescoSearchControlComponent', () => {
|
|||||||
|
|
||||||
it('should select the first result in find-as-you-type when down arrow is pressed and FAYT is visible', (done) => {
|
it('should select the first result in find-as-you-type when down arrow is pressed and FAYT is visible', (done) => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
spyOn(component.autocompleteComponent, 'focusResult');
|
spyOn(component.liveSearchComponent, 'focusResult');
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
inputEl.dispatchEvent(new Event('focus'));
|
inputEl.dispatchEvent(new Event('focus'));
|
||||||
window.setTimeout(() => { // wait for debounce() to complete
|
window.setTimeout(() => { // wait for debounce() to complete
|
||||||
@@ -228,7 +228,7 @@ describe('AlfrescoSearchControlComponent', () => {
|
|||||||
key: 'ArrowDown'
|
key: 'ArrowDown'
|
||||||
}));
|
}));
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(component.autocompleteComponent.focusResult).toHaveBeenCalled();
|
expect(component.liveSearchComponent.focusResult).toHaveBeenCalled();
|
||||||
done();
|
done();
|
||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
@@ -254,7 +254,7 @@ describe('AlfrescoSearchControlComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should NOT display a find-as-you-type control when configured not to', () => {
|
it('should NOT display a find-as-you-type control when configured not to', () => {
|
||||||
fixture.componentInstance.autocompleteEnabled = false;
|
fixture.componentInstance.liveSearchEnabled = false;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
let autocomplete: Element = element.querySelector('alfresco-search-autocomplete');
|
let autocomplete: Element = element.querySelector('alfresco-search-autocomplete');
|
||||||
expect(autocomplete).toBeNull();
|
expect(autocomplete).toBeNull();
|
||||||
|
@@ -56,16 +56,29 @@ export class AlfrescoSearchControlComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
searchControl: FormControl;
|
searchControl: FormControl;
|
||||||
|
|
||||||
@ViewChild('searchInput', {}) searchInput: ElementRef;
|
@ViewChild('searchInput', {})
|
||||||
|
searchInput: ElementRef;
|
||||||
|
|
||||||
@ViewChild('autocomplete')
|
@ViewChild(AlfrescoSearchAutocompleteComponent)
|
||||||
autocompleteComponent: AlfrescoSearchAutocompleteComponent;
|
liveSearchComponent: AlfrescoSearchAutocompleteComponent;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
autocompleteEnabled = true;
|
liveSearchEnabled: boolean = true;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
autocompleteSearchTerm = '';
|
liveSearchTerm: string = '';
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
liveSearchRoot: string = '-root-';
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
liveSearchResultType: string = 'cm:content';
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
liveSearchResultSort: string = null;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
liveSearchMaxResults: number = 5;
|
||||||
|
|
||||||
searchActive = false;
|
searchActive = false;
|
||||||
|
|
||||||
@@ -99,7 +112,7 @@ export class AlfrescoSearchControlComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
private onSearchTermChange(value: string): void {
|
private onSearchTermChange(value: string): void {
|
||||||
this.setAutoCompleteDisplayed(true);
|
this.setAutoCompleteDisplayed(true);
|
||||||
this.autocompleteSearchTerm = value;
|
this.liveSearchTerm = value;
|
||||||
this.searchControl.setValue(value, true);
|
this.searchControl.setValue(value, true);
|
||||||
this.searchValid = this.searchControl.valid;
|
this.searchValid = this.searchControl.valid;
|
||||||
this.searchChange.emit({
|
this.searchChange.emit({
|
||||||
@@ -195,7 +208,7 @@ export class AlfrescoSearchControlComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
onArrowDown(): void {
|
onArrowDown(): void {
|
||||||
if (this.isAutoCompleteDisplayed()) {
|
if (this.isAutoCompleteDisplayed()) {
|
||||||
this.autocompleteComponent.focusResult();
|
this.liveSearchComponent.focusResult();
|
||||||
} else {
|
} else {
|
||||||
this.setAutoCompleteDisplayed(true);
|
this.setAutoCompleteDisplayed(true);
|
||||||
}
|
}
|
||||||
|
@@ -154,17 +154,40 @@ describe('AlfrescoSearchComponent', () => {
|
|||||||
expect(translationService.addTranslationFolder).toHaveBeenCalledWith('node_modules/ng2-alfresco-search/dist/src');
|
expect(translationService.addTranslationFolder).toHaveBeenCalledWith('node_modules/ng2-alfresco-search/dist/src');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Rendering search results', () => {
|
describe('Search results', () => {
|
||||||
|
|
||||||
|
it('should call search service with the correct parameters', (done) => {
|
||||||
|
let searchTerm = 'searchTerm63688', options = {
|
||||||
|
include: ['path'],
|
||||||
|
rootNodeId: '-my-',
|
||||||
|
nodeType: 'my:type',
|
||||||
|
maxItems: 20,
|
||||||
|
orderBy: null
|
||||||
|
};
|
||||||
|
component.searchTerm = searchTerm;
|
||||||
|
component.rootNodeId = '-my-';
|
||||||
|
component.resultType = 'my:type';
|
||||||
|
let searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
||||||
|
spyOn(searchService, 'getQueryNodesPromise')
|
||||||
|
.and.returnValue(Promise.resolve(result));
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
component.resultsLoad.subscribe(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(searchService.getQueryNodesPromise).toHaveBeenCalledWith(searchTerm, options);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should display search results when a search term is provided', (done) => {
|
it('should display search results when a search term is provided', (done) => {
|
||||||
|
|
||||||
let searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
let searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
||||||
spyOn(searchService, 'getSearchNodesPromise')
|
spyOn(searchService, 'getQueryNodesPromise')
|
||||||
.and.returnValue(Promise.resolve(result));
|
.and.returnValue(Promise.resolve(result));
|
||||||
|
|
||||||
component.resultsLoad.subscribe(() => {
|
component.resultsLoad.subscribe(() => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(searchService.getSearchNodesPromise).toHaveBeenCalled();
|
expect(searchService.getQueryNodesPromise).toHaveBeenCalled();
|
||||||
expect(element.querySelector('#result_user_0')).not.toBeNull();
|
expect(element.querySelector('#result_user_0')).not.toBeNull();
|
||||||
expect(element.querySelector('#result_user_0').innerHTML).toBe('John Doe');
|
expect(element.querySelector('#result_user_0').innerHTML).toBe('John Doe');
|
||||||
expect(element.querySelector('#result_name_0').innerHTML).toBe('MyDoc');
|
expect(element.querySelector('#result_name_0').innerHTML).toBe('MyDoc');
|
||||||
@@ -178,7 +201,7 @@ describe('AlfrescoSearchComponent', () => {
|
|||||||
it('should display no result if no result are returned', (done) => {
|
it('should display no result if no result are returned', (done) => {
|
||||||
|
|
||||||
let searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
let searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
||||||
spyOn(searchService, 'getSearchNodesPromise')
|
spyOn(searchService, 'getQueryNodesPromise')
|
||||||
.and.returnValue(Promise.resolve(noResult));
|
.and.returnValue(Promise.resolve(noResult));
|
||||||
|
|
||||||
component.resultsLoad.subscribe(() => {
|
component.resultsLoad.subscribe(() => {
|
||||||
@@ -194,7 +217,7 @@ describe('AlfrescoSearchComponent', () => {
|
|||||||
it('should display an error if an error is encountered running the search', (done) => {
|
it('should display an error if an error is encountered running the search', (done) => {
|
||||||
|
|
||||||
let searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
let searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
||||||
spyOn(searchService, 'getSearchNodesPromise')
|
spyOn(searchService, 'getQueryNodesPromise')
|
||||||
.and.returnValue(Promise.reject(errorJson));
|
.and.returnValue(Promise.reject(errorJson));
|
||||||
|
|
||||||
component.resultsLoad.subscribe(() => {}, () => {
|
component.resultsLoad.subscribe(() => {}, () => {
|
||||||
@@ -214,12 +237,12 @@ describe('AlfrescoSearchComponent', () => {
|
|||||||
it('should update search results when the search term input is changed', (done) => {
|
it('should update search results when the search term input is changed', (done) => {
|
||||||
|
|
||||||
let searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
let searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
||||||
spyOn(searchService, 'getSearchNodesPromise')
|
spyOn(searchService, 'getQueryNodesPromise')
|
||||||
.and.returnValue(Promise.resolve(result));
|
.and.returnValue(Promise.resolve(result));
|
||||||
|
|
||||||
component.resultsLoad.subscribe(() => {
|
component.resultsLoad.subscribe(() => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(searchService.getSearchNodesPromise).toHaveBeenCalledWith('searchTerm2');
|
expect(searchService.getQueryNodesPromise.calls.mostRecent().args[0]).toBe('searchTerm2');
|
||||||
expect(element.querySelector('#result_user_0')).not.toBeNull();
|
expect(element.querySelector('#result_user_0')).not.toBeNull();
|
||||||
expect(element.querySelector('#result_user_0').innerHTML).toBe('John Doe');
|
expect(element.querySelector('#result_user_0').innerHTML).toBe('John Doe');
|
||||||
expect(element.querySelector('#result_name_0').innerHTML).toBe('MyDoc');
|
expect(element.querySelector('#result_name_0').innerHTML).toBe('MyDoc');
|
||||||
@@ -235,7 +258,7 @@ describe('AlfrescoSearchComponent', () => {
|
|||||||
it('should emit preview when file item clicked', (done) => {
|
it('should emit preview when file item clicked', (done) => {
|
||||||
|
|
||||||
let searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
let searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
||||||
spyOn(searchService, 'getSearchNodesPromise')
|
spyOn(searchService, 'getQueryNodesPromise')
|
||||||
.and.returnValue(Promise.resolve(result));
|
.and.returnValue(Promise.resolve(result));
|
||||||
|
|
||||||
component.resultsLoad.subscribe(() => {
|
component.resultsLoad.subscribe(() => {
|
||||||
@@ -254,7 +277,7 @@ describe('AlfrescoSearchComponent', () => {
|
|||||||
it('should not emit preview when non-file item is clicked', (done) => {
|
it('should not emit preview when non-file item is clicked', (done) => {
|
||||||
|
|
||||||
let searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
let searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
|
||||||
spyOn(searchService, 'getSearchNodesPromise')
|
spyOn(searchService, 'getQueryNodesPromise')
|
||||||
.and.returnValue(Promise.resolve(folderResult));
|
.and.returnValue(Promise.resolve(folderResult));
|
||||||
|
|
||||||
spyOn(component.preview, 'emit');
|
spyOn(component.preview, 'emit');
|
||||||
|
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
import { Component, EventEmitter, Input, Output, Optional, OnChanges, SimpleChanges, OnInit } from '@angular/core';
|
import { Component, EventEmitter, Input, Output, Optional, OnChanges, SimpleChanges, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute, Params } from '@angular/router';
|
import { ActivatedRoute, Params } from '@angular/router';
|
||||||
import { AlfrescoSearchService } from './../services/alfresco-search.service';
|
import { AlfrescoSearchService, SearchOptions } from './../services/alfresco-search.service';
|
||||||
import { AlfrescoThumbnailService } from './../services/alfresco-thumbnail.service';
|
import { AlfrescoThumbnailService } from './../services/alfresco-thumbnail.service';
|
||||||
import { AlfrescoTranslationService } from 'ng2-alfresco-core';
|
import { AlfrescoTranslationService } from 'ng2-alfresco-core';
|
||||||
|
|
||||||
@@ -34,6 +34,18 @@ export class AlfrescoSearchComponent implements OnChanges, OnInit {
|
|||||||
@Input()
|
@Input()
|
||||||
searchTerm: string = '';
|
searchTerm: string = '';
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
maxResults: number = 20;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
resultSort: string = null;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
rootNodeId: string = '-root-';
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
resultType: string = null;
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
preview: EventEmitter<any> = new EventEmitter();
|
preview: EventEmitter<any> = new EventEmitter();
|
||||||
|
|
||||||
@@ -102,10 +114,17 @@ export class AlfrescoSearchComponent implements OnChanges, OnInit {
|
|||||||
* Loads and displays search results
|
* Loads and displays search results
|
||||||
* @param searchTerm Search query entered by user
|
* @param searchTerm Search query entered by user
|
||||||
*/
|
*/
|
||||||
public displaySearchResults(searchTerm): void {
|
private displaySearchResults(searchTerm): void {
|
||||||
if (searchTerm !== null && this.alfrescoSearchService !== null) {
|
if (searchTerm && this.alfrescoSearchService) {
|
||||||
|
let searchOpts: SearchOptions = {
|
||||||
|
include: ['path'],
|
||||||
|
rootNodeId: this.rootNodeId,
|
||||||
|
nodeType: this.resultType,
|
||||||
|
maxItems: this.maxResults,
|
||||||
|
orderBy: this.resultSort
|
||||||
|
};
|
||||||
this.alfrescoSearchService
|
this.alfrescoSearchService
|
||||||
.getLiveSearchResults(searchTerm)
|
.getNodeQueryResults(searchTerm, searchOpts)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
results => {
|
results => {
|
||||||
this.results = results.list.entries;
|
this.results = results.list.entries;
|
||||||
|
@@ -40,23 +40,34 @@ describe('AlfrescoSearchService', () => {
|
|||||||
spyOn(authenticationService, 'getAlfrescoApi').and.returnValue(fakeApi);
|
spyOn(authenticationService, 'getAlfrescoApi').and.returnValue(fakeApi);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call search API with the correct parameters', (done) => {
|
it('should call search API with no additional options', (done) => {
|
||||||
|
let searchTerm = 'searchTerm63688';
|
||||||
|
spyOn(fakeApi.core.queriesApi, 'findNodes').and.returnValue(Promise.resolve(fakeSearch));
|
||||||
|
service.getNodeQueryResults(searchTerm).subscribe(
|
||||||
|
() => {
|
||||||
|
expect(fakeApi.core.queriesApi.findNodes).toHaveBeenCalledWith(searchTerm, undefined);
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call search API with additional options', (done) => {
|
||||||
let searchTerm = 'searchTerm63688', options = {
|
let searchTerm = 'searchTerm63688', options = {
|
||||||
include: [ 'path' ],
|
include: [ 'path' ],
|
||||||
rootNodeId: '-root-',
|
rootNodeId: '-root-',
|
||||||
nodeType: 'cm:content'
|
nodeType: 'cm:content'
|
||||||
};
|
};
|
||||||
spyOn(fakeApi.core.searchApi, 'liveSearchNodes').and.returnValue(Promise.resolve(fakeSearch));
|
spyOn(fakeApi.core.queriesApi, 'findNodes').and.returnValue(Promise.resolve(fakeSearch));
|
||||||
service.getLiveSearchResults(searchTerm).subscribe(
|
service.getNodeQueryResults(searchTerm, options).subscribe(
|
||||||
() => {
|
() => {
|
||||||
expect(fakeApi.core.searchApi.liveSearchNodes).toHaveBeenCalledWith(searchTerm, options);
|
expect(fakeApi.core.queriesApi.findNodes).toHaveBeenCalledWith(searchTerm, options);
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return search results returned from the API', (done) => {
|
it('should return search results returned from the API', (done) => {
|
||||||
service.getLiveSearchResults('').subscribe(
|
service.getNodeQueryResults('').subscribe(
|
||||||
(res: any) => {
|
(res: any) => {
|
||||||
expect(res).toBeDefined();
|
expect(res).toBeDefined();
|
||||||
expect(res).toEqual(fakeSearch);
|
expect(res).toEqual(fakeSearch);
|
||||||
@@ -66,8 +77,8 @@ describe('AlfrescoSearchService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should notify errors returned from the API', (done) => {
|
it('should notify errors returned from the API', (done) => {
|
||||||
spyOn(fakeApi.core.searchApi, 'liveSearchNodes').and.returnValue(Promise.reject(fakeError));
|
spyOn(fakeApi.core.queriesApi, 'findNodes').and.returnValue(Promise.reject(fakeError));
|
||||||
service.getLiveSearchResults('').subscribe(
|
service.getNodeQueryResults('').subscribe(
|
||||||
() => {},
|
() => {},
|
||||||
(res: any) => {
|
(res: any) => {
|
||||||
expect(res).toBeDefined();
|
expect(res).toBeDefined();
|
||||||
@@ -78,8 +89,8 @@ describe('AlfrescoSearchService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should notify a general error if the API does not return a specific error', (done) => {
|
it('should notify a general error if the API does not return a specific error', (done) => {
|
||||||
spyOn(fakeApi.core.searchApi, 'liveSearchNodes').and.returnValue(Promise.reject(null));
|
spyOn(fakeApi.core.queriesApi, 'findNodes').and.returnValue(Promise.reject(null));
|
||||||
service.getLiveSearchResults('').subscribe(
|
service.getNodeQueryResults('').subscribe(
|
||||||
() => {},
|
() => {},
|
||||||
(res: any) => {
|
(res: any) => {
|
||||||
expect(res).toBeDefined();
|
expect(res).toBeDefined();
|
||||||
|
@@ -32,25 +32,30 @@ export class AlfrescoSearchService {
|
|||||||
* Execute a search against the repository
|
* Execute a search against the repository
|
||||||
*
|
*
|
||||||
* @param term Search term
|
* @param term Search term
|
||||||
|
* @param options Additional options passed to the search
|
||||||
* @returns {Observable<NodePaging>} Search results
|
* @returns {Observable<NodePaging>} Search results
|
||||||
*/
|
*/
|
||||||
public getLiveSearchResults(term: string): Observable<any> {
|
public getNodeQueryResults(term: string, options?: SearchOptions): Observable<any> {
|
||||||
return Observable.fromPromise(this.getSearchNodesPromise(term))
|
return Observable.fromPromise(this.getQueryNodesPromise(term, options))
|
||||||
.map(res => <any> res)
|
.map(res => <any> res)
|
||||||
.catch(this.handleError);
|
.catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getSearchNodesPromise(term: string) {
|
private getQueryNodesPromise(term: string, opts: SearchOptions) {
|
||||||
let nodeId = '-root-';
|
return this.authService.getAlfrescoApi().core.queriesApi.findNodes(term, opts);
|
||||||
let opts = {
|
|
||||||
include: ['path'],
|
|
||||||
rootNodeId: nodeId,
|
|
||||||
nodeType: 'cm:content'
|
|
||||||
};
|
|
||||||
return this.authService.getAlfrescoApi().core.searchApi.liveSearchNodes(term, opts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleError(error: any): Observable<any> {
|
private handleError(error: any): Observable<any> {
|
||||||
return Observable.throw(error || 'Server error');
|
return Observable.throw(error || 'Server error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SearchOptions {
|
||||||
|
skipCount?: number;
|
||||||
|
maxItems?: number;
|
||||||
|
rootNodeId?: string;
|
||||||
|
nodeType?: string;
|
||||||
|
include?: string[];
|
||||||
|
orderBy?: string;
|
||||||
|
fields?: string[];
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user