mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ADF-2189] new search facets (#3230)
* slider facet * number range facet * unit tests * remove fdescribe * remove old demo-only content * remove old tests * Support "include" and "field" values with app config * exclude deprecated demo content from export checks
This commit is contained in:
committed by
Eugenio Romano
parent
b7fc44d576
commit
3a51c27f66
@@ -53,6 +53,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"search": {
|
"search": {
|
||||||
|
"include": ["path", "allowableOperations"],
|
||||||
|
"fields": [],
|
||||||
"filterQueries": [
|
"filterQueries": [
|
||||||
{ "query": "TYPE:'cm:folder' OR TYPE:'cm:content'" },
|
{ "query": "TYPE:'cm:folder' OR TYPE:'cm:content'" },
|
||||||
{ "query": "NOT cm:creator:System" }
|
{ "query": "NOT cm:creator:System" }
|
||||||
@@ -78,85 +80,62 @@
|
|||||||
"query": {
|
"query": {
|
||||||
"categories": [
|
"categories": [
|
||||||
{
|
{
|
||||||
"id": "broken",
|
"id": "queryName",
|
||||||
"name": "Broken Facet",
|
"name": "Name",
|
||||||
"enabled": false,
|
"enabled": true,
|
||||||
"expanded": false,
|
"expanded": true,
|
||||||
"component": {
|
"component": {
|
||||||
"selector": "text",
|
"selector": "text",
|
||||||
"settings": {
|
"settings": {
|
||||||
"field": "fieldname"
|
"pattern": "cm:name:'(.*?)'",
|
||||||
|
"field": "cm:name",
|
||||||
|
"placeholder": "Enter the name"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "contentSize",
|
||||||
|
"name": "Content Size",
|
||||||
|
"enabled": true,
|
||||||
|
"component": {
|
||||||
|
"selector": "slider",
|
||||||
|
"settings": {
|
||||||
|
"field": "cm:content.size",
|
||||||
|
"min": 0,
|
||||||
|
"max": 18,
|
||||||
|
"step": 1,
|
||||||
|
"thumbLabel": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "contentSizeRange",
|
||||||
|
"name": "Content Size (range)",
|
||||||
|
"enabled": true,
|
||||||
|
"component": {
|
||||||
|
"selector": "number-range",
|
||||||
|
"settings": {
|
||||||
|
"field": "cm:content.size"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "queryType",
|
||||||
|
"name": "Type",
|
||||||
|
"enabled": true,
|
||||||
|
"component": {
|
||||||
|
"selector": "radio",
|
||||||
|
"settings": {
|
||||||
|
"field": null,
|
||||||
|
"options": [
|
||||||
|
{ "name": "None", "value": "", "default": true },
|
||||||
|
{ "name": "All", "value": "TYPE:'cm:folder' OR TYPE:'cm:content'" },
|
||||||
|
{ "name": "Folder", "value": "TYPE:'cm:folder'" },
|
||||||
|
{ "name": "Document", "value": "TYPE:'cm:content'" }
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "queryName",
|
|
||||||
"name": "Name",
|
|
||||||
"enabled": true,
|
|
||||||
"expanded": true,
|
|
||||||
"component": {
|
|
||||||
"selector": "text",
|
|
||||||
"settings": {
|
|
||||||
"pattern": "cm:name:'(.*?)'",
|
|
||||||
"field": "cm:name",
|
|
||||||
"placeholder": "Enter the name"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "queryFields",
|
|
||||||
"name": "Fields",
|
|
||||||
"enabled": true,
|
|
||||||
"expanded": false,
|
|
||||||
"component": {
|
|
||||||
"selector": "fields",
|
|
||||||
"settings": {
|
|
||||||
"field": null,
|
|
||||||
"options": [
|
|
||||||
{ "name": "Name", "value": "name", "fields": ["name"], "default": true },
|
|
||||||
{ "name": "File Size", "value": "content.sizeInBytes", "fields": ["content"], "default": true },
|
|
||||||
{ "name": "Modified On", "value": "modifiedAt", "fields": ["modifiedAt"], "default": true },
|
|
||||||
{ "name": "Modified By", "value": "modifiedByUser.displayName", "fields": ["modifiedByUser"], "default": true }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "queryType",
|
|
||||||
"name": "Type",
|
|
||||||
"enabled": true,
|
|
||||||
"expanded": false,
|
|
||||||
"component": {
|
|
||||||
"selector": "radio",
|
|
||||||
"settings": {
|
|
||||||
"field": null,
|
|
||||||
"options": [
|
|
||||||
{ "name": "None", "value": "", "default": true },
|
|
||||||
{ "name": "All", "value": "TYPE:'cm:folder' OR TYPE:'cm:content'" },
|
|
||||||
{ "name": "Folder", "value": "TYPE:'cm:folder'" },
|
|
||||||
{ "name": "Document", "value": "TYPE:'cm:content'" }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "queryLocations",
|
|
||||||
"name": "Locations",
|
|
||||||
"enabled": true,
|
|
||||||
"expanded": false,
|
|
||||||
"component": {
|
|
||||||
"selector": "scope-locations",
|
|
||||||
"settings": {
|
|
||||||
"field": null,
|
|
||||||
"options": [
|
|
||||||
{ "name": "Default", "value": "nodes", "default": true },
|
|
||||||
{ "name": "Nodes", "value": "nodes" },
|
|
||||||
{ "name": "Deleted Nodes", "value": "deleted-nodes" },
|
|
||||||
{ "name": "Versions", "value": "versions" }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@@ -5109,7 +5109,8 @@
|
|||||||
"character": 8,
|
"character": 8,
|
||||||
"fileName": "lib/content-services/search/components/search-widget-container/search-widgets.module.ts"
|
"fileName": "lib/content-services/search/components/search-widget-container/search-widgets.module.ts"
|
||||||
},
|
},
|
||||||
"name": "SearchFieldsComponent"
|
"name": "SearchFieldsComponent",
|
||||||
|
"skipError": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"position": {
|
"position": {
|
||||||
@@ -5173,7 +5174,8 @@
|
|||||||
"character": 8,
|
"character": 8,
|
||||||
"fileName": "lib/content-services/search/components/search-widget-container/search-widgets.module.ts"
|
"fileName": "lib/content-services/search/components/search-widget-container/search-widgets.module.ts"
|
||||||
},
|
},
|
||||||
"name": "SearchScopeLocationsComponent"
|
"name": "SearchScopeLocationsComponent",
|
||||||
|
"skipError": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"position": {
|
"position": {
|
||||||
@@ -6455,4 +6457,4 @@
|
|||||||
},
|
},
|
||||||
"name": "WidgetComponent"
|
"name": "WidgetComponent"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@@ -165,6 +165,16 @@
|
|||||||
"MODIFIED_AT": "Modified at"
|
"MODIFIED_AT": "Modified at"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"FILTER": {
|
||||||
|
"ACTIONS": {
|
||||||
|
"CLEAR": "Clear",
|
||||||
|
"APPLY": "Apply"
|
||||||
|
},
|
||||||
|
"RANGE": {
|
||||||
|
"FROM": "From",
|
||||||
|
"TO": "To"
|
||||||
|
}
|
||||||
|
},
|
||||||
"ICONS": {
|
"ICONS": {
|
||||||
"ft_ic_raster_image": "Image file",
|
"ft_ic_raster_image": "Image file",
|
||||||
"ft_ic_pdf": "PDF document",
|
"ft_ic_pdf": "PDF document",
|
||||||
|
@@ -34,7 +34,8 @@ import {
|
|||||||
MatCheckboxModule,
|
MatCheckboxModule,
|
||||||
MatDatepickerModule,
|
MatDatepickerModule,
|
||||||
MatSlideToggleModule,
|
MatSlideToggleModule,
|
||||||
MatRadioModule
|
MatRadioModule,
|
||||||
|
MatSliderModule
|
||||||
} from '@angular/material';
|
} from '@angular/material';
|
||||||
|
|
||||||
export function modules() {
|
export function modules() {
|
||||||
@@ -56,7 +57,8 @@ export function modules() {
|
|||||||
MatCheckboxModule,
|
MatCheckboxModule,
|
||||||
MatDatepickerModule,
|
MatDatepickerModule,
|
||||||
MatSlideToggleModule,
|
MatSlideToggleModule,
|
||||||
MatRadioModule
|
MatRadioModule,
|
||||||
|
MatSliderModule
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +0,0 @@
|
|||||||
<mat-checkbox
|
|
||||||
*ngFor="let option of settings.options"
|
|
||||||
[checked]="option.checked"
|
|
||||||
(change)="changeHandler($event, option)">
|
|
||||||
{{ option.name }}
|
|
||||||
</mat-checkbox>
|
|
@@ -1,8 +0,0 @@
|
|||||||
.adf-search-fields {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
.mat-checkbox {
|
|
||||||
margin: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,70 +0,0 @@
|
|||||||
/*!
|
|
||||||
* @license
|
|
||||||
* Copyright 2016 Alfresco Software, Ltd.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Component, ViewEncapsulation, OnInit, Input } from '@angular/core';
|
|
||||||
import { MatCheckboxChange } from '@angular/material';
|
|
||||||
|
|
||||||
import { SearchWidget } from '../../search-widget.interface';
|
|
||||||
import { SearchWidgetSettings } from '../../search-widget-settings.interface';
|
|
||||||
import { SearchQueryBuilderService } from '../../search-query-builder.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'adf-search-fields',
|
|
||||||
templateUrl: './search-fields.component.html',
|
|
||||||
styleUrls: ['./search-fields.component.scss'],
|
|
||||||
encapsulation: ViewEncapsulation.None,
|
|
||||||
host: { class: 'adf-search-fields' }
|
|
||||||
})
|
|
||||||
export class SearchFieldsComponent implements SearchWidget, OnInit {
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
value: string;
|
|
||||||
|
|
||||||
id: string;
|
|
||||||
settings: SearchWidgetSettings;
|
|
||||||
context: SearchQueryBuilderService;
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
const defaultOptions = (this.settings.options || [])
|
|
||||||
.filter(opt => opt.default)
|
|
||||||
.map(opt => {
|
|
||||||
opt.checked = true;
|
|
||||||
return opt;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (defaultOptions.length > 0) {
|
|
||||||
this.flush(defaultOptions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
changeHandler(event: MatCheckboxChange, option: any) {
|
|
||||||
option.checked = event.checked;
|
|
||||||
this.flush(this.settings.options);
|
|
||||||
}
|
|
||||||
|
|
||||||
flush(opts: any[] = []) {
|
|
||||||
const checkedValues = opts
|
|
||||||
.filter(v => v.checked)
|
|
||||||
.map(v => v.fields)
|
|
||||||
.reduce((prev, curr) => {
|
|
||||||
return prev.concat(curr);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
this.context.fields[this.id] = checkedValues;
|
|
||||||
this.context.update();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -18,8 +18,8 @@
|
|||||||
import { Injectable, Type } from '@angular/core';
|
import { Injectable, Type } from '@angular/core';
|
||||||
import { SearchTextComponent } from '../search-text/search-text.component';
|
import { SearchTextComponent } from '../search-text/search-text.component';
|
||||||
import { SearchRadioComponent } from '../search-radio/search-radio.component';
|
import { SearchRadioComponent } from '../search-radio/search-radio.component';
|
||||||
import { SearchFieldsComponent } from '../search-fields/search-fields.component';
|
import { SearchSliderComponent } from '../search-slider/search-slider.component';
|
||||||
import { SearchScopeLocationsComponent } from '../search-scope-locations/search-scope-locations.component';
|
import { SearchNumberRangeComponent } from '../search-number-range/search-number-range.component';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SearchFilterService {
|
export class SearchFilterService {
|
||||||
@@ -30,8 +30,8 @@ export class SearchFilterService {
|
|||||||
widgets: { [id: string]: Type<{}> } = {
|
widgets: { [id: string]: Type<{}> } = {
|
||||||
'text': SearchTextComponent,
|
'text': SearchTextComponent,
|
||||||
'radio': SearchRadioComponent,
|
'radio': SearchRadioComponent,
|
||||||
'fields': SearchFieldsComponent,
|
'slider': SearchSliderComponent,
|
||||||
'scope-locations': SearchScopeLocationsComponent
|
'number-range': SearchNumberRangeComponent
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,27 @@
|
|||||||
|
<form [formGroup]="form" novalidate (ngSubmit)="apply(form.value, form.valid)">
|
||||||
|
|
||||||
|
<mat-form-field>
|
||||||
|
<input
|
||||||
|
matInput [formControl]="from" [errorStateMatcher]="matcher"
|
||||||
|
placeholder="{{ 'SEARCH.FILTER.RANGE.FROM' | translate }}">
|
||||||
|
<mat-error *ngIf="from.hasError('pattern')">Invalid format</mat-error>
|
||||||
|
<mat-error *ngIf="from.hasError('required')">Required value</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field >
|
||||||
|
<input
|
||||||
|
matInput [formControl]="to" [errorStateMatcher]="matcher"
|
||||||
|
placeholder="{{ 'SEARCH.FILTER.RANGE.TO' | translate }}">
|
||||||
|
<mat-error *ngIf="to.invalid">Invalid format</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button mat-button color="primary" (click)="reset()">
|
||||||
|
{{ 'SEARCH.FILTER.ACTIONS.CLEAR' | translate }}
|
||||||
|
</button>
|
||||||
|
<button mat-button color="primary" type="submit" [disabled]="!form.valid">
|
||||||
|
{{ 'SEARCH.FILTER.ACTIONS.APPLY' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
@@ -0,0 +1,8 @@
|
|||||||
|
.adf-search-number-range > form {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.mat-button {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,88 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { SearchNumberRangeComponent } from './search-number-range.component';
|
||||||
|
|
||||||
|
describe('SearchNumberRangeComponent', () => {
|
||||||
|
|
||||||
|
let component: SearchNumberRangeComponent;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
component = new SearchNumberRangeComponent();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should setup form elements on init', () => {
|
||||||
|
component.ngOnInit();
|
||||||
|
expect(component.form).toBeDefined();
|
||||||
|
expect(component.to).toBeDefined();
|
||||||
|
expect(component.form).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reset form', () => {
|
||||||
|
component.ngOnInit();
|
||||||
|
component.form.reset({ from: '10', to: '20' });
|
||||||
|
component.reset();
|
||||||
|
|
||||||
|
expect(component.from.value).toEqual('');
|
||||||
|
expect(component.to.value).toEqual('');
|
||||||
|
expect(component.form.value).toEqual({ from: '', to: '' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update query builder on reset', () => {
|
||||||
|
const context: any = {
|
||||||
|
queryFragments: {
|
||||||
|
contentSize: 'query'
|
||||||
|
},
|
||||||
|
update() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
component.id = 'contentSize';
|
||||||
|
component.context = context;
|
||||||
|
|
||||||
|
spyOn(context, 'update').and.stub();
|
||||||
|
|
||||||
|
component.ngOnInit();
|
||||||
|
component.reset();
|
||||||
|
|
||||||
|
expect(context.queryFragments.contentSize).toEqual('');
|
||||||
|
expect(context.update).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update query builder on value changes', () => {
|
||||||
|
const context: any = {
|
||||||
|
queryFragments: {},
|
||||||
|
update() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
component.id = 'contentSize';
|
||||||
|
component.context = context;
|
||||||
|
component.settings = { field: 'cm:content.size' };
|
||||||
|
|
||||||
|
spyOn(context, 'update').and.stub();
|
||||||
|
|
||||||
|
component.ngOnInit();
|
||||||
|
component.apply({
|
||||||
|
from: '10',
|
||||||
|
to: '20'
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
const expectedQuery = 'cm:content.size:[10 TO 20]';
|
||||||
|
expect(context.queryFragments[component.id]).toEqual(expectedQuery);
|
||||||
|
expect(context.update).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@@ -0,0 +1,77 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { OnInit, Component, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { FormControl, Validators, FormGroup } from '@angular/forms';
|
||||||
|
import { SearchWidget } from '../../search-widget.interface';
|
||||||
|
import { SearchWidgetSettings } from '../../search-widget-settings.interface';
|
||||||
|
import { SearchQueryBuilderService } from '../../search-query-builder.service';
|
||||||
|
import { LiveErrorStateMatcher } from '../../forms/live-error-state-matcher';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-search-number-range',
|
||||||
|
templateUrl: './search-number-range.component.html',
|
||||||
|
styleUrls: ['./search-number-range.component.scss'],
|
||||||
|
encapsulation: ViewEncapsulation.None,
|
||||||
|
host: { class: 'adf-search-number-range' }
|
||||||
|
})
|
||||||
|
export class SearchNumberRangeComponent implements SearchWidget, OnInit {
|
||||||
|
|
||||||
|
from: FormControl;
|
||||||
|
to: FormControl;
|
||||||
|
|
||||||
|
form: FormGroup;
|
||||||
|
matcher = new LiveErrorStateMatcher();
|
||||||
|
|
||||||
|
id: string;
|
||||||
|
settings?: SearchWidgetSettings;
|
||||||
|
context?: SearchQueryBuilderService;
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
const validators = Validators.compose([
|
||||||
|
Validators.required,
|
||||||
|
Validators.pattern(/^-?(0|[1-9]\d*)?$/)
|
||||||
|
]);
|
||||||
|
|
||||||
|
this.from = new FormControl('', validators);
|
||||||
|
this.to = new FormControl('', validators);
|
||||||
|
|
||||||
|
this.form = new FormGroup({
|
||||||
|
from: this.from,
|
||||||
|
to: this.to
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(model: { from: string, to: string }, isValid: boolean) {
|
||||||
|
if (isValid && this.id && this.context && this.settings && this.settings.field) {
|
||||||
|
this.context.queryFragments[this.id] = `${this.settings.field}:[${model.from} TO ${model.to}]`;
|
||||||
|
this.context.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.form.reset({
|
||||||
|
from: '',
|
||||||
|
to: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.id && this.context) {
|
||||||
|
this.context.queryFragments[this.id] = '';
|
||||||
|
this.context.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,11 +0,0 @@
|
|||||||
<mat-form-field>
|
|
||||||
<mat-select
|
|
||||||
[(value)]="value"
|
|
||||||
(selectionChange)="changeHandler($event)">
|
|
||||||
<mat-option
|
|
||||||
*ngFor="let option of settings.options"
|
|
||||||
[value]="option.value">
|
|
||||||
{{option.name}}
|
|
||||||
</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
@@ -1,57 +0,0 @@
|
|||||||
/*!
|
|
||||||
* @license
|
|
||||||
* Copyright 2016 Alfresco Software, Ltd.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Component, ViewEncapsulation, OnInit, Input } from '@angular/core';
|
|
||||||
import { MatSelectChange } from '@angular/material';
|
|
||||||
|
|
||||||
import { SearchWidget } from '../../search-widget.interface';
|
|
||||||
import { SearchWidgetSettings } from '../../search-widget-settings.interface';
|
|
||||||
import { SearchQueryBuilderService } from '../../search-query-builder.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'adf-search-scope-locations',
|
|
||||||
templateUrl: './search-scope-locations.component.html',
|
|
||||||
encapsulation: ViewEncapsulation.None,
|
|
||||||
host: { class: 'adf-search-scope-locations' }
|
|
||||||
})
|
|
||||||
export class SearchScopeLocationsComponent implements SearchWidget, OnInit {
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
value: string;
|
|
||||||
|
|
||||||
id: string;
|
|
||||||
settings: SearchWidgetSettings;
|
|
||||||
context: SearchQueryBuilderService;
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
|
|
||||||
const defaultSelection = (this.settings.options || []).find(opt => opt.default);
|
|
||||||
if (defaultSelection) {
|
|
||||||
this.flush(defaultSelection.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
changeHandler(event: MatSelectChange) {
|
|
||||||
this.flush(event.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
flush(value: string) {
|
|
||||||
this.value = value;
|
|
||||||
this.context.scope.locations = value;
|
|
||||||
this.context.update();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -0,0 +1,8 @@
|
|||||||
|
<mat-slider
|
||||||
|
[value]="value"
|
||||||
|
[min]="min"
|
||||||
|
[max]="max"
|
||||||
|
[step]="step"
|
||||||
|
[thumbLabel]="thumbLabel"
|
||||||
|
(change)="onChangedHandler($event)">
|
||||||
|
</mat-slider>
|
@@ -0,0 +1,5 @@
|
|||||||
|
.adf-search-slider {
|
||||||
|
.mat-slider {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,73 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { MatSliderChange } from '@angular/material';
|
||||||
|
import { SearchSliderComponent } from './search-slider.component';
|
||||||
|
|
||||||
|
describe('SearchSliderComponent', () => {
|
||||||
|
|
||||||
|
let component: SearchSliderComponent;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
component = new SearchSliderComponent();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should setup slider from settings', () => {
|
||||||
|
const settings: any = {
|
||||||
|
min: 10,
|
||||||
|
max: 100,
|
||||||
|
step: 2,
|
||||||
|
thumbLabel: true
|
||||||
|
};
|
||||||
|
|
||||||
|
component.settings = settings;
|
||||||
|
component.ngOnInit();
|
||||||
|
|
||||||
|
expect(component.min).toEqual(settings.min);
|
||||||
|
expect(component.max).toEqual(settings.max);
|
||||||
|
expect(component.step).toEqual(settings.step);
|
||||||
|
expect(component.thumbLabel).toEqual(settings.thumbLabel);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update value on slider change', () => {
|
||||||
|
component.onChangedHandler(<MatSliderChange> { value: 10 });
|
||||||
|
expect(component.value).toEqual(10);
|
||||||
|
|
||||||
|
component.onChangedHandler(<MatSliderChange> { value: 20 });
|
||||||
|
expect(component.value).toEqual(20);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update its query part on slider change', () => {
|
||||||
|
const context: any = {
|
||||||
|
queryFragments: {},
|
||||||
|
update() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
spyOn(context, 'update').and.stub();
|
||||||
|
|
||||||
|
component.context = context;
|
||||||
|
component.id = 'contentSize';
|
||||||
|
component.settings = { field: 'cm:content.size' };
|
||||||
|
|
||||||
|
component.onChangedHandler(<MatSliderChange> { value: 10 });
|
||||||
|
|
||||||
|
const expectedQuery = 'cm:content.size:[0 TO 10]';
|
||||||
|
expect(context.queryFragments[component.id]).toEqual(expectedQuery);
|
||||||
|
expect(context.update).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@@ -0,0 +1,69 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
|
||||||
|
import { SearchWidget } from '../../search-widget.interface';
|
||||||
|
import { SearchWidgetSettings } from '../../search-widget-settings.interface';
|
||||||
|
import { SearchQueryBuilderService } from '../../search-query-builder.service';
|
||||||
|
import { MatSliderChange } from '@angular/material';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-search-slider',
|
||||||
|
templateUrl: './search-slider.component.html',
|
||||||
|
styleUrls: ['./search-slider.component.scss'],
|
||||||
|
encapsulation: ViewEncapsulation.None,
|
||||||
|
host: { class: 'adf-search-slider' }
|
||||||
|
})
|
||||||
|
export class SearchSliderComponent implements SearchWidget, OnInit {
|
||||||
|
|
||||||
|
id: string;
|
||||||
|
settings: SearchWidgetSettings;
|
||||||
|
context: SearchQueryBuilderService;
|
||||||
|
step: number;
|
||||||
|
min: number;
|
||||||
|
max: number;
|
||||||
|
thumbLabel = false;
|
||||||
|
value: number;
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (this.settings) {
|
||||||
|
if (this.settings.hasOwnProperty('min')) {
|
||||||
|
this.min = this.settings['min'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.settings.hasOwnProperty('max')) {
|
||||||
|
this.max = this.settings['max'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.settings.hasOwnProperty('step')) {
|
||||||
|
this.step = this.settings['step'];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.thumbLabel = this.settings['thumbLabel'] ? true : false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onChangedHandler(event: MatSliderChange) {
|
||||||
|
this.value = event.value;
|
||||||
|
|
||||||
|
if (this.id && this.context && this.settings && this.settings.field) {
|
||||||
|
this.context.queryFragments[this.id] = `${this.settings.field}:[0 TO ${this.value}]`;
|
||||||
|
this.context.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ErrorStateMatcher } from '@angular/material';
|
||||||
|
import { FormControl, FormGroupDirective, NgForm } from '@angular/forms';
|
||||||
|
|
||||||
|
export class LiveErrorStateMatcher implements ErrorStateMatcher {
|
||||||
|
|
||||||
|
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
|
||||||
|
const isSubmitted = form && form.submitted;
|
||||||
|
return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -21,13 +21,11 @@ import { FacetField } from './facet-field.interface';
|
|||||||
import { SearchCategory } from './search-category.interface';
|
import { SearchCategory } from './search-category.interface';
|
||||||
|
|
||||||
export interface SearchConfiguration {
|
export interface SearchConfiguration {
|
||||||
|
include?: Array<string>;
|
||||||
|
fields?: Array<string>;
|
||||||
query?: {
|
query?: {
|
||||||
categories: Array<SearchCategory>
|
categories: Array<SearchCategory>
|
||||||
};
|
};
|
||||||
limits?: {
|
|
||||||
permissionEvaluationTime?: number;
|
|
||||||
permissionEvaluationCount?: number;
|
|
||||||
};
|
|
||||||
filterQueries?: Array<FilterQuery>;
|
filterQueries?: Array<FilterQuery>;
|
||||||
facetQueries?: Array<FacetQuery>;
|
facetQueries?: Array<FacetQuery>;
|
||||||
facetFields?: {
|
facetFields?: {
|
||||||
|
@@ -69,13 +69,6 @@ describe('SearchQueryBuilder', () => {
|
|||||||
expect(builder.filterQueries[1].query).toBe('query2');
|
expect(builder.filterQueries[1].query).toBe('query2');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should setup default location scope', () => {
|
|
||||||
const builder = new SearchQueryBuilderService(buildConfig({}), null);
|
|
||||||
|
|
||||||
expect(builder.scope).toBeDefined();
|
|
||||||
expect(builder.scope.locations).toBeNull();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should add new filter query', () => {
|
it('should add new filter query', () => {
|
||||||
const builder = new SearchQueryBuilderService(buildConfig({}), null);
|
const builder = new SearchQueryBuilderService(buildConfig({}), null);
|
||||||
|
|
||||||
@@ -237,6 +230,7 @@ describe('SearchQueryBuilder', () => {
|
|||||||
|
|
||||||
it('should build query with custom fields', () => {
|
it('should build query with custom fields', () => {
|
||||||
const config: SearchConfiguration = {
|
const config: SearchConfiguration = {
|
||||||
|
fields: ['field1', 'field2'],
|
||||||
query: {
|
query: {
|
||||||
categories: [
|
categories: [
|
||||||
<any> { id: 'cat1', enabled: true },
|
<any> { id: 'cat1', enabled: true },
|
||||||
@@ -247,15 +241,14 @@ describe('SearchQueryBuilder', () => {
|
|||||||
const builder = new SearchQueryBuilderService(buildConfig(config), null);
|
const builder = new SearchQueryBuilderService(buildConfig(config), null);
|
||||||
|
|
||||||
builder.queryFragments['cat1'] = 'cm:name:test';
|
builder.queryFragments['cat1'] = 'cm:name:test';
|
||||||
builder.fields['cat1'] = ['field1', 'field3'];
|
|
||||||
builder.fields['cat2'] = ['field2', 'field3'];
|
|
||||||
|
|
||||||
const compiled = builder.buildQuery();
|
const compiled = builder.buildQuery();
|
||||||
expect(compiled.fields).toEqual(['field1', 'field3', 'field2']);
|
expect(compiled.fields).toEqual(['field1', 'field2']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should build query with empty custom fields', () => {
|
it('should build query with empty custom fields', () => {
|
||||||
const config: SearchConfiguration = {
|
const config: SearchConfiguration = {
|
||||||
|
fields: [],
|
||||||
query: {
|
query: {
|
||||||
categories: [
|
categories: [
|
||||||
<any> { id: 'cat1', enabled: true },
|
<any> { id: 'cat1', enabled: true },
|
||||||
@@ -266,8 +259,6 @@ describe('SearchQueryBuilder', () => {
|
|||||||
const builder = new SearchQueryBuilderService(buildConfig(config), null);
|
const builder = new SearchQueryBuilderService(buildConfig(config), null);
|
||||||
|
|
||||||
builder.queryFragments['cat1'] = 'cm:name:test';
|
builder.queryFragments['cat1'] = 'cm:name:test';
|
||||||
builder.fields['cat1'] = [];
|
|
||||||
builder.fields['cat2'] = null;
|
|
||||||
|
|
||||||
const compiled = builder.buildQuery();
|
const compiled = builder.buildQuery();
|
||||||
expect(compiled.fields).toEqual([]);
|
expect(compiled.fields).toEqual([]);
|
||||||
@@ -330,41 +321,6 @@ describe('SearchQueryBuilder', () => {
|
|||||||
expect(compiled.facetFields).toEqual(config.facetFields);
|
expect(compiled.facetFields).toEqual(config.facetFields);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should build query with custom limits', () => {
|
|
||||||
const config: SearchConfiguration = {
|
|
||||||
query: {
|
|
||||||
categories: [
|
|
||||||
<any> { id: 'cat1', enabled: true }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
limits: {
|
|
||||||
permissionEvaluationCount: 100,
|
|
||||||
permissionEvaluationTime: 100
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const builder = new SearchQueryBuilderService(buildConfig(config), null);
|
|
||||||
builder.queryFragments['cat1'] = 'cm:name:test';
|
|
||||||
|
|
||||||
const compiled = builder.buildQuery();
|
|
||||||
expect(compiled.limits).toEqual(config.limits);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should build query with custom scope', () => {
|
|
||||||
const config: SearchConfiguration = {
|
|
||||||
query: {
|
|
||||||
categories: [
|
|
||||||
<any> { id: 'cat1', enabled: true }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const builder = new SearchQueryBuilderService(buildConfig(config), null);
|
|
||||||
builder.queryFragments['cat1'] = 'cm:name:test';
|
|
||||||
builder.scope.locations = 'custom';
|
|
||||||
|
|
||||||
const compiled = builder.buildQuery();
|
|
||||||
expect(compiled.scope.locations).toEqual('custom');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should use pagination settings', () => {
|
it('should use pagination settings', () => {
|
||||||
const config: SearchConfiguration = {
|
const config: SearchConfiguration = {
|
||||||
query: {
|
query: {
|
||||||
|
@@ -33,8 +33,6 @@ export class SearchQueryBuilderService {
|
|||||||
|
|
||||||
categories: Array<SearchCategory> = [];
|
categories: Array<SearchCategory> = [];
|
||||||
queryFragments: { [id: string]: string } = {};
|
queryFragments: { [id: string]: string } = {};
|
||||||
fields: { [id: string]: string[] } = {};
|
|
||||||
scope: { locations?: string };
|
|
||||||
filterQueries: FilterQuery[] = [];
|
filterQueries: FilterQuery[] = [];
|
||||||
ranges: { [id: string]: SearchRange } = {};
|
ranges: { [id: string]: SearchRange } = {};
|
||||||
paging: { maxItems?: number; skipCount?: number } = null;
|
paging: { maxItems?: number; skipCount?: number } = null;
|
||||||
@@ -52,9 +50,6 @@ export class SearchQueryBuilderService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.filterQueries = this.config.filterQueries || [];
|
this.filterQueries = this.config.filterQueries || [];
|
||||||
this.scope = {
|
|
||||||
locations: null
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addFilterQuery(query: string): void {
|
addFilterQuery(query: string): void {
|
||||||
@@ -93,7 +88,6 @@ export class SearchQueryBuilderService {
|
|||||||
|
|
||||||
buildQuery(): QueryBody {
|
buildQuery(): QueryBody {
|
||||||
let query = '';
|
let query = '';
|
||||||
const fields: string[] = [];
|
|
||||||
|
|
||||||
this.categories.forEach(facet => {
|
this.categories.forEach(facet => {
|
||||||
const customQuery = this.queryFragments[facet.id];
|
const customQuery = this.queryFragments[facet.id];
|
||||||
@@ -103,17 +97,13 @@ export class SearchQueryBuilderService {
|
|||||||
}
|
}
|
||||||
query += `(${customQuery})`;
|
query += `(${customQuery})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const customFields = this.fields[facet.id];
|
|
||||||
if (customFields && customFields.length > 0) {
|
|
||||||
for (const field of customFields) {
|
|
||||||
if (!fields.includes(field)) {
|
|
||||||
fields.push(field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const include = this.config.include || [];
|
||||||
|
if (include.length === 0) {
|
||||||
|
include.push('path', 'allowableOperations');
|
||||||
|
}
|
||||||
|
|
||||||
if (query) {
|
if (query) {
|
||||||
|
|
||||||
const result: QueryBody = {
|
const result: QueryBody = {
|
||||||
@@ -121,14 +111,12 @@ export class SearchQueryBuilderService {
|
|||||||
query: query,
|
query: query,
|
||||||
language: 'afts'
|
language: 'afts'
|
||||||
},
|
},
|
||||||
include: ['path', 'allowableOperations'],
|
include: include,
|
||||||
fields: fields,
|
|
||||||
paging: this.paging,
|
paging: this.paging,
|
||||||
|
fields: this.config.fields,
|
||||||
filterQueries: this.filterQueries,
|
filterQueries: this.filterQueries,
|
||||||
facetQueries: this.config.facetQueries,
|
facetQueries: this.config.facetQueries,
|
||||||
facetFields: this.config.facetFields,
|
facetFields: this.config.facetFields
|
||||||
limits: this.config.limits,
|
|
||||||
scope: this.scope
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@@ -33,8 +33,8 @@ import { SearchFilterComponent } from './components/search-filter/search-filter.
|
|||||||
import { SearchChipListComponent } from './components/search-chip-list/search-chip-list.component';
|
import { SearchChipListComponent } from './components/search-chip-list/search-chip-list.component';
|
||||||
import { SearchTextComponent } from './components/search-text/search-text.component';
|
import { SearchTextComponent } from './components/search-text/search-text.component';
|
||||||
import { SearchRadioComponent } from './components/search-radio/search-radio.component';
|
import { SearchRadioComponent } from './components/search-radio/search-radio.component';
|
||||||
import { SearchFieldsComponent } from './components/search-fields/search-fields.component';
|
import { SearchSliderComponent } from './components/search-slider/search-slider.component';
|
||||||
import { SearchScopeLocationsComponent } from './components/search-scope-locations/search-scope-locations.component';
|
import { SearchNumberRangeComponent } from './components/search-number-range/search-number-range.component';
|
||||||
|
|
||||||
export const ALFRESCO_SEARCH_DIRECTIVES: any[] = [
|
export const ALFRESCO_SEARCH_DIRECTIVES: any[] = [
|
||||||
SearchComponent,
|
SearchComponent,
|
||||||
@@ -59,23 +59,23 @@ export const ALFRESCO_SEARCH_DIRECTIVES: any[] = [
|
|||||||
SearchWidgetContainerComponent,
|
SearchWidgetContainerComponent,
|
||||||
SearchTextComponent,
|
SearchTextComponent,
|
||||||
SearchRadioComponent,
|
SearchRadioComponent,
|
||||||
SearchFieldsComponent,
|
SearchSliderComponent,
|
||||||
SearchScopeLocationsComponent
|
SearchNumberRangeComponent
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
...ALFRESCO_SEARCH_DIRECTIVES,
|
...ALFRESCO_SEARCH_DIRECTIVES,
|
||||||
SearchWidgetContainerComponent,
|
SearchWidgetContainerComponent,
|
||||||
SearchTextComponent,
|
SearchTextComponent,
|
||||||
SearchRadioComponent,
|
SearchRadioComponent,
|
||||||
SearchFieldsComponent,
|
SearchSliderComponent,
|
||||||
SearchScopeLocationsComponent
|
SearchNumberRangeComponent
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
SearchWidgetContainerComponent,
|
SearchWidgetContainerComponent,
|
||||||
SearchTextComponent,
|
SearchTextComponent,
|
||||||
SearchRadioComponent,
|
SearchRadioComponent,
|
||||||
SearchFieldsComponent,
|
SearchSliderComponent,
|
||||||
SearchScopeLocationsComponent
|
SearchNumberRangeComponent
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class SearchModule {}
|
export class SearchModule {}
|
||||||
|
@@ -481,12 +481,16 @@
|
|||||||
"description": "Search configuration parameters",
|
"description": "Search configuration parameters",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"limits": {
|
"include": {
|
||||||
"description": "The limits element limits the time and resources used for query execution. Limits applied to the query go to the database.",
|
"type": "array",
|
||||||
"type": "object",
|
"items": {
|
||||||
"properties": {
|
"type": "string"
|
||||||
"permissionEvaluationTime": { "type": "integer" },
|
}
|
||||||
"permissionEvaluationCount": { "type": "integer" }
|
},
|
||||||
|
"fields": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"filterQueries": {
|
"filterQueries": {
|
||||||
|
Reference in New Issue
Block a user