diff --git a/demo-shell/src/app.config.json b/demo-shell/src/app.config.json index 539edf77d9..d8d0bccd87 100644 --- a/demo-shell/src/app.config.json +++ b/demo-shell/src/app.config.json @@ -132,7 +132,8 @@ "component": { "selector": "number-range", "settings": { - "field": "cm:content.size" + "field": "cm:content.size", + "format": "[{FROM} TO {TO}]" } } }, diff --git a/docs/content-services/search-filter.component.md b/docs/content-services/search-filter.component.md index c5d227a1ba..ebb9b91901 100644 --- a/docs/content-services/search-filter.component.md +++ b/docs/content-services/search-filter.component.md @@ -326,7 +326,8 @@ Provides ability to select a range between two Numbers based on the particular ` "component": { "selector": "number-range", "settings": { - "field": "cm:content.size" + "field": "cm:content.size", + "format": "[{FROM} TO {TO}]" } } } @@ -337,6 +338,42 @@ Provides ability to select a range between two Numbers based on the particular ` ![Number Range Widget](../docassets/images/search-number-range.png) +#### Widget Settings + +| Name | Type | Description | +| --- | --- | --- | +| field | string | Field to to use | +| format | string | Value format. Uses string substitution to allow all sorts of [range queries](https://docs.alfresco.com/5.2/concepts/rm-searchsyntax-ranges.html). | + +#### Range query format + +For more details on the range search format please refer to the "[Search for ranges](https://docs.alfresco.com/5.2/concepts/rm-searchsyntax-ranges.html)" article. + +The widget uses `{FROM}` and `{TO}` values together with the required target format of the query. +You can use any type of the query pattern, the widget automatically substitutes the values, for example: + +```json +"settings": { + "field": "cm:content.size", + "format": "[{FROM} TO {TO}]" +} +``` + +The format above may result in the following query at runtime: + +```text +cm:content.size:[0 TO 100] +``` + +Other format examples: + +| Format | Example | +| --- | --- | +| `[{FROM} TO {TO}]` | `[0 TO 5]` | +| `<{FROM} TO {TO}]` | `<0 TO 5]` | +| `[{FROM} TO {TO}>` | `[0 TO 5>` | +| `<{FROM} TO {TO}>` | `<0 TO 5>` | + ### Radio List Widget Provides you with a list of radio-boxes, each backed by a particular query fragment. diff --git a/lib/content-services/search/components/search-number-range/search-number-range.component.spec.ts b/lib/content-services/search/components/search-number-range/search-number-range.component.spec.ts index 0a1f6e7893..e1fa4bf996 100644 --- a/lib/content-services/search/components/search-number-range/search-number-range.component.spec.ts +++ b/lib/content-services/search/components/search-number-range/search-number-range.component.spec.ts @@ -85,4 +85,43 @@ describe('SearchNumberRangeComponent', () => { expect(context.update).toHaveBeenCalled(); }); + it('should fetch format from the settings', () => { + component.settings = { + field: 'cm:content.size', + format: '<{FROM} TO {TO}>' + }; + component.ngOnInit(); + + expect(component.field).toEqual('cm:content.size'); + expect(component.format).toEqual('<{FROM} TO {TO}>'); + }); + + it('should use default format if not provided', () => { + component.settings = { + field: 'cm:content.size' + }; + component.ngOnInit(); + + expect(component.field).toEqual('cm:content.size'); + expect(component.format).toEqual('[{FROM} TO {TO}]'); + }); + + it('should format value based on the current pattern', () => { + const context: any = { + queryFragments: {}, + update() {} + }; + + component.id = 'range1'; + component.settings = { + field: 'cm:content.size', + format: '<{FROM} TO {TO}>' + }; + component.context = context; + component.ngOnInit(); + + component.apply({ from: '0', to: '100' }, true); + expect(context.queryFragments['range1']).toEqual('cm:content.size:<0 TO 100>'); + }); + }); diff --git a/lib/content-services/search/components/search-number-range/search-number-range.component.ts b/lib/content-services/search/components/search-number-range/search-number-range.component.ts index ca9a9229bd..c997e76105 100644 --- a/lib/content-services/search/components/search-number-range/search-number-range.component.ts +++ b/lib/content-services/search/components/search-number-range/search-number-range.component.ts @@ -41,7 +41,16 @@ export class SearchNumberRangeComponent implements SearchWidget, OnInit { settings?: SearchWidgetSettings; context?: SearchQueryBuilderService; + field: string; + format = '[{FROM} TO {TO}]'; + ngOnInit(): void { + + if (this.settings) { + this.field = this.settings.field; + this.format = this.settings.format || '[{FROM} TO {TO}]'; + } + const validators = Validators.compose([ Validators.required, Validators.pattern(/^-?(0|[1-9]\d*)?$/) @@ -57,12 +66,30 @@ export class SearchNumberRangeComponent implements SearchWidget, OnInit { } 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}]`; + if (isValid && this.id && this.context && this.field) { + const map = new Map(); + map.set('FROM', model.from); + map.set('TO', model.to); + + const value = this.formatString(this.format, map); + const query = `${this.field}:${value}`; + + this.context.queryFragments[this.id] = query; this.context.update(); } } + private formatString(str: string, map: Map): string { + let result = str; + + map.forEach((value, key) => { + const expr = new RegExp('{' + key + '}', 'gm'); + result = result.replace(expr, value); + }); + + return result; + } + reset() { this.form.reset({ from: '', diff --git a/lib/content-services/tag/tag-actions.component.spec.ts b/lib/content-services/tag/tag-actions.component.spec.ts index 8f8f35b18e..c624975edf 100644 --- a/lib/content-services/tag/tag-actions.component.spec.ts +++ b/lib/content-services/tag/tag-actions.component.spec.ts @@ -192,13 +192,14 @@ describe('TagActionsComponent', () => { }); }); - it('Add tag should be disabled by default', (done) => { + it('Add tag should be disabled by default', () => { component.nodeId = 'fake-node-id'; component.newTagName = 'fake-tag-name'; + fixture.detectChanges(); + let addButton: any = element.querySelector('#add-tag'); expect(addButton.disabled).toEqual(true); - done(); }); it('Add tag should return an error if the tag is already present', (done) => { diff --git a/lib/content-services/tag/tag-actions.component.ts b/lib/content-services/tag/tag-actions.component.ts index 9379ba0e25..9ac307a763 100644 --- a/lib/content-services/tag/tag-actions.component.ts +++ b/lib/content-services/tag/tag-actions.component.ts @@ -16,8 +16,9 @@ */ import { TranslationService } from '@alfresco/adf-core'; -import { Component, EventEmitter, Input, OnChanges, Output, ViewEncapsulation } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, Output, ViewEncapsulation, OnDestroy, OnInit } from '@angular/core'; import { TagService } from './services/tag.service'; +import { Subscription } from 'rxjs/Subscription'; /** * @@ -30,7 +31,7 @@ import { TagService } from './services/tag.service'; styleUrls: ['./tag-actions.component.scss'], encapsulation: ViewEncapsulation.None }) -export class TagActionsComponent implements OnChanges { +export class TagActionsComponent implements OnChanges, OnInit, OnDestroy { /** The identifier of a node. */ @Input() @@ -49,23 +50,31 @@ export class TagActionsComponent implements OnChanges { result = new EventEmitter(); newTagName: string; - tagsEntries: any; - errorMsg: string; - disableAddTag: boolean = true; - constructor(private tagService: TagService, private translateService: TranslationService) { - this.tagService.refresh.subscribe(() => { - this.refreshTag(); - }); + private subscriptions: Subscription[] = []; + + constructor(private tagService: TagService, private translateService: TranslationService) {} + + ngOnInit() { + this.subscriptions.push( + this.tagService.refresh.subscribe(() => { + this.refreshTag(); + }) + ); } ngOnChanges() { return this.refreshTag(); } + ngOnDestroy() { + this.subscriptions.forEach(subscription => subscription.unsubscribe()); + this.subscriptions = []; + } + refreshTag() { if (this.nodeId) { this.tagService.getTagsByNodeId(this.nodeId).subscribe((data) => {