Newer
Older
import {OverlayRef} from "@angular/cdk/overlay";

Florent Poittevin
committed
import {
AfterViewInit,

Florent Poittevin
committed
ElementRef,
HostBinding,

Florent Poittevin
committed
Input,
OnInit,
ViewChild,
} from "@angular/core";
import {
FormBuilder,
FormGroup,
} from "@angular/forms";
import {environment} from "@environments/environment";

Florent Poittevin
committed
import {Store} from "@ngxs/store";
import {SharedAbstractContentPresentational} from "@shared/components/presentationals/shared-abstract-content/shared-abstract-content.presentational";

Florent Poittevin
committed
import {SharedSearchableMultiSelectPresentational} from "@shared/components/presentationals/shared-searchable-multi-select/shared-searchable-multi-select.presentational";
import {SharedSearchableSingleSelectPresentational} from "@shared/components/presentationals/shared-searchable-single-select/shared-searchable-single-select.presentational";
import {Observable} from "rxjs";

Florent Poittevin
committed
import {
debounceTime,
distinctUntilChanged,
tap,
} from "rxjs/operators";
import {

Florent Poittevin
committed
BaseResourceType,
Florent POITTEVIN
committed
isEmptyString,
isNotNullNorUndefined,
Florent POITTEVIN
committed
isNullOrUndefined,
MappingObjectUtil,

Florent Poittevin
committed
MemoizedUtil,

Florent Poittevin
committed
QueryParameters,

Florent Poittevin
committed
ResourceState,
ResourceStateModel,

Florent Poittevin
committed
} from "solidify-frontend";
export abstract class SharedSearchableAbstractContentPresentational<TResource extends BaseResourceType> extends SharedAbstractContentPresentational<TResource> implements OnInit, AfterViewInit {

Florent Poittevin
committed
listObs: Observable<TResource[]>;

Florent Poittevin
committed
totalObs: Observable<number>;
isLoadingObs: Observable<boolean>;

Florent Poittevin
committed
form: FormGroup;
protected _overlayRefs: Set<OverlayRef> = new Set<OverlayRef>();

Florent Poittevin
committed
@HostBinding("class.is-loading")
isLoading: boolean;

Florent Poittevin
committed
@Input()

Florent Poittevin
committed
abstract host: SharedSearchableMultiSelectPresentational<ResourceStateModel<TResource>, TResource> | SharedSearchableSingleSelectPresentational<ResourceStateModel<TResource>, TResource>;

Florent Poittevin
committed

Florent Poittevin
committed
input: ElementRef;
protected readonly _debounceTime: number = 250;
protected readonly _pageSize: number = environment.defaultEnumValuePageSizeLazyLoad;
constructor(protected _store: Store,

Florent Poittevin
committed
protected _fb: FormBuilder) {
super();
}
ngOnInit(): void {
super.ngOnInit();
this._initSearchForm();
this._dispatchInitDataLoad();
this._retrieveSelector();
this._observeSearchInput();
this._observeIsLoading();

Florent Poittevin
committed
}
private _initSearchForm(): void {
this.form = this._fb.group({
[this.host.formDefinition.search]: [""],
});
}
getFocusedResourceAndIndex(): { value: TResource | undefined, index: number } {
const list = this.list;
for (let index = 0; index < list.length; index++) {
if (this.navigationResId === list[index].resId) {
return {value: list[index], index};
getFocusedResource(): TResource | undefined {
return this.getFocusedResourceAndIndex().value;
}
getFocusedIndex(): number {
return this.getFocusedResourceAndIndex().index;
}
selectNextResource(): void {
const list = this.list;
const focusedIndex = this.getFocusedIndex();
if (focusedIndex !== list.length - 1) {
this.navigationResId = list[focusedIndex + 1].resId;
}
}
selectPreviousResource(): void {
const list = this.list;
const focusedIndex = this.getFocusedIndex();
if (focusedIndex > 0) {
this.navigationResId = list[focusedIndex - 1].resId;
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
}
}
@HostListener("keydown.arrowDown", ["$event"])
onArrowDown(keyboardEvent: KeyboardEvent): void {
if (keyboardEvent && !keyboardEvent.defaultPrevented) {
keyboardEvent.preventDefault();
this.selectNextResource();
}
}
@HostListener("keydown.arrowUp", ["$event"])
onArrowUp(keyboardEvent: KeyboardEvent): void {
if (keyboardEvent && !keyboardEvent.defaultPrevented) {
keyboardEvent.preventDefault();
this.selectPreviousResource();
}
}
@HostListener("keydown.enter", ["$event"])
onSelectValue(keyboardEvent: KeyboardEvent): void {
if (keyboardEvent && !keyboardEvent.defaultPrevented) {
keyboardEvent.preventDefault();
this.select(this.getFocusedResource());
}
}

Florent Poittevin
committed
private _dispatchInitDataLoad(): void {
const queryParameters = new QueryParameters(this._pageSize);
if (isNotNullNorUndefined(this.host.extraSearchQueryParam)) {
queryParameters.search.searchItems = MappingObjectUtil.copy(this.host.extraSearchQueryParam);
}
this._store.dispatch(new this.host.resourceNameSpace.GetAll(queryParameters));

Florent Poittevin
committed
}
private _retrieveSelector(): void {
this.listObs = ResourceState.list(this._store, this.host.state);
this.totalObs = ResourceState.total(this._store, this.host.state);
this.isLoadingObs = MemoizedUtil.isLoading(this._store, this.host.state);

Florent Poittevin
committed
}
private _observeSearchInput(): void {
this.subscribe(this.form.get(this.host.formDefinition.search).valueChanges.pipe(
debounceTime(this._debounceTime),
distinctUntilChanged(),
tap(v => {
const queryParameters = new QueryParameters();
queryParameters.paging.pageSize = this._pageSize;
if (isNotNullNorUndefined(this.host.extraSearchQueryParam)) {
queryParameters.search.searchItems = MappingObjectUtil.copy(this.host.extraSearchQueryParam);
}
MappingObjectUtil.set(queryParameters.search.searchItems, (isNotNullNorUndefined(this.host.searchKey) ? this.host.searchKey : this.host.labelKey), v);
this._store.dispatch(new this.host.resourceNameSpace.GetAll(queryParameters, true));

Florent Poittevin
committed
}),
));
}
ngAfterViewInit(): void {
this.setFocusOnInput();
}
private setFocusOnInput(): void {
setTimeout(() => {
this.input.nativeElement.focus();
}, 0);
}
private _observeIsLoading(): void {
this.subscribe(this.isLoadingObs.pipe(
distinctUntilChanged(),
tap(isLoading => this.isLoading = isLoading),
));
}
private _observeList(): void {
this.subscribe(this.listObs.pipe(
distinctUntilChanged(),
tap(list => this.list = list),
));
}
Florent POITTEVIN
committed
computeHighlightText(valueElement: string): string {
const fc = this.form.get(this.host.formDefinition.search);
if (isNullOrUndefined(fc)) {
return valueElement;
}
const value = fc.value;
if (isNullOrUndefined(value) || isEmptyString(value)) {
return valueElement;
}
return valueElement.replace(new RegExp(value, "gi"), match => `<span class="highlight-text">${match}</span>`);
Florent POITTEVIN
committed
}