mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[AAE-534] Core - add search cloud component (#5193)
* [AAE-534] - add search cloud component * change doc file * more changes on doc file * remove empty scss file * add animation and more customizations * add preselect value property * fix unit tests
This commit is contained in:
40
docs/core/components/search-cloud.component.md
Normal file
40
docs/core/components/search-cloud.component.md
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
Title: Search Cloud Component
|
||||
Added: v3.5.0
|
||||
Status: Active
|
||||
Last reviewed: 2019-10-24
|
||||
---
|
||||
|
||||
# [Search Cloud Component](../../../lib/core/search-cloud/search-cloud.component.ts "Defined in pagination.component.ts")
|
||||
|
||||
Should manage search for cloud components
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```html
|
||||
<adf-search-cloud>
|
||||
[type]="'text'"
|
||||
[placeholder]="'placeholder'"
|
||||
[debounceTime]="200"
|
||||
[expandable]='false'
|
||||
(change)="onSearchValueChanged($event)"
|
||||
</adf-search-cloud>
|
||||
```
|
||||
|
||||
## Class members
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
| ---- | ---- | ------------- | ----------- |
|
||||
| type | [`SearchCloudTypesEnum`](../../../lib/core/models/search-cloud.model.ts) | | search type ('text'). |
|
||||
| value | `string` | | preselected input value |
|
||||
| expandable | `boolean` | false | The field should expand on click when this flag is true |
|
||||
| placeholder | `string` | | placeholder content. |
|
||||
| debounceTime | `number` | 500 | Time in miliseconds for debounce the event. |
|
||||
|
||||
### Events
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| change | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<string>` | Emitted when search widget value is changed. |
|
@@ -56,6 +56,7 @@ import { TranslateLoaderService } from './services/translate-loader.service';
|
||||
import { ExtensionsModule } from '@alfresco/adf-extensions';
|
||||
import { directionalityConfigFactory } from './services/directionality-config-factory';
|
||||
import { DirectionalityConfigService } from './services/directionality-config.service';
|
||||
import { SearchCloudModule } from './search-cloud/search-cloud.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -89,7 +90,8 @@ import { DirectionalityConfigService } from './services/directionality-config.se
|
||||
TemplateModule,
|
||||
IconModule,
|
||||
SortingPickerModule,
|
||||
NotificationHistoryModule
|
||||
NotificationHistoryModule,
|
||||
SearchCloudModule
|
||||
],
|
||||
exports: [
|
||||
AboutModule,
|
||||
@@ -122,7 +124,8 @@ import { DirectionalityConfigService } from './services/directionality-config.se
|
||||
TemplateModule,
|
||||
SortingPickerModule,
|
||||
IconModule,
|
||||
NotificationHistoryModule
|
||||
NotificationHistoryModule,
|
||||
SearchCloudModule
|
||||
]
|
||||
})
|
||||
export class CoreModule {
|
||||
|
@@ -42,6 +42,7 @@ export * from './clipboard/index';
|
||||
export * from './dialogs/index';
|
||||
export * from './icon/index';
|
||||
export * from './notifications/index';
|
||||
export * from './search-cloud/index';
|
||||
|
||||
export * from './utils/index';
|
||||
export * from './interface/index';
|
||||
|
38
lib/core/models/search-cloud.model.ts
Normal file
38
lib/core/models/search-cloud.model.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { SearchTextCloudComponent } from '../search-cloud/components/search-text-cloud/search-text-cloud.component';
|
||||
|
||||
export interface SearchCloudProperties {
|
||||
value?: string;
|
||||
placeholder?: string;
|
||||
debounceTime?: number;
|
||||
expandable?: boolean;
|
||||
}
|
||||
|
||||
export enum SearchCloudTypesEnum {
|
||||
text = 'text'
|
||||
}
|
||||
|
||||
export const SEARCH_CLOUD_TYPES = {
|
||||
text: SearchTextCloudComponent
|
||||
};
|
||||
|
||||
export interface SearchCloudWidget {
|
||||
properties: SearchCloudProperties;
|
||||
onChangedHandler(event: any);
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
<div class="adf-search-cloud-wrapper" #searchContainer>
|
||||
|
||||
<mat-form-field class="adf-search-text-cloud">
|
||||
<input
|
||||
matInput
|
||||
[(ngModel)]="properties.value"
|
||||
placeholder="{{ properties?.placeholder }}"
|
||||
(input)="onChangedHandler($event)"
|
||||
data-automation-id="search-project-field" />
|
||||
<mat-icon matSuffix *ngIf="properties.value?.length > 0" (click)="clear()">close</mat-icon>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-icon class="adf-search-cloud-icon" (click)="toggle()" matSuffix>search</mat-icon>
|
||||
</div>
|
@@ -0,0 +1,57 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { SearchTextCloudComponent } from './search-text-cloud.component';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { setupTestBed } from 'core';
|
||||
import { CoreTestingModule } from '../../../testing/core.testing.module';
|
||||
import { SearchCloudService } from '../../../services/search-cloud.service';
|
||||
|
||||
describe('SearchTextCloudComponent', () => {
|
||||
|
||||
let fixture: ComponentFixture<SearchTextCloudComponent>;
|
||||
let service: SearchCloudService;
|
||||
|
||||
setupTestBed({
|
||||
imports: [CoreTestingModule]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SearchTextCloudComponent);
|
||||
service = TestBed.get(SearchCloudService);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('should update search service value when is field is changed', async(() => {
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
const searchInput = fixture.nativeElement.querySelector('.adf-search-text-cloud input');
|
||||
searchInput.value = 'mock-search-text';
|
||||
searchInput.dispatchEvent(new Event('input'));
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
service.value.subscribe( value => {
|
||||
expect(value).toBe('mock-search-text');
|
||||
});
|
||||
}));
|
||||
|
||||
});
|
@@ -0,0 +1,69 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { ViewEncapsulation, Component, ViewChild, ElementRef, Renderer2, OnInit } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { SearchCloudService } from '../../../services/search-cloud.service';
|
||||
import { SearchCloudProperties, SearchCloudWidget } from '../../../models/search-cloud.model';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-search-text-cloud',
|
||||
templateUrl: './search-text-cloud.component.html',
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class SearchTextCloudComponent implements OnInit, SearchCloudWidget {
|
||||
|
||||
@ViewChild('searchContainer')
|
||||
searchInput: ElementRef;
|
||||
|
||||
properties: SearchCloudProperties = {};
|
||||
onDestroy$: Subject<void> = new Subject<void>();
|
||||
|
||||
expandedClass = 'app-field-expanded';
|
||||
|
||||
constructor(
|
||||
private searchCloudService: SearchCloudService,
|
||||
private renderer: Renderer2) {}
|
||||
|
||||
ngOnInit() {
|
||||
if (!this.isExpandable()) {
|
||||
this.renderer.addClass(this.searchInput.nativeElement, this.expandedClass);
|
||||
}
|
||||
}
|
||||
|
||||
onChangedHandler(event) {
|
||||
this.searchCloudService.value.next(event.target.value);
|
||||
}
|
||||
|
||||
toggle() {
|
||||
if (!this.isExpandable()) { return; }
|
||||
|
||||
if (this.searchInput.nativeElement && this.searchInput.nativeElement.classList.contains(this.expandedClass)) {
|
||||
this.renderer.removeClass(this.searchInput.nativeElement, this.expandedClass);
|
||||
} else {
|
||||
this.renderer.addClass(this.searchInput.nativeElement, this.expandedClass);
|
||||
}
|
||||
}
|
||||
|
||||
private isExpandable() {
|
||||
return this.properties && this.properties.expandable;
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.properties.value = '';
|
||||
}
|
||||
}
|
18
lib/core/search-cloud/index.ts
Normal file
18
lib/core/search-cloud/index.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
|
||||
export * from './public-api';
|
19
lib/core/search-cloud/public-api.ts
Normal file
19
lib/core/search-cloud/public-api.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
|
||||
export * from './search-cloud.component';
|
||||
export * from './search-cloud.module';
|
33
lib/core/search-cloud/search-cloud.component.scss
Normal file
33
lib/core/search-cloud/search-cloud.component.scss
Normal file
@@ -0,0 +1,33 @@
|
||||
.adf-search-cloud {
|
||||
|
||||
&-wrapper {
|
||||
position: relative;
|
||||
margin: 10px;
|
||||
width: 260px;
|
||||
|
||||
&.app-field-expanded {
|
||||
mat-form-field {
|
||||
display: block;
|
||||
width: 220px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-icon {
|
||||
fill: currentColor;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
line-height: 65px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
mat-form-field {
|
||||
float: right;
|
||||
width:0;
|
||||
margin-left: 10px;
|
||||
|
||||
-webkit-transition: all 0.5s ease;
|
||||
-moz-transition: all 0.5s ease;
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
}
|
61
lib/core/search-cloud/search-cloud.component.spec.ts
Normal file
61
lib/core/search-cloud/search-cloud.component.spec.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { setupTestBed } from 'core';
|
||||
import { CoreTestingModule } from '../testing/core.testing.module';
|
||||
import { SearchCloudComponent } from './search-cloud.component';
|
||||
import { SearchCloudTypesEnum } from '../models/search-cloud.model';
|
||||
|
||||
describe('SearchCloudComponent', () => {
|
||||
|
||||
let fixture: ComponentFixture<SearchCloudComponent>;
|
||||
let component: SearchCloudComponent;
|
||||
|
||||
setupTestBed({
|
||||
imports: [CoreTestingModule]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SearchCloudComponent);
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('should emit search text when is field is changed', async(() => {
|
||||
spyOn(component.change, 'emit');
|
||||
component.type = SearchCloudTypesEnum.text;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
const searchInput = fixture.nativeElement.querySelector('.adf-search-text-cloud input');
|
||||
searchInput.value = 'mock-search-text';
|
||||
searchInput.dispatchEvent(new Event('input'));
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
component.change.subscribe( emitValue => {
|
||||
expect(emitValue).toBe('mock-search-text');
|
||||
});
|
||||
}));
|
||||
|
||||
});
|
95
lib/core/search-cloud/search-cloud.component.ts
Normal file
95
lib/core/search-cloud/search-cloud.component.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { ViewEncapsulation, Component, OnInit, ComponentRef, ViewChild, ViewContainerRef, Input, ComponentFactoryResolver, OnDestroy, EventEmitter, Output } from '@angular/core';
|
||||
import { SearchCloudService } from '../services/search-cloud.service';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil, debounceTime } from 'rxjs/operators';
|
||||
import { SearchCloudTypesEnum, SEARCH_CLOUD_TYPES, SearchCloudProperties } from '../models/search-cloud.model';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-search-cloud',
|
||||
template: '<div #container></div>',
|
||||
styleUrls: ['./search-cloud.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
host: {
|
||||
'class': 'adf-search-cloud'
|
||||
}
|
||||
})
|
||||
export class SearchCloudComponent implements OnInit, OnDestroy {
|
||||
|
||||
@Input() value: string = '';
|
||||
|
||||
@Input() debounceTime: number = 500;
|
||||
|
||||
@Input() placeholder: string;
|
||||
|
||||
@Input() expandable: boolean = false;
|
||||
|
||||
@Input() type: SearchCloudTypesEnum;
|
||||
|
||||
@ViewChild('container', { read: ViewContainerRef })
|
||||
container: ViewContainerRef;
|
||||
|
||||
@Output() change: EventEmitter<String> = new EventEmitter<String>();
|
||||
|
||||
private componentRef: ComponentRef<any>;
|
||||
onDestroy$: Subject<void> = new Subject<void>();
|
||||
|
||||
constructor (
|
||||
private searchCloudService: SearchCloudService,
|
||||
private componentFactoryResolver: ComponentFactoryResolver) {}
|
||||
|
||||
ngOnInit() {
|
||||
const componentType = SEARCH_CLOUD_TYPES[this.type];
|
||||
if (componentType) {
|
||||
const factory = this.componentFactoryResolver.resolveComponentFactory(componentType);
|
||||
if (factory) {
|
||||
this.componentRef = this.container.createComponent(factory, 0);
|
||||
this.setupWidget();
|
||||
}
|
||||
}
|
||||
|
||||
this.searchCloudService.value
|
||||
.pipe(
|
||||
debounceTime(this.debounceTime),
|
||||
takeUntil(this.onDestroy$)
|
||||
)
|
||||
.subscribe( (value: string) => {
|
||||
this.change.emit(value);
|
||||
});
|
||||
}
|
||||
|
||||
setupWidget() {
|
||||
if (this.componentRef && this.componentRef.instance) {
|
||||
const properties: SearchCloudProperties = {
|
||||
placeholder: this.placeholder,
|
||||
debounceTime: this.debounceTime,
|
||||
expandable: this.expandable,
|
||||
value: this.value
|
||||
};
|
||||
this.componentRef.instance.properties = properties;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.componentRef) {
|
||||
this.componentRef.destroy();
|
||||
this.componentRef = null;
|
||||
}
|
||||
}
|
||||
}
|
38
lib/core/search-cloud/search-cloud.module.ts
Normal file
38
lib/core/search-cloud/search-cloud.module.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { NgModule } from '@angular/core';
|
||||
import { SearchCloudComponent } from './search-cloud.component';
|
||||
import { SearchTextCloudComponent } from './components/search-text-cloud/search-text-cloud.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MaterialModule } from '../material.module';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
SearchCloudComponent,
|
||||
SearchTextCloudComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
MaterialModule,
|
||||
FormsModule
|
||||
],
|
||||
exports: [ SearchCloudComponent],
|
||||
entryComponents: [ SearchTextCloudComponent ]
|
||||
})
|
||||
export class SearchCloudModule {}
|
26
lib/core/services/search-cloud.service.ts
Normal file
26
lib/core/services/search-cloud.service.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { Injectable } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SearchCloudService {
|
||||
value = new Subject<String>();
|
||||
}
|
Reference in New Issue
Block a user