mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
[ACS-5839] migrate from QueryBody to SearchResult type (#8861)
* [ci:force] migrate from QueryBody to SearchQuery * [ci:force] migrate from QueryBody to SearchQuery * [ci:force] migrate from QueryBody to SearchQuery * [ci:force] update docs and variables as per code review
This commit is contained in:
parent
c73e95c9bf
commit
c83d92c539
@ -15,15 +15,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { QueryBody } from '@alfresco/js-api';
|
||||
import { SearchRequest } from '@alfresco/js-api';
|
||||
import { SearchConfigurationInterface } from '@alfresco/adf-content-services';
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class TestSearchConfigurationService implements SearchConfigurationInterface {
|
||||
|
||||
public generateQueryBody(searchTerm: string, maxResults: number, skipCount: number): QueryBody {
|
||||
const defaultQueryBody: QueryBody = {
|
||||
public generateQueryBody(searchTerm: string, maxResults: number, skipCount: number): SearchRequest {
|
||||
return {
|
||||
query: {
|
||||
query: searchTerm ? `${searchTerm}* OR name:${searchTerm}*` : searchTerm
|
||||
},
|
||||
@ -35,9 +34,8 @@ export class TestSearchConfigurationService implements SearchConfigurationInterf
|
||||
filterQueries: [
|
||||
/* eslint-disable-next-line */
|
||||
{ query: "TYPE:'cm:folder'" },
|
||||
{ query: 'NOT cm:creator:System' }]
|
||||
{ query: 'NOT cm:creator:System' }
|
||||
]
|
||||
};
|
||||
|
||||
return defaultQueryBody;
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ This document lists all the deprecated ADF v2.x components that were removed for
|
||||
This modification has enabled us to remove some code duplication between the two modules.
|
||||
|
||||
- [PR ADF-1873](https://github.com/Alfresco/alfresco-ng2-components/pull/4145):
|
||||
- `adf-search-control`: The `QueryBody`, and
|
||||
- `adf-search-control`: The `SearchRequest`, and
|
||||
`customQueryBody` inputs of the [`SearchControlComponent`](../content-services/components/search-control.component.md) have been removed in favor of the
|
||||
[custom search configuration interface](../core/interfaces/search-configuration.interface.md).
|
||||
The inputs were deprecated in v2.1.0.
|
||||
|
@ -151,8 +151,7 @@ By doing this, you can get the results as the user types into the input text.
|
||||
### Custom search configuration
|
||||
|
||||
You can get finer control over the parameters of a search by defining them in a custom
|
||||
[QueryBody](https://github.com/Alfresco/alfresco-js-api/blob/1.6.0/src/alfresco-search-rest-api/docs/QueryBody.md)
|
||||
object. The recommended way to do this is with a custom implementation of the
|
||||
**SearchRequest** object. The recommended way to do this is with a custom implementation of the
|
||||
[Search Configuration interface](../../core/interfaces/search-configuration.interface.md). The ADF source provides a standard implementation of this
|
||||
interface, [`SearchConfigurationService`](../../core/services/search-configuration.service.md) that you can use as a base to adapt to your needs. See the
|
||||
[Search Configuration interface](../../core/interfaces/search-configuration.interface.md) page for full details of how to
|
||||
|
@ -20,12 +20,12 @@ Stores information from all the custom search and faceted search widgets, compil
|
||||
Adds a facet bucket to a field.
|
||||
- _field:_ [`FacetField`](../../../lib/content-services/src/lib/search/models/facet-field.interface.ts) - The target field
|
||||
- _bucket:_ [`FacetFieldBucket`](../../../lib/content-services/src/lib/search/models/facet-field-bucket.interface.ts) - Bucket to add
|
||||
- **buildQuery**(): `QueryBody`<br/>
|
||||
- **buildQuery**(): `SearchRequest`<br/>
|
||||
Builds the current query.
|
||||
- **Returns** `QueryBody` - The finished query
|
||||
- **execute**(queryBody?: `QueryBody`)<br/>
|
||||
- **Returns** `SearchRequest` - The finished query
|
||||
- **execute**(queryBody?: `SearchRequest`)<br/>
|
||||
Builds and executes the current query.
|
||||
- _queryBody:_ `QueryBody` - (Optional)
|
||||
- _queryBody:_ `SearchRequest` - (Optional)
|
||||
- **getDefaultConfiguration**(): [`SearchConfiguration`](../../../lib/content-services/src/lib/search/models/search-configuration.interface.ts)`|undefined`<br/>
|
||||
|
||||
- **Returns** [`SearchConfiguration`](../../../lib/content-services/src/lib/search/models/search-configuration.interface.ts)`|undefined` -
|
||||
@ -81,18 +81,18 @@ Stores information from all the custom search and faceted search widgets, compil
|
||||
- _bucket:_ [`FacetFieldBucket`](../../../lib/content-services/src/lib/search/models/facet-field-bucket.interface.ts) - Bucket to remove
|
||||
- **resetToDefaults**()<br/>
|
||||
|
||||
- **search**(queryBody: `QueryBody`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ResultSetPaging`](https://github.com/Alfresco/alfresco-js-api/blob/develop/src/api/search-rest-api/docs/ResultSetPaging.md)`>`<br/>
|
||||
- **search**(queryBody: `SearchRequest`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ResultSetPaging`](https://github.com/Alfresco/alfresco-js-api/blob/develop/src/api/search-rest-api/docs/ResultSetPaging.md)`>`<br/>
|
||||
|
||||
- _queryBody:_ `QueryBody` -
|
||||
- _queryBody:_ `SearchRequest` -
|
||||
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ResultSetPaging`](https://github.com/Alfresco/alfresco-js-api/blob/develop/src/api/search-rest-api/docs/ResultSetPaging.md)`>` -
|
||||
|
||||
- **setScope**(scope: `RequestScope`)<br/>
|
||||
|
||||
- _scope:_ `RequestScope` -
|
||||
|
||||
- **update**(queryBody?: `QueryBody`)<br/>
|
||||
- **update**(queryBody?: `SearchRequest`)<br/>
|
||||
Builds the current query and triggers the `updated` event.
|
||||
- _queryBody:_ `QueryBody` - (Optional)
|
||||
- _queryBody:_ `SearchRequest` - (Optional)
|
||||
- **updateSelectedConfiguration**(index: `number`)<br/>
|
||||
|
||||
- _index:_ `number` -
|
||||
|
@ -10,14 +10,13 @@ Provides fine control of parameters to a search.
|
||||
|
||||
## Methods
|
||||
|
||||
`generateQueryBody(searchTerm: string, maxResults: string, skipCount: string): QueryBody`<br/>
|
||||
Generates a QueryBody object with custom search parameters.
|
||||
`generateQueryBody(searchTerm: string, maxResults: string, skipCount: string): SearchRequest`<br/>
|
||||
Generates a request object with custom search parameters.
|
||||
|
||||
## Details
|
||||
|
||||
The interface defines a service that generates a custom
|
||||
[QueryBody](https://github.com/Alfresco/alfresco-js-api/blob/1.6.0/src/alfresco-search-rest-api/docs/QueryBody.md)
|
||||
object. This object can then be supplied to a search operation to refine the search parameters.
|
||||
**SearchRequest** object. This object can then be supplied to a search operation to refine the search parameters.
|
||||
|
||||
A standard implementation, the
|
||||
[Search Configuration service](../services/search-configuration.service.md) is provided in the ADF Core library
|
||||
@ -29,37 +28,30 @@ described below.
|
||||
1. Implement the service class
|
||||
|
||||
Create your own service class to implement the [`SearchConfigurationInterface`](../../core/interfaces/search-configuration.interface.md). This defines the
|
||||
the `generateQueryBody` method that returns the QueryBody object. See the
|
||||
[QueryBody](https://github.com/Alfresco/alfresco-js-api/blob/1.6.0/src/alfresco-search-rest-api/docs/QueryBody.md)
|
||||
page in the Alfresco JS API for further details about the options this object provides.
|
||||
`generateQueryBody` method that returns the query object.
|
||||
|
||||
An example implementation is given below:
|
||||
|
||||
```ts
|
||||
import { QueryBody } from '@alfresco/js-api';
|
||||
import { SearchRequest } from '@alfresco/js-api';
|
||||
import { SearchConfigurationInterface } from '@alfresco/adf-core';
|
||||
|
||||
export class TestSearchConfigurationService implements SearchConfigurationInterface {
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
public generateQueryBody(searchTerm: string, maxResults: string, skipCount: string): QueryBody {
|
||||
const defaultQueryBody: QueryBody = {
|
||||
generateQueryBody(searchTerm: string, maxItems: string, skipCount: string): SearchRequest {
|
||||
return {
|
||||
query: {
|
||||
query: searchTerm ? `${searchTerm}* OR name:${searchTerm}*` : searchTerm
|
||||
},
|
||||
include: ['path', 'allowableOperations'],
|
||||
paging: {
|
||||
maxItems: maxResults,
|
||||
skipCount: skipCount
|
||||
maxItems,
|
||||
skipCount
|
||||
},
|
||||
filterQueries: [
|
||||
{ query: "TYPE:'cm:folder'" },
|
||||
{ query: 'NOT cm:creator:System' }]
|
||||
};
|
||||
|
||||
return defaultQueryBody;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -13,18 +13,17 @@ Provides fine control of parameters to a search.
|
||||
|
||||
### Methods
|
||||
|
||||
- **generateQueryBody**(searchTerm: `string`, maxResults: `number`, skipCount: `number`): `QueryBody`<br/>
|
||||
Generates a QueryBody object with custom search parameters.
|
||||
- **generateQueryBody**(searchTerm: `string`, maxResults: `number`, skipCount: `number`): `SearchRequest`<br/>
|
||||
Generates a request object with custom search parameters.
|
||||
- _searchTerm:_ `string` - Term text to search for
|
||||
- _maxResults:_ `number` - Maximum number of search results to show in a page
|
||||
- _skipCount:_ `number` - The offset of the start of the page within the results list
|
||||
- **Returns** `QueryBody` - Query body defined by the parameters
|
||||
- **Returns** `SearchRequest` - Query body defined by the parameters
|
||||
|
||||
## Details
|
||||
|
||||
The `generateQueryBody` method returns a
|
||||
[QueryBody](https://github.com/Alfresco/alfresco-js-api/blob/1.6.0/src/alfresco-search-rest-api/docs/QueryBody.md)
|
||||
object. This configures the search to use `searchTerm` along with `maxResults` and `skipCount`
|
||||
The `generateQueryBody` method returns a **SearchRequest** object.
|
||||
This configures the search to use `searchTerm` along with `maxResults` and `skipCount`
|
||||
specified for the paging of the search results.
|
||||
|
||||
This service is a standard implementation of the
|
||||
|
@ -24,9 +24,9 @@ Accesses the Content Services Search API.
|
||||
- _maxResults:_ `number` - Maximum number of items in the list of results
|
||||
- _skipCount:_ `number` - Number of higher-ranked items to skip over in the list
|
||||
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ResultSetPaging`](https://github.com/Alfresco/alfresco-js-api/blob/develop/src/api/search-rest-api/docs/ResultSetPaging.md)`>` - List of search results
|
||||
- **searchByQueryBody**(queryBody: `QueryBody`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ResultSetPaging`](https://github.com/Alfresco/alfresco-js-api/blob/develop/src/api/search-rest-api/docs/ResultSetPaging.md)`>`<br/>
|
||||
Performs a search with its parameters supplied by a QueryBody object.
|
||||
- _queryBody:_ `QueryBody` - Object containing the search parameters
|
||||
- **searchByQueryBody**(queryBody: `SearchRequest`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ResultSetPaging`](https://github.com/Alfresco/alfresco-js-api/blob/develop/src/api/search-rest-api/docs/ResultSetPaging.md)`>`<br/>
|
||||
Performs a search with its parameters supplied by a SearchRequest object.
|
||||
- _queryBody:_ `SearchRequest` - Object containing the search parameters
|
||||
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ResultSetPaging`](https://github.com/Alfresco/alfresco-js-api/blob/develop/src/api/search-rest-api/docs/ResultSetPaging.md)`>` - List of search results
|
||||
|
||||
## Details
|
||||
|
@ -15,18 +15,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { QueryBody } from '@alfresco/js-api';
|
||||
import { SearchRequest } from '@alfresco/js-api';
|
||||
|
||||
export interface SearchConfigurationInterface {
|
||||
|
||||
/**
|
||||
* Generates a QueryBody object with custom search parameters.
|
||||
* Generates a query object with custom search parameters.
|
||||
*
|
||||
* @param searchTerm Term text to search for
|
||||
* @param maxResults Maximum number of search results to show in a page
|
||||
* @param skipCount The offset of the start of the page within the results list
|
||||
* @returns Query body defined by the parameters
|
||||
*/
|
||||
generateQueryBody(searchTerm: string, maxResults: number, skipCount: number): QueryBody;
|
||||
|
||||
generateQueryBody(searchTerm: string, maxResults: number, skipCount: number): SearchRequest;
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ import { CustomResourcesService } from '../document-list/services/custom-resourc
|
||||
import { NodeEntryEvent, ShareDataRow } from '../document-list';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { SearchQueryBuilderService } from '../search';
|
||||
import { mockQueryBody } from '../mock/search-query.mock';
|
||||
import { mockSearchRequest } from '../mock/search-query.mock';
|
||||
import { SitesService } from '../common/services/sites.service';
|
||||
import { NodesApiService } from '../common/services/nodes-api.service';
|
||||
|
||||
@ -168,16 +168,16 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
||||
expect(component.searchTerm).toEqual('search-term');
|
||||
}));
|
||||
|
||||
it('should perform a search when the queryBody gets updated and it is defined', fakeAsync(() => {
|
||||
it('should perform a search when the search request gets updated and it is defined', fakeAsync(() => {
|
||||
typeToSearchBox('search-term');
|
||||
|
||||
tick(debounceSearch);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(searchSpy).toHaveBeenCalledWith(mockQueryBody);
|
||||
expect(searchSpy).toHaveBeenCalledWith(mockSearchRequest);
|
||||
}));
|
||||
|
||||
it('should NOT perform a search and clear the results when the queryBody gets updated and it is NOT defined', async () => {
|
||||
it('should NOT perform a search and clear the results when the search request gets updated and it is NOT defined', async () => {
|
||||
spyOn(component, 'clearSearch');
|
||||
|
||||
searchQueryBuilderService.userQuery = '';
|
||||
@ -212,22 +212,22 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
||||
tick(debounceSearch);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(searchSpy).toHaveBeenCalledWith(mockQueryBody);
|
||||
expect(searchSpy).toHaveBeenCalledWith(mockSearchRequest);
|
||||
}));
|
||||
|
||||
it('should the query include the show files filterQuery', fakeAsync(() => {
|
||||
component.showFilesInResult = true;
|
||||
typeToSearchBox('search-term');
|
||||
|
||||
const expectedQueryBody = mockQueryBody;
|
||||
expectedQueryBody.filterQueries.push({
|
||||
const expectedRequest = mockSearchRequest;
|
||||
expectedRequest.filterQueries.push({
|
||||
query: `TYPE:'cm:folder' OR TYPE:'cm:content'`
|
||||
});
|
||||
|
||||
tick(debounceSearch);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(searchSpy).toHaveBeenCalledWith(expectedQueryBody);
|
||||
expect(searchSpy).toHaveBeenCalledWith(expectedRequest);
|
||||
}));
|
||||
|
||||
it('should reset the currently chosen node in case of starting a new search', fakeAsync(() => {
|
||||
@ -257,11 +257,11 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
||||
|
||||
component.siteChanged({ entry: { guid: 'namek' } } as SiteEntry);
|
||||
|
||||
const expectedQueryBody = mockQueryBody;
|
||||
expectedQueryBody.filterQueries = [{ query: `ANCESTOR:'workspace://SpacesStore/namek'` }];
|
||||
const expectedRequest = mockSearchRequest;
|
||||
expectedRequest.filterQueries = [{ query: `ANCESTOR:'workspace://SpacesStore/namek'` }];
|
||||
|
||||
expect(searchSpy.calls.count()).toBe(2);
|
||||
expect(searchSpy).toHaveBeenCalledWith(expectedQueryBody);
|
||||
expect(searchSpy).toHaveBeenCalledWith(expectedRequest);
|
||||
}));
|
||||
|
||||
it('should create the query with the right parameters on changing the site selectBox value from a custom dropdown menu', fakeAsync(() => {
|
||||
@ -277,8 +277,8 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
||||
|
||||
component.siteChanged({ entry: { guid: '-sites-' } } as SiteEntry);
|
||||
|
||||
const expectedQueryBodyWithSiteChange = mockQueryBody;
|
||||
expectedQueryBodyWithSiteChange.filterQueries = [
|
||||
const expectedRequest = mockSearchRequest;
|
||||
expectedRequest.filterQueries = [
|
||||
{
|
||||
query: `ANCESTOR:'workspace://SpacesStore/-sites-' OR ANCESTOR:'workspace://SpacesStore/123456testId' OR ANCESTOR:'workspace://SpacesStore/09876543testId'`
|
||||
}
|
||||
@ -286,8 +286,8 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
||||
|
||||
expect(searchSpy).toHaveBeenCalled();
|
||||
expect(searchSpy.calls.count()).toBe(2);
|
||||
expect(searchSpy).toHaveBeenCalledWith(mockQueryBody);
|
||||
expect(searchSpy).toHaveBeenCalledWith(expectedQueryBodyWithSiteChange);
|
||||
expect(searchSpy).toHaveBeenCalledWith(mockSearchRequest);
|
||||
expect(searchSpy).toHaveBeenCalledWith(expectedRequest);
|
||||
}));
|
||||
|
||||
it('should get the corresponding node ids on search when a known alias is selected from dropdown', fakeAsync(() => {
|
||||
@ -404,10 +404,10 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
||||
typeToSearchBox('search-term');
|
||||
tick(debounceSearch);
|
||||
|
||||
const expectedQueryBody = mockQueryBody;
|
||||
expectedQueryBody.filterQueries = [{ query: `ANCESTOR:'workspace://SpacesStore/my-root-id'` }];
|
||||
const expectedRequest = mockSearchRequest;
|
||||
expectedRequest.filterQueries = [{ query: `ANCESTOR:'workspace://SpacesStore/my-root-id'` }];
|
||||
|
||||
expect(searchSpy).toHaveBeenCalledWith(expectedQueryBody);
|
||||
expect(searchSpy).toHaveBeenCalledWith(expectedRequest);
|
||||
}));
|
||||
|
||||
it('should emit showingSearch event with true while searching', async () => {
|
||||
@ -476,10 +476,10 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
||||
component.restrictRootToCurrentFolderId = true;
|
||||
component.siteChanged({ entry: { guid: 'my-site-id' } } as SiteEntry);
|
||||
|
||||
const expectedQueryBodyWithSiteChange = mockQueryBody;
|
||||
expectedQueryBodyWithSiteChange.filterQueries = [{ query: `ANCESTOR:'workspace://SpacesStore/my-site-id'` }];
|
||||
const expectedRequest = mockSearchRequest;
|
||||
expectedRequest.filterQueries = [{ query: `ANCESTOR:'workspace://SpacesStore/my-site-id'` }];
|
||||
|
||||
expect(searchSpy).toHaveBeenCalledWith(expectedQueryBodyWithSiteChange);
|
||||
expect(searchSpy).toHaveBeenCalledWith(expectedRequest);
|
||||
});
|
||||
|
||||
it('should restrict the breadcrumb to the currentFolderId in case restrictedRoot is true', async () => {
|
||||
@ -735,7 +735,7 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
||||
});
|
||||
|
||||
it('should set its loading state to true to perform a new search', async () => {
|
||||
component.prepareDialogForNewSearch(mockQueryBody);
|
||||
component.prepareDialogForNewSearch(mockSearchRequest);
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
|
@ -15,22 +15,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
EventEmitter,
|
||||
Input,
|
||||
OnInit,
|
||||
Output,
|
||||
ViewChild,
|
||||
ViewEncapsulation,
|
||||
OnDestroy,
|
||||
Inject
|
||||
} from '@angular/core';
|
||||
import { Component, EventEmitter, Input, OnInit, Output, ViewChild, ViewEncapsulation, OnDestroy, Inject } from '@angular/core';
|
||||
import {
|
||||
HighlightDirective,
|
||||
UserPreferencesService,
|
||||
UserPreferenceValues,
|
||||
InfinitePaginationComponent, PaginatedComponent,
|
||||
InfinitePaginationComponent,
|
||||
PaginatedComponent,
|
||||
AppConfigService,
|
||||
DataSorting,
|
||||
ShowHeaderMode
|
||||
@ -39,7 +30,7 @@ import { NodesApiService } from '../common/services/nodes-api.service';
|
||||
import { UploadService } from '../common/services/upload.service';
|
||||
import { FileUploadCompleteEvent, FileUploadDeleteEvent } from '../common/events/file.event';
|
||||
import { UntypedFormControl } from '@angular/forms';
|
||||
import { Node, NodePaging, Pagination, SiteEntry, SitePaging, NodeEntry, QueryBody, RequestScope } from '@alfresco/js-api';
|
||||
import { Node, NodePaging, Pagination, SiteEntry, SitePaging, NodeEntry, SearchRequest, RequestScope } from '@alfresco/js-api';
|
||||
import { DocumentListComponent } from '../document-list/components/document-list.component';
|
||||
import { RowFilter } from '../document-list/data/row-filter.model';
|
||||
import { ImageResolver } from '../document-list/data/image-resolver.model';
|
||||
@ -63,13 +54,14 @@ export const defaultValidation = () => true;
|
||||
styleUrls: ['./content-node-selector-panel.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
host: { class: 'adf-content-node-selector-panel' },
|
||||
providers: [{
|
||||
provide: SEARCH_QUERY_SERVICE_TOKEN,
|
||||
useClass: SearchQueryBuilderService
|
||||
}]
|
||||
providers: [
|
||||
{
|
||||
provide: SEARCH_QUERY_SERVICE_TOKEN,
|
||||
useClass: SearchQueryBuilderService
|
||||
}
|
||||
]
|
||||
})
|
||||
export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
DEFAULT_PAGINATION: Pagination = new Pagination({
|
||||
maxItems: 25,
|
||||
@ -276,15 +268,16 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
|
||||
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(private customResourcesService: CustomResourcesService,
|
||||
@Inject(SEARCH_QUERY_SERVICE_TOKEN) public queryBuilderService: SearchQueryBuilderService,
|
||||
private userPreferencesService: UserPreferencesService,
|
||||
private nodesApiService: NodesApiService,
|
||||
private uploadService: UploadService,
|
||||
private sitesService: SitesService,
|
||||
private appConfigService: AppConfigService,
|
||||
private contentNodeSelectorPanelService: ContentNodeSelectorPanelService) {
|
||||
}
|
||||
constructor(
|
||||
private customResourcesService: CustomResourcesService,
|
||||
@Inject(SEARCH_QUERY_SERVICE_TOKEN) public queryBuilderService: SearchQueryBuilderService,
|
||||
private userPreferencesService: UserPreferencesService,
|
||||
private nodesApiService: NodesApiService,
|
||||
private uploadService: UploadService,
|
||||
private sitesService: SitesService,
|
||||
private appConfigService: AppConfigService,
|
||||
private contentNodeSelectorPanelService: ContentNodeSelectorPanelService
|
||||
) {}
|
||||
|
||||
set chosenNode(value: Node[]) {
|
||||
this._chosenNode = value;
|
||||
@ -304,43 +297,34 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.searchInput.valueChanges
|
||||
.pipe(
|
||||
debounceTime(this.debounceSearch),
|
||||
takeUntil(this.onDestroy$)
|
||||
)
|
||||
.subscribe((searchValue: string) => {
|
||||
this.searchTerm = searchValue;
|
||||
this.queryBuilderService.userQuery = searchValue.length > 0 ? `${searchValue}*` : searchValue ;
|
||||
this.queryBuilderService.update();
|
||||
});
|
||||
this.searchInput.valueChanges.pipe(debounceTime(this.debounceSearch), takeUntil(this.onDestroy$)).subscribe((searchValue: string) => {
|
||||
this.searchTerm = searchValue;
|
||||
this.queryBuilderService.userQuery = searchValue.length > 0 ? `${searchValue}*` : searchValue;
|
||||
this.queryBuilderService.update();
|
||||
});
|
||||
|
||||
this.queryBuilderService.updated
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe((queryBody: QueryBody) => {
|
||||
if (queryBody) {
|
||||
this.hasValidQuery = true;
|
||||
this.prepareDialogForNewSearch(queryBody);
|
||||
this.queryBuilderService.execute(queryBody);
|
||||
} else {
|
||||
this.hasValidQuery = false;
|
||||
this.resetFolderToShow();
|
||||
this.clearSearch();
|
||||
}
|
||||
});
|
||||
this.queryBuilderService.updated.pipe(takeUntil(this.onDestroy$)).subscribe((searchRequest) => {
|
||||
if (searchRequest) {
|
||||
this.hasValidQuery = true;
|
||||
this.prepareDialogForNewSearch(searchRequest);
|
||||
this.queryBuilderService.execute(searchRequest);
|
||||
} else {
|
||||
this.hasValidQuery = false;
|
||||
this.resetFolderToShow();
|
||||
this.clearSearch();
|
||||
}
|
||||
});
|
||||
|
||||
this.queryBuilderService.executed
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe((results: NodePaging) => {
|
||||
if (this.hasValidQuery) {
|
||||
this.showSearchResults(results);
|
||||
}
|
||||
});
|
||||
this.queryBuilderService.executed.pipe(takeUntil(this.onDestroy$)).subscribe((results: NodePaging) => {
|
||||
if (this.hasValidQuery) {
|
||||
this.showSearchResults(results);
|
||||
}
|
||||
});
|
||||
|
||||
this.userPreferencesService
|
||||
.select(UserPreferenceValues.PaginationSize)
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(pagSize => this.pageSize = pagSize);
|
||||
.subscribe((pagSize) => (this.pageSize = pagSize));
|
||||
|
||||
this.target = this.documentList;
|
||||
this.folderIdToShow = this.currentFolderId;
|
||||
@ -360,11 +344,9 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
|
||||
this.resetPagination();
|
||||
this.setSearchScopeToNodes();
|
||||
|
||||
this.documentList.$folderNode
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe((currentNode: Node) => {
|
||||
this.documentList.$folderNode.pipe(takeUntil(this.onDestroy$)).subscribe((currentNode: Node) => {
|
||||
this.currentFolder.emit(currentNode);
|
||||
});
|
||||
});
|
||||
|
||||
this.sorting = this.appConfigService.get('adf-content-node-selector.sorting', ['createdAt', 'desc']);
|
||||
}
|
||||
@ -384,10 +366,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
|
||||
|
||||
private onFileUploadEvent() {
|
||||
this.uploadService.fileUploadComplete
|
||||
.pipe(
|
||||
debounceTime(500),
|
||||
takeUntil(this.onDestroy$)
|
||||
)
|
||||
.pipe(debounceTime(500), takeUntil(this.onDestroy$))
|
||||
.subscribe((fileUploadEvent: FileUploadCompleteEvent) => {
|
||||
this.currentUploadBatch.push(fileUploadEvent.data);
|
||||
if (!this.uploadService.isUploading()) {
|
||||
@ -399,12 +378,10 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
private onFileUploadDeletedEvent() {
|
||||
this.uploadService.fileUploadDeleted
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe((deletedFileEvent: FileUploadDeleteEvent) => {
|
||||
this.documentList.unselectRowFromNodeId(deletedFileEvent.file.data.entry.id);
|
||||
this.documentList.reloadWithoutResettingSelection();
|
||||
});
|
||||
this.uploadService.fileUploadDeleted.pipe(takeUntil(this.onDestroy$)).subscribe((deletedFileEvent: FileUploadDeleteEvent) => {
|
||||
this.documentList.unselectRowFromNodeId(deletedFileEvent.file.data.entry.id);
|
||||
this.documentList.reloadWithoutResettingSelection();
|
||||
});
|
||||
}
|
||||
|
||||
private getStartSite() {
|
||||
@ -424,19 +401,14 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
|
||||
if (!filter) {
|
||||
filter = () => true;
|
||||
}
|
||||
this._rowFilter = (value: ShareDataRow, index: number, array: ShareDataRow[]) => filter(value, index, array) &&
|
||||
!this.isExcludedSiteContent(value);
|
||||
this._rowFilter = (value: ShareDataRow, index: number, array: ShareDataRow[]) =>
|
||||
filter(value, index, array) && !this.isExcludedSiteContent(value);
|
||||
}
|
||||
|
||||
private isExcludedSiteContent(row: ShareDataRow): boolean {
|
||||
const entry = row.node.entry;
|
||||
if (this._excludeSiteContent && this._excludeSiteContent.length &&
|
||||
entry &&
|
||||
entry.properties &&
|
||||
entry.properties['st:componentId']) {
|
||||
const excludedItem = this._excludeSiteContent.find(
|
||||
(id: string) => entry.properties['st:componentId'] === id
|
||||
);
|
||||
if (this._excludeSiteContent && this._excludeSiteContent.length && entry && entry.properties && entry.properties['st:componentId']) {
|
||||
const excludedItem = this._excludeSiteContent.find((id: string) => entry.properties['st:componentId'] === id);
|
||||
return !!excludedItem;
|
||||
}
|
||||
return false;
|
||||
@ -472,8 +444,8 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
|
||||
/**
|
||||
* Prepares the dialog for a new search
|
||||
*/
|
||||
prepareDialogForNewSearch(queryBody: QueryBody): void {
|
||||
this.target = queryBody ? null : this.documentList;
|
||||
prepareDialogForNewSearch(searchRequest: SearchRequest): void {
|
||||
this.target = searchRequest ? null : this.documentList;
|
||||
if (this.target) {
|
||||
this.infinitePaginationComponent.reset();
|
||||
}
|
||||
@ -516,18 +488,17 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
|
||||
let extraParentFiltering = '';
|
||||
|
||||
if (this.customResourcesService.hasCorrespondingNodeIds(this.siteId)) {
|
||||
this.customResourcesService.getCorrespondingNodeIds(this.siteId)
|
||||
.subscribe((nodeIds) => {
|
||||
if (nodeIds && nodeIds.length) {
|
||||
nodeIds
|
||||
.filter((id) => id !== this.siteId)
|
||||
.forEach((extraId) => {
|
||||
extraParentFiltering += ` OR ANCESTOR:'workspace://SpacesStore/${extraId}'`;
|
||||
});
|
||||
}
|
||||
const parentFiltering = this.siteId ? `ANCESTOR:'workspace://SpacesStore/${this.siteId}'${extraParentFiltering}` : '';
|
||||
this.queryBuilderService.addFilterQuery(parentFiltering);
|
||||
});
|
||||
this.customResourcesService.getCorrespondingNodeIds(this.siteId).subscribe((nodeIds) => {
|
||||
if (nodeIds && nodeIds.length) {
|
||||
nodeIds
|
||||
.filter((id) => id !== this.siteId)
|
||||
.forEach((extraId) => {
|
||||
extraParentFiltering += ` OR ANCESTOR:'workspace://SpacesStore/${extraId}'`;
|
||||
});
|
||||
}
|
||||
const parentFiltering = this.siteId ? `ANCESTOR:'workspace://SpacesStore/${this.siteId}'${extraParentFiltering}` : '';
|
||||
this.queryBuilderService.addFilterQuery(parentFiltering);
|
||||
});
|
||||
} else {
|
||||
const parentFiltering = this.siteId ? `ANCESTOR:'workspace://SpacesStore/${this.siteId}'` : '';
|
||||
this.queryBuilderService.addFilterQuery(parentFiltering);
|
||||
@ -638,7 +609,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
|
||||
onCurrentSelection(nodesEntries: NodeEntry[]): void {
|
||||
const validNodesEntity = nodesEntries.filter((node) => this.isSelectionValid(node.entry));
|
||||
this.chosenNode = validNodesEntity.map((node) => node.entry);
|
||||
this.selectionWithoutValidation = nodesEntries.map(node => node.entry);
|
||||
this.selectionWithoutValidation = nodesEntries.map((node) => node.entry);
|
||||
}
|
||||
|
||||
setTitleIfCustomSite(site: SiteEntry) {
|
||||
|
@ -15,9 +15,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { QueryBody } from '@alfresco/js-api';
|
||||
import { SearchRequest } from '@alfresco/js-api';
|
||||
|
||||
export const mockQueryBody: QueryBody = {
|
||||
export const mockSearchRequest = {
|
||||
query: {
|
||||
query: '(search-term*)',
|
||||
language: 'afts'
|
||||
@ -38,4 +38,4 @@ export const mockQueryBody: QueryBody = {
|
||||
},
|
||||
highlight: null,
|
||||
facetFormat: 'V2'
|
||||
} as QueryBody;
|
||||
} as SearchRequest;
|
||||
|
@ -17,13 +17,13 @@
|
||||
|
||||
import { Component, ViewChild } from '@angular/core';
|
||||
import { SearchComponent } from '../search/components/search.component';
|
||||
import { QueryBody, ResultSetPaging } from '@alfresco/js-api';
|
||||
import { SearchRequest, ResultSetPaging } from '@alfresco/js-api';
|
||||
|
||||
const entryItem = {
|
||||
entry: {
|
||||
id: '123',
|
||||
name: 'MyDoc',
|
||||
isFile : true,
|
||||
isFile: true,
|
||||
content: {
|
||||
mimeType: 'text/plain'
|
||||
},
|
||||
@ -40,7 +40,7 @@ const entryDifferentItem = {
|
||||
entry: {
|
||||
id: '999',
|
||||
name: 'TEST_DOC',
|
||||
isFile : true,
|
||||
isFile: true,
|
||||
content: {
|
||||
mimeType: 'text/plain'
|
||||
},
|
||||
@ -55,27 +55,19 @@ const entryDifferentItem = {
|
||||
|
||||
export const result = new ResultSetPaging({
|
||||
list: {
|
||||
entries: [
|
||||
entryItem
|
||||
]
|
||||
entries: [entryItem]
|
||||
}
|
||||
});
|
||||
|
||||
export const differentResult = new ResultSetPaging({
|
||||
list: {
|
||||
entries: [
|
||||
entryDifferentItem
|
||||
]
|
||||
entries: [entryDifferentItem]
|
||||
}
|
||||
});
|
||||
|
||||
export const results = {
|
||||
list: {
|
||||
entries: [
|
||||
entryItem,
|
||||
entryItem,
|
||||
entryItem
|
||||
]
|
||||
entries: [entryItem, entryItem, entryItem]
|
||||
}
|
||||
};
|
||||
|
||||
@ -86,8 +78,8 @@ export const folderResult = {
|
||||
entry: {
|
||||
id: '123',
|
||||
name: 'MyFolder',
|
||||
isFile : false,
|
||||
isFolder : true,
|
||||
isFile: false,
|
||||
isFolder: true,
|
||||
createdByUser: {
|
||||
displayName: 'John Doe'
|
||||
},
|
||||
@ -118,35 +110,36 @@ export const errorJson = {
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<adf-search [searchTerm]="searchedWord" [maxResults]="maxResults"
|
||||
(error)="showSearchResult('ERROR')"
|
||||
(success)="showSearchResult('success')" #search>
|
||||
<ng-template let-data>
|
||||
<ul id="autocomplete-search-result-list">
|
||||
<li *ngFor="let item of data?.list?.entries; let idx = index" (click)="elementClicked(item)">
|
||||
<div id="result_option_{{idx}}">
|
||||
<span>{{ item?.entry.name }}</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</ng-template>
|
||||
</adf-search>
|
||||
<span id="component-result-message">{{message}}</span>
|
||||
<adf-search
|
||||
[searchTerm]="searchedWord"
|
||||
[maxResults]="maxResults"
|
||||
(error)="showSearchResult('ERROR')"
|
||||
(success)="showSearchResult('success')"
|
||||
#search
|
||||
>
|
||||
<ng-template let-data>
|
||||
<ul id="autocomplete-search-result-list">
|
||||
<li *ngFor="let item of data?.list?.entries; let idx = index" (click)="elementClicked()">
|
||||
<div id="result_option_{{ idx }}">
|
||||
<span>{{ item?.entry.name }}</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</ng-template>
|
||||
</adf-search>
|
||||
<span id="component-result-message">{{ message }}</span>
|
||||
`
|
||||
})
|
||||
|
||||
export class SimpleSearchTestComponent {
|
||||
|
||||
})
|
||||
export class SimpleSearchTestComponent {
|
||||
@ViewChild('search', { static: true })
|
||||
search: SearchComponent;
|
||||
|
||||
message: string = '';
|
||||
searchedWord = '';
|
||||
maxResults: number = 5;
|
||||
searchNode: QueryBody;
|
||||
searchNode: SearchRequest;
|
||||
|
||||
constructor() {
|
||||
}
|
||||
constructor() {}
|
||||
|
||||
showSearchResult(event: any) {
|
||||
this.message = event;
|
||||
@ -160,7 +153,7 @@ export const errorJson = {
|
||||
this.searchedWord = str;
|
||||
}
|
||||
|
||||
setSearchNodeTo(searchNode: QueryBody) {
|
||||
setSearchNodeTo(searchNode: SearchRequest) {
|
||||
this.searchNode = searchNode;
|
||||
}
|
||||
|
||||
@ -171,5 +164,4 @@ export const errorJson = {
|
||||
forceHidePanel() {
|
||||
this.search.hidePanel();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { QueryBody } from '@alfresco/js-api';
|
||||
import { SearchRequest } from '@alfresco/js-api';
|
||||
import { Injectable, Optional, Inject, InjectionToken } from '@angular/core';
|
||||
import { SearchConfigurationInterface } from '../../../common/interfaces/search-configuration.interface';
|
||||
|
||||
@ -26,15 +26,14 @@ export interface QueryProvider {
|
||||
|
||||
@Injectable()
|
||||
export class SearchPermissionConfigurationService implements SearchConfigurationInterface {
|
||||
|
||||
constructor(
|
||||
@Optional()
|
||||
@Inject(SEARCH_QUERY_TOKEN)
|
||||
private queryProvider: QueryProvider) {
|
||||
}
|
||||
private queryProvider: QueryProvider
|
||||
) {}
|
||||
|
||||
public generateQueryBody(searchTerm: string, maxResults: number, skipCount: number): QueryBody {
|
||||
const defaultQueryBody: QueryBody = {
|
||||
public generateQueryBody(searchTerm: string, maxResults: number, skipCount: number): SearchRequest {
|
||||
return new SearchRequest({
|
||||
query: {
|
||||
query: this.getQuery(searchTerm)
|
||||
},
|
||||
@ -45,17 +44,15 @@ export class SearchPermissionConfigurationService implements SearchConfiguration
|
||||
},
|
||||
filterQueries: [
|
||||
/* eslint-disable-next-line */
|
||||
{ query: "TYPE:'cm:authority'" }]
|
||||
};
|
||||
|
||||
return defaultQueryBody;
|
||||
{ query: "TYPE:'cm:authority'" }
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
private getQuery(searchTerm: string) {
|
||||
let query: string;
|
||||
if (this.queryProvider && this.queryProvider.query) {
|
||||
query = this.queryProvider.query.replace(
|
||||
new RegExp(/\${([^}]+)}/g), searchTerm);
|
||||
query = this.queryProvider.query.replace(new RegExp(/\${([^}]+)}/g), searchTerm);
|
||||
} else {
|
||||
query = `(email:*${searchTerm}* OR firstName:*${searchTerm}* OR lastName:*${searchTerm}* OR displayName:*${searchTerm}* OR authorityName:*${searchTerm}* OR authorityDisplayName:*${searchTerm}*) AND ANAME:(\"0/APP.DEFAULT\")`;
|
||||
}
|
||||
|
@ -15,21 +15,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
AlfrescoApiService,
|
||||
TranslationService
|
||||
} from '@alfresco/adf-core';
|
||||
import { AlfrescoApiService, TranslationService } from '@alfresco/adf-core';
|
||||
import { NodesApiService } from '../../common/services/nodes-api.service';
|
||||
import { EcmUserModel } from '../../common/models/ecm-user.model';
|
||||
import {
|
||||
Group,
|
||||
GroupMemberEntry,
|
||||
GroupMemberPaging, GroupsApi,
|
||||
Node,
|
||||
PathElement,
|
||||
PermissionElement,
|
||||
QueryBody
|
||||
} from '@alfresco/js-api';
|
||||
import { Group, GroupMemberEntry, GroupMemberPaging, GroupsApi, Node, PathElement, PermissionElement, SearchRequest } from '@alfresco/js-api';
|
||||
import { SearchService } from '../../search/services/search.service';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { forkJoin, from, Observable, of, throwError } from 'rxjs';
|
||||
@ -41,18 +30,18 @@ import { RoleModel } from '../models/role.model';
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class NodePermissionService {
|
||||
|
||||
private _groupsApi: GroupsApi;
|
||||
get groupsApi(): GroupsApi {
|
||||
this._groupsApi = this._groupsApi ?? new GroupsApi(this.apiService.getInstance());
|
||||
return this._groupsApi;
|
||||
}
|
||||
|
||||
constructor(private apiService: AlfrescoApiService,
|
||||
private searchApiService: SearchService,
|
||||
private nodeService: NodesApiService,
|
||||
private translation: TranslationService) {
|
||||
}
|
||||
constructor(
|
||||
private apiService: AlfrescoApiService,
|
||||
private searchApiService: SearchService,
|
||||
private nodeService: NodesApiService,
|
||||
private translation: TranslationService
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Gets a list of roles for the current node.
|
||||
@ -61,20 +50,23 @@ export class NodePermissionService {
|
||||
* @returns Array of strings representing the roles
|
||||
*/
|
||||
getNodeRoles(node: Node): Observable<string[]> {
|
||||
const retrieveSiteQueryBody: QueryBody = this.buildRetrieveSiteQueryBody(node.path.elements);
|
||||
return this.searchApiService.searchByQueryBody(retrieveSiteQueryBody)
|
||||
.pipe(
|
||||
switchMap((siteNodeList: any) => {
|
||||
if (siteNodeList.list.entries.length > 0) {
|
||||
const siteName = siteNodeList.list.entries[0].entry.name;
|
||||
return this.getGroupMembersBySiteName(siteName);
|
||||
} else {
|
||||
return of(node.permissions?.settable);
|
||||
}
|
||||
})
|
||||
);
|
||||
const searchRequest = this.buildRetrieveSiteQueryBody(node.path.elements);
|
||||
return this.searchApiService.searchByQueryBody(searchRequest).pipe(
|
||||
switchMap((siteNodeList: any) => {
|
||||
if (siteNodeList.list.entries.length > 0) {
|
||||
const siteName = siteNodeList.list.entries[0].entry.name;
|
||||
return this.getGroupMembersBySiteName(siteName);
|
||||
} else {
|
||||
return of(node.permissions?.settable);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get permissions for a given node
|
||||
* @param node Node to check permissions for
|
||||
*/
|
||||
getNodePermissions(node: Node): PermissionDisplayModel[] {
|
||||
const result: PermissionDisplayModel[] = [];
|
||||
|
||||
@ -121,9 +113,7 @@ export class NodePermissionService {
|
||||
* @returns Node with updated permissions
|
||||
*/
|
||||
updateNodePermissions(nodeId: string, permissionList: PermissionElement[]): Observable<Node> {
|
||||
return this.nodeService.getNode(nodeId).pipe(
|
||||
switchMap((node) => this.updateLocallySetPermissions(node, permissionList))
|
||||
);
|
||||
return this.nodeService.getNode(nodeId).pipe(switchMap((node) => this.updateLocallySetPermissions(node, permissionList)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -138,7 +128,9 @@ export class NodePermissionService {
|
||||
const permissionList = permissions;
|
||||
const duplicatedPermissions = this.getDuplicatedPermissions(node.permissions.locallySet, permissionList);
|
||||
if (duplicatedPermissions.length > 0) {
|
||||
const list = duplicatedPermissions.map((permission) => 'authority -> ' + permission.authorityId + ' / role -> ' + permission.name).join(', ');
|
||||
const list = duplicatedPermissions
|
||||
.map((permission) => 'authority -> ' + permission.authorityId + ' / role -> ' + permission.name)
|
||||
.join(', ');
|
||||
const duplicatePermissionMessage: string = this.translation.instant('PERMISSION_MANAGER.ERROR.DUPLICATE-PERMISSION', { list });
|
||||
return throwError(duplicatePermissionMessage);
|
||||
}
|
||||
@ -160,9 +152,11 @@ export class NodePermissionService {
|
||||
}
|
||||
|
||||
private isEqualPermission(oldPermission: PermissionElement, newPermission: PermissionElement): boolean {
|
||||
return oldPermission.accessStatus === newPermission.accessStatus &&
|
||||
return (
|
||||
oldPermission.accessStatus === newPermission.accessStatus &&
|
||||
oldPermission.authorityId === newPermission.authorityId &&
|
||||
oldPermission.name === newPermission.name;
|
||||
oldPermission.name === newPermission.name
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -187,16 +181,15 @@ export class NodePermissionService {
|
||||
|
||||
private getGroupMembersBySiteName(siteName: string): Observable<string[]> {
|
||||
const groupName = 'GROUP_site_' + siteName;
|
||||
return this.getGroupMemberByGroupName(groupName)
|
||||
.pipe(
|
||||
map((groupMemberPaging: GroupMemberPaging) => {
|
||||
const displayResult: string[] = [];
|
||||
groupMemberPaging.list.entries.forEach((member: GroupMemberEntry) => {
|
||||
displayResult.push(this.formattedRoleName(member.entry.displayName, 'site_' + siteName));
|
||||
});
|
||||
return displayResult;
|
||||
})
|
||||
);
|
||||
return this.getGroupMemberByGroupName(groupName).pipe(
|
||||
map((groupMemberPaging: GroupMemberPaging) => {
|
||||
const displayResult: string[] = [];
|
||||
groupMemberPaging.list.entries.forEach((member: GroupMemberEntry) => {
|
||||
displayResult.push(this.formattedRoleName(member.entry.displayName, 'site_' + siteName));
|
||||
});
|
||||
return displayResult;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -214,7 +207,7 @@ export class NodePermissionService {
|
||||
return displayName.replace(siteName + '_', '');
|
||||
}
|
||||
|
||||
private buildRetrieveSiteQueryBody(nodePath: PathElement[]): QueryBody {
|
||||
private buildRetrieveSiteQueryBody(nodePath: PathElement[]): SearchRequest {
|
||||
const pathNames = nodePath.map((node: PathElement) => 'name: "' + node.name + '"');
|
||||
const builtPathNames = pathNames.join(' OR ');
|
||||
|
||||
@ -229,8 +222,7 @@ export class NodePermissionService {
|
||||
include: ['aspectNames', 'properties'],
|
||||
filterQueries: [
|
||||
{
|
||||
query:
|
||||
`TYPE:'st:site'`
|
||||
query: `TYPE:'st:site'`
|
||||
}
|
||||
]
|
||||
};
|
||||
@ -302,15 +294,15 @@ export class NodePermissionService {
|
||||
*/
|
||||
getNodeWithRoles(nodeId: string): Observable<{ node: Node; roles: RoleModel[] }> {
|
||||
return this.nodeService.getNode(nodeId).pipe(
|
||||
switchMap(node => forkJoin({
|
||||
node: of(node),
|
||||
roles: this.getNodeRoles(node)
|
||||
.pipe(
|
||||
switchMap((node) =>
|
||||
forkJoin({
|
||||
node: of(node),
|
||||
roles: this.getNodeRoles(node).pipe(
|
||||
catchError(() => of(node.permissions?.settable)),
|
||||
map(_roles => _roles.map(role => ({ role, label: role }))
|
||||
)
|
||||
map((_roles) => _roles.map((role) => ({ role, label: role })))
|
||||
)
|
||||
}))
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ import { Injectable } from '@angular/core';
|
||||
import { Subject, Observable, from, ReplaySubject } from 'rxjs';
|
||||
import { AlfrescoApiService, AppConfigService } from '@alfresco/adf-core';
|
||||
import {
|
||||
QueryBody,
|
||||
SearchRequest,
|
||||
RequestFacetFields,
|
||||
RequestSortDefinitionInner,
|
||||
ResultSetPaging,
|
||||
@ -41,7 +41,6 @@ import { SearchForm } from '../models/search-form.interface';
|
||||
providedIn: 'root'
|
||||
})
|
||||
export abstract class BaseQueryBuilderService {
|
||||
|
||||
private _searchApi: SearchApi;
|
||||
get searchApi(): SearchApi {
|
||||
this._searchApi = this._searchApi ?? new SearchApi(this.alfrescoApiService.getInstance());
|
||||
@ -52,7 +51,7 @@ export abstract class BaseQueryBuilderService {
|
||||
configUpdated = new Subject<SearchConfiguration>();
|
||||
|
||||
/* Stream that emits the query before search whenever user search */
|
||||
updated = new Subject<QueryBody>();
|
||||
updated = new Subject<SearchRequest>();
|
||||
|
||||
/* Stream that emits the results whenever user search */
|
||||
executed = new Subject<ResultSetPaging>();
|
||||
@ -152,12 +151,14 @@ export abstract class BaseQueryBuilderService {
|
||||
selected: this.selectedConfiguration !== undefined ? index === this.selectedConfiguration : configuration.default
|
||||
}));
|
||||
} else if (!!configurations) {
|
||||
return [{
|
||||
index: 0,
|
||||
name: configurations.name || 'SEARCH.UNKNOWN_CONFIGURATION',
|
||||
default: true,
|
||||
selected: true
|
||||
}];
|
||||
return [
|
||||
{
|
||||
index: 0,
|
||||
name: configurations.name || 'SEARCH.UNKNOWN_CONFIGURATION',
|
||||
default: true,
|
||||
selected: true
|
||||
}
|
||||
];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
@ -165,9 +166,7 @@ export abstract class BaseQueryBuilderService {
|
||||
private setUpSearchConfiguration(currentConfiguration: SearchConfiguration) {
|
||||
if (currentConfiguration) {
|
||||
this.config = JSON.parse(JSON.stringify(currentConfiguration));
|
||||
this.categories = (this.config.categories || []).filter(
|
||||
category => category.enabled
|
||||
);
|
||||
this.categories = (this.config.categories || []).filter((category) => category.enabled);
|
||||
this.filterQueries = this.config.filterQueries || [];
|
||||
this.userFacetBuckets = {};
|
||||
if (this.config.sorting) {
|
||||
@ -213,8 +212,7 @@ export abstract class BaseQueryBuilderService {
|
||||
removeUserFacetBucket(field: string, bucket: FacetFieldBucket) {
|
||||
if (field && bucket) {
|
||||
const buckets = this.userFacetBuckets[field] || [];
|
||||
this.userFacetBuckets[field] = buckets
|
||||
.filter((facetBucket) => facetBucket.label !== bucket.label);
|
||||
this.userFacetBuckets[field] = buckets.filter((facetBucket) => facetBucket.label !== bucket.label);
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,8 +237,7 @@ export abstract class BaseQueryBuilderService {
|
||||
*/
|
||||
removeFilterQuery(query: string): void {
|
||||
if (query) {
|
||||
this.filterQueries = this.filterQueries
|
||||
.filter((filterQuery) => filterQuery.query !== query);
|
||||
this.filterQueries = this.filterQueries.filter((filterQuery) => filterQuery.query !== query);
|
||||
}
|
||||
}
|
||||
|
||||
@ -289,7 +286,7 @@ export abstract class BaseQueryBuilderService {
|
||||
/**
|
||||
* Builds the current query and triggers the `updated` event.
|
||||
*/
|
||||
update(queryBody?: QueryBody): void {
|
||||
update(queryBody?: SearchRequest): void {
|
||||
const query = queryBody ? queryBody : this.buildQuery();
|
||||
this.updated.next(query);
|
||||
}
|
||||
@ -299,7 +296,7 @@ export abstract class BaseQueryBuilderService {
|
||||
*
|
||||
* @returns Nothing
|
||||
*/
|
||||
async execute(queryBody?: QueryBody) {
|
||||
async execute(queryBody?: SearchRequest) {
|
||||
try {
|
||||
const query = queryBody ? queryBody : this.buildQuery();
|
||||
if (query) {
|
||||
@ -320,7 +317,7 @@ export abstract class BaseQueryBuilderService {
|
||||
}
|
||||
}
|
||||
|
||||
search(queryBody: QueryBody): Observable<ResultSetPaging> {
|
||||
search(queryBody: SearchRequest): Observable<ResultSetPaging> {
|
||||
const promise = this.searchApi.search(queryBody);
|
||||
|
||||
promise.then((resultSetPaging) => {
|
||||
@ -335,7 +332,7 @@ export abstract class BaseQueryBuilderService {
|
||||
*
|
||||
* @returns The finished query
|
||||
*/
|
||||
buildQuery(): QueryBody {
|
||||
buildQuery(): SearchRequest {
|
||||
const query = this.getFinalQuery();
|
||||
|
||||
const include = this.config.include || [];
|
||||
@ -344,8 +341,7 @@ export abstract class BaseQueryBuilderService {
|
||||
}
|
||||
|
||||
if (query) {
|
||||
|
||||
const result: QueryBody = {
|
||||
const result: SearchRequest = {
|
||||
query: {
|
||||
query,
|
||||
language: 'afts'
|
||||
@ -362,7 +358,7 @@ export abstract class BaseQueryBuilderService {
|
||||
};
|
||||
|
||||
if (this.scope) {
|
||||
result['scope'] = this.scope;
|
||||
result.scope = this.scope;
|
||||
}
|
||||
|
||||
result['facetFormat'] = 'V2';
|
||||
@ -412,10 +408,7 @@ export abstract class BaseQueryBuilderService {
|
||||
* @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) {
|
||||
if (this.config && this.config.facetQueries && this.config.facetQueries.queries && this.config.facetQueries.queries.length > 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -427,11 +420,7 @@ export abstract class BaseQueryBuilderService {
|
||||
* @returns True if defined, false otherwise
|
||||
*/
|
||||
get hasFacetIntervals(): boolean {
|
||||
return this.config
|
||||
&& this.config.facetIntervals
|
||||
&& this.config.facetIntervals.intervals
|
||||
&& this.config.facetIntervals.intervals.length > 0;
|
||||
|
||||
return this.config && this.config.facetIntervals && this.config.facetIntervals.intervals && this.config.facetIntervals.intervals.length > 0;
|
||||
}
|
||||
|
||||
get hasFacetHighlight(): boolean {
|
||||
@ -439,11 +428,14 @@ export abstract class BaseQueryBuilderService {
|
||||
}
|
||||
|
||||
protected get sort(): RequestSortDefinitionInner[] {
|
||||
return this.sorting.map((def) => new RequestSortDefinitionInner({
|
||||
type: def.type,
|
||||
field: def.field,
|
||||
ascending: def.ascending
|
||||
}));
|
||||
return this.sorting.map(
|
||||
(def) =>
|
||||
new RequestSortDefinitionInner({
|
||||
type: def.type,
|
||||
field: def.field,
|
||||
ascending: def.ascending
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
protected get facetQueries(): FacetQuery[] {
|
||||
@ -462,17 +454,23 @@ export abstract class BaseQueryBuilderService {
|
||||
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
|
||||
} as any))
|
||||
} as any))
|
||||
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
|
||||
} as any)
|
||||
)
|
||||
} as any)
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
@ -496,9 +494,7 @@ export abstract class BaseQueryBuilderService {
|
||||
}
|
||||
});
|
||||
|
||||
let result = [this.userQuery, query]
|
||||
.filter((entry) => entry)
|
||||
.join(' AND ');
|
||||
let result = [this.userQuery, query].filter((entry) => entry).join(' AND ');
|
||||
|
||||
if (this.userFacetBuckets) {
|
||||
Object.keys(this.userFacetBuckets).forEach((key) => {
|
||||
@ -523,14 +519,17 @@ export abstract class BaseQueryBuilderService {
|
||||
|
||||
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
|
||||
} as any))
|
||||
facets: facetFields.map(
|
||||
(facet) =>
|
||||
({
|
||||
field: facet.field,
|
||||
mincount: facet.mincount,
|
||||
label: this.getSupportedLabel(facet.label),
|
||||
limit: facet.limit,
|
||||
offset: facet.offset,
|
||||
prefix: facet.prefix
|
||||
} as any)
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -16,24 +16,23 @@
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { QueryBody } from '@alfresco/js-api';
|
||||
import { SearchRequest } from '@alfresco/js-api';
|
||||
import { SearchConfigurationInterface } from '../../common/interfaces/search-configuration.interface';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SearchConfigurationService implements SearchConfigurationInterface {
|
||||
|
||||
/**
|
||||
* Generates a QueryBody object with custom search parameters.
|
||||
* Generates a request object with custom search parameters.
|
||||
*
|
||||
* @param searchTerm Term text to search for
|
||||
* @param maxResults Maximum number of search results to show in a page
|
||||
* @param skipCount The offset of the start of the page within the results list
|
||||
* @returns Query body defined by the parameters
|
||||
*/
|
||||
generateQueryBody(searchTerm: string, maxResults: number, skipCount: number): QueryBody {
|
||||
const defaultQueryBody: QueryBody = {
|
||||
generateQueryBody(searchTerm: string, maxResults: number, skipCount: number): SearchRequest {
|
||||
return new SearchRequest({
|
||||
query: {
|
||||
query: searchTerm ? `'${searchTerm}*' OR name:'${searchTerm}*'` : searchTerm
|
||||
},
|
||||
@ -42,11 +41,7 @@ export class SearchConfigurationService implements SearchConfigurationInterface
|
||||
maxItems: maxResults,
|
||||
skipCount
|
||||
},
|
||||
filterQueries: [
|
||||
{ query: `TYPE:'cm:folder' OR TYPE:'cm:content'` },
|
||||
{ query: 'NOT cm:creator:System' }]
|
||||
};
|
||||
|
||||
return defaultQueryBody;
|
||||
filterQueries: [{ query: `TYPE:'cm:folder' OR TYPE:'cm:content'` }, { query: 'NOT cm:creator:System' }]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ import { TestBed } from '@angular/core/testing';
|
||||
import { ContentTestingModule } from '../../testing/content.testing.module';
|
||||
|
||||
describe('SearchQueryBuilder', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ContentTestingModule]
|
||||
@ -38,14 +37,8 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should reset to defaults', () => {
|
||||
const config: SearchConfiguration = {
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any,
|
||||
{ id: 'cat2', enabled: true } as any
|
||||
],
|
||||
filterQueries: [
|
||||
{ query: 'query1' },
|
||||
{ query: 'query2' }
|
||||
]
|
||||
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any],
|
||||
filterQueries: [{ query: 'query1' }, { query: 'query2' }]
|
||||
};
|
||||
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
|
||||
@ -86,11 +79,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should use only enabled categories', () => {
|
||||
const config: SearchConfiguration = {
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any,
|
||||
{ id: 'cat2', enabled: false } as any,
|
||||
{ id: 'cat3', enabled: true } as any
|
||||
]
|
||||
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: false } as any, { id: 'cat3', enabled: true } as any]
|
||||
};
|
||||
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
|
||||
@ -104,10 +93,7 @@ describe('SearchQueryBuilder', () => {
|
||||
it('should fetch filter queries from config', () => {
|
||||
const config: SearchConfiguration = {
|
||||
categories: [],
|
||||
filterQueries: [
|
||||
{ query: 'query1' },
|
||||
{ query: 'query2' }
|
||||
]
|
||||
filterQueries: [{ query: 'query1' }, { query: 'query2' }]
|
||||
};
|
||||
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
|
||||
@ -202,9 +188,7 @@ describe('SearchQueryBuilder', () => {
|
||||
const config: SearchConfiguration = {
|
||||
categories: [],
|
||||
facetQueries: {
|
||||
queries: [
|
||||
{ query: 'q1', label: 'query1' }
|
||||
]
|
||||
queries: [{ query: 'q1', label: 'query1' }]
|
||||
}
|
||||
};
|
||||
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
@ -259,9 +243,7 @@ describe('SearchQueryBuilder', () => {
|
||||
const config: SearchConfiguration = {
|
||||
categories: [],
|
||||
facetFields: {
|
||||
fields: [
|
||||
{ field: 'content.size', mincount: 1, label: 'Label with spaces' }
|
||||
]
|
||||
fields: [{ field: 'content.size', mincount: 1, label: 'Label with spaces' }]
|
||||
}
|
||||
};
|
||||
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
@ -275,9 +257,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should require a query fragment to build query', () => {
|
||||
const config: SearchConfiguration = {
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any
|
||||
]
|
||||
categories: [{ id: 'cat1', enabled: true } as any]
|
||||
};
|
||||
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
|
||||
@ -290,9 +270,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should build query with single fragment', () => {
|
||||
const config: SearchConfiguration = {
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any
|
||||
]
|
||||
categories: [{ id: 'cat1', enabled: true } as any]
|
||||
};
|
||||
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
|
||||
@ -306,10 +284,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should build query with multiple fragments', () => {
|
||||
const config: SearchConfiguration = {
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any,
|
||||
{ id: 'cat2', enabled: true } as any
|
||||
]
|
||||
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any]
|
||||
};
|
||||
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
|
||||
@ -319,18 +294,13 @@ describe('SearchQueryBuilder', () => {
|
||||
builder.queryFragments['cat2'] = 'NOT cm:creator:System';
|
||||
|
||||
const compiled = builder.buildQuery();
|
||||
expect(compiled.query.query).toBe(
|
||||
'(cm:name:test) AND (NOT cm:creator:System)'
|
||||
);
|
||||
expect(compiled.query.query).toBe('(cm:name:test) AND (NOT cm:creator:System)');
|
||||
});
|
||||
|
||||
it('should build query with custom fields', () => {
|
||||
const config: SearchConfiguration = {
|
||||
fields: ['field1', 'field2'],
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any,
|
||||
{ id: 'cat2', enabled: true } as any
|
||||
]
|
||||
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any]
|
||||
};
|
||||
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
|
||||
@ -345,10 +315,7 @@ describe('SearchQueryBuilder', () => {
|
||||
it('should build query with empty custom fields', () => {
|
||||
const config: SearchConfiguration = {
|
||||
fields: [],
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any,
|
||||
{ id: 'cat2', enabled: true } as any
|
||||
]
|
||||
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any]
|
||||
};
|
||||
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
|
||||
@ -362,9 +329,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should build query with custom filter queries', () => {
|
||||
const config: SearchConfiguration = {
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any
|
||||
]
|
||||
categories: [{ id: 'cat1', enabled: true } as any]
|
||||
};
|
||||
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
|
||||
@ -373,20 +338,14 @@ describe('SearchQueryBuilder', () => {
|
||||
builder.addFilterQuery('query1');
|
||||
|
||||
const compiled = builder.buildQuery();
|
||||
expect(compiled.filterQueries).toEqual(
|
||||
[{ query: 'query1' }]
|
||||
);
|
||||
expect(compiled.filterQueries).toEqual([{ query: 'query1' }]);
|
||||
});
|
||||
|
||||
it('should build query with custom facet queries', () => {
|
||||
const config: SearchConfiguration = {
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any
|
||||
],
|
||||
categories: [{ id: 'cat1', enabled: true } as any],
|
||||
facetQueries: {
|
||||
queries: [
|
||||
{ query: 'q1', label: 'q2', group: 'group-name' }
|
||||
]
|
||||
queries: [{ query: 'q1', label: 'q2', group: 'group-name' }]
|
||||
}
|
||||
};
|
||||
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
@ -400,9 +359,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should build query with custom facet fields', () => {
|
||||
const config: SearchConfiguration = {
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any
|
||||
],
|
||||
categories: [{ id: 'cat1', enabled: true } as any],
|
||||
facetFields: {
|
||||
fields: [
|
||||
{ field: 'field1', label: 'field1', mincount: 1, limit: null, offset: 0, prefix: null },
|
||||
@ -430,9 +387,7 @@ describe('SearchQueryBuilder', () => {
|
||||
};
|
||||
|
||||
const config: SearchConfiguration = {
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any
|
||||
],
|
||||
categories: [{ id: 'cat1', enabled: true } as any],
|
||||
facetFields: {
|
||||
fields: [
|
||||
{
|
||||
@ -468,9 +423,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should build query with custom facet intervals', () => {
|
||||
const config: SearchConfiguration = {
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any
|
||||
],
|
||||
categories: [{ id: 'cat1', enabled: true } as any],
|
||||
facetIntervals: {
|
||||
intervals: [
|
||||
{
|
||||
@ -516,9 +469,7 @@ describe('SearchQueryBuilder', () => {
|
||||
};
|
||||
|
||||
const config: SearchConfiguration = {
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any
|
||||
],
|
||||
categories: [{ id: 'cat1', enabled: true } as any],
|
||||
facetIntervals: {
|
||||
intervals: [
|
||||
{
|
||||
@ -557,10 +508,7 @@ describe('SearchQueryBuilder', () => {
|
||||
it('should build query with sorting', () => {
|
||||
const config: SearchConfiguration = {
|
||||
fields: [],
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any,
|
||||
{ id: 'cat2', enabled: true } as any
|
||||
]
|
||||
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any]
|
||||
};
|
||||
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
|
||||
@ -575,9 +523,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should use pagination settings', () => {
|
||||
const config: SearchConfiguration = {
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any
|
||||
]
|
||||
categories: [{ id: 'cat1', enabled: true } as any]
|
||||
};
|
||||
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
|
||||
@ -593,9 +539,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should build final request with user and custom queries', () => {
|
||||
const config: SearchConfiguration = {
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any
|
||||
]
|
||||
categories: [{ id: 'cat1', enabled: true } as any]
|
||||
};
|
||||
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
|
||||
@ -629,9 +573,7 @@ describe('SearchQueryBuilder', () => {
|
||||
];
|
||||
|
||||
const config: SearchConfiguration = {
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any
|
||||
]
|
||||
categories: [{ id: 'cat1', enabled: true } as any]
|
||||
};
|
||||
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
|
||||
@ -671,9 +613,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should emit error event', () => {
|
||||
const config: SearchConfiguration = {
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any
|
||||
]
|
||||
categories: [{ id: 'cat1', enabled: true } as any]
|
||||
};
|
||||
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
|
||||
@ -689,9 +629,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should emit empty results on error', (done) => {
|
||||
const config: SearchConfiguration = {
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any
|
||||
]
|
||||
categories: [{ id: 'cat1', enabled: true } as any]
|
||||
};
|
||||
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
|
||||
@ -712,9 +650,9 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
const builder = new SearchQueryBuilderService(buildConfig({}), alfrescoApiService);
|
||||
builder.userQuery = 'nuka cola quantum';
|
||||
const queryBody = builder.buildQuery();
|
||||
const searchRequest = builder.buildQuery();
|
||||
|
||||
expect(queryBody.include).toEqual(['path', 'allowableOperations']);
|
||||
expect(searchRequest.include).toEqual(['path', 'allowableOperations']);
|
||||
});
|
||||
|
||||
it('should fetch the include config from the app config', () => {
|
||||
@ -726,9 +664,9 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
|
||||
builder.userQuery = 'nuka cola quantum';
|
||||
const queryBody = builder.buildQuery();
|
||||
const searchRequest = builder.buildQuery();
|
||||
|
||||
expect(queryBody.include).toEqual(includeConfig);
|
||||
expect(searchRequest.include).toEqual(includeConfig);
|
||||
});
|
||||
|
||||
it('should the query contain the pagination', () => {
|
||||
@ -741,9 +679,9 @@ describe('SearchQueryBuilder', () => {
|
||||
skipCount: 0
|
||||
};
|
||||
builder.paging = mockPagination;
|
||||
const queryBody = builder.buildQuery();
|
||||
const searchRequest = builder.buildQuery();
|
||||
|
||||
expect(queryBody.paging).toEqual(mockPagination);
|
||||
expect(searchRequest.paging).toEqual(mockPagination);
|
||||
});
|
||||
|
||||
it('should the query contain the scope in case it is defined', () => {
|
||||
@ -753,9 +691,9 @@ describe('SearchQueryBuilder', () => {
|
||||
const mockScope = { locations: 'mock-location' };
|
||||
builder.userQuery = 'nuka cola quantum';
|
||||
builder.setScope(mockScope);
|
||||
const queryBody = builder.buildQuery();
|
||||
const searchRequest = builder.buildQuery();
|
||||
|
||||
expect(queryBody.scope).toEqual(mockScope);
|
||||
expect(searchRequest.scope).toEqual(mockScope);
|
||||
});
|
||||
|
||||
it('should return empty if array of search config not found', (done) => {
|
||||
@ -774,32 +712,19 @@ describe('SearchQueryBuilder', () => {
|
||||
beforeEach(() => {
|
||||
configs = [
|
||||
{
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true } as any,
|
||||
{ id: 'cat2', enabled: true } as any
|
||||
],
|
||||
filterQueries: [
|
||||
{ query: 'query1' },
|
||||
{ query: 'query2' }
|
||||
],
|
||||
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any],
|
||||
filterQueries: [{ query: 'query1' }, { query: 'query2' }],
|
||||
name: 'config1',
|
||||
default: true
|
||||
},
|
||||
{
|
||||
categories: [
|
||||
{ id: 'mouse', enabled: true } as any
|
||||
],
|
||||
filterQueries: [
|
||||
{ query: 'query1' },
|
||||
{ query: 'query2' }
|
||||
],
|
||||
categories: [{ id: 'mouse', enabled: true } as any],
|
||||
filterQueries: [{ query: 'query1' }, { query: 'query2' }],
|
||||
name: 'config2',
|
||||
default: false
|
||||
},
|
||||
{
|
||||
categories: [
|
||||
{ id: 'cat_and_mouse', enabled: true } as any
|
||||
],
|
||||
categories: [{ id: 'cat_and_mouse', enabled: true } as any],
|
||||
default: false
|
||||
}
|
||||
];
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { NodePaging, QueriesApi, QueryBody, ResultSetPaging, SearchApi } from '@alfresco/js-api';
|
||||
import { NodePaging, QueriesApi, SearchRequest, ResultSetPaging, SearchApi } from '@alfresco/js-api';
|
||||
import { Observable, Subject, from, throwError } from 'rxjs';
|
||||
import { AlfrescoApiService } from '@alfresco/adf-core';
|
||||
import { SearchConfigurationService } from './search-configuration.service';
|
||||
@ -25,7 +25,6 @@ import { SearchConfigurationService } from './search-configuration.service';
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SearchService {
|
||||
|
||||
dataLoaded: Subject<ResultSetPaging> = new Subject();
|
||||
|
||||
private _queriesApi: QueriesApi;
|
||||
@ -40,9 +39,7 @@ export class SearchService {
|
||||
return this._searchApi;
|
||||
}
|
||||
|
||||
constructor(private apiService: AlfrescoApiService,
|
||||
private searchConfigurationService: SearchConfigurationService) {
|
||||
}
|
||||
constructor(private apiService: AlfrescoApiService, private searchConfigurationService: SearchConfigurationService) {}
|
||||
|
||||
/**
|
||||
* Gets a list of nodes that match the given search criteria.
|
||||
@ -54,9 +51,11 @@ export class SearchService {
|
||||
getNodeQueryResults(term: string, options?: SearchOptions): Observable<NodePaging> {
|
||||
const promise = this.queriesApi.findNodes(term, options);
|
||||
|
||||
promise.then((nodePaging: NodePaging) => {
|
||||
this.dataLoaded.next(nodePaging);
|
||||
}).catch((err) => this.handleError(err));
|
||||
promise
|
||||
.then((nodePaging) => {
|
||||
this.dataLoaded.next(nodePaging);
|
||||
})
|
||||
.catch((err) => this.handleError(err));
|
||||
|
||||
return from(promise);
|
||||
}
|
||||
@ -70,28 +69,32 @@ export class SearchService {
|
||||
* @returns List of search results
|
||||
*/
|
||||
search(searchTerm: string, maxResults: number, skipCount: number): Observable<ResultSetPaging> {
|
||||
const searchQuery = Object.assign(this.searchConfigurationService.generateQueryBody(searchTerm, maxResults, skipCount));
|
||||
const searchQuery = this.searchConfigurationService.generateQueryBody(searchTerm, maxResults, skipCount);
|
||||
const promise = this.searchApi.search(searchQuery);
|
||||
|
||||
promise.then((nodePaging: NodePaging) => {
|
||||
this.dataLoaded.next(nodePaging);
|
||||
}).catch((err) => this.handleError(err));
|
||||
promise
|
||||
.then((nodePaging) => {
|
||||
this.dataLoaded.next(nodePaging);
|
||||
})
|
||||
.catch((err) => this.handleError(err));
|
||||
|
||||
return from(promise);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a search with its parameters supplied by a QueryBody object.
|
||||
* Performs a search with its parameters supplied by a request object.
|
||||
*
|
||||
* @param queryBody Object containing the search parameters
|
||||
* @returns List of search results
|
||||
*/
|
||||
searchByQueryBody(queryBody: QueryBody): Observable<ResultSetPaging> {
|
||||
searchByQueryBody(queryBody: SearchRequest): Observable<ResultSetPaging> {
|
||||
const promise = this.searchApi.search(queryBody);
|
||||
|
||||
promise.then((nodePaging: NodePaging) => {
|
||||
this.dataLoaded.next(nodePaging);
|
||||
}).catch((err) => this.handleError(err));
|
||||
promise
|
||||
.then((nodePaging) => {
|
||||
this.dataLoaded.next(nodePaging);
|
||||
})
|
||||
.catch((err) => this.handleError(err));
|
||||
|
||||
return from(promise);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user