mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
[CST-3088] added management of hierarchical vocabulary on typeahead component
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
</ul>
|
||||
</ng-template>
|
||||
|
||||
<div class="position-relative right-addon">
|
||||
<div *ngIf="!(isHierarchicalVocabulary() | async)" class="position-relative right-addon">
|
||||
<i *ngIf="searching" class="fas fa-circle-notch fa-spin fa-2x fa-fw text-primary position-absolute mt-1 p-0" aria-hidden="true"></i>
|
||||
<i *ngIf="!searching"
|
||||
dsAuthorityConfidenceState
|
||||
@@ -49,3 +49,20 @@
|
||||
|
||||
<div class="invalid-feedback" *ngIf="searchFailed">Sorry, suggestions could not be loaded.</div>
|
||||
</div>
|
||||
|
||||
<input *ngIf="(isHierarchicalVocabulary() | async)"
|
||||
class="form-control custom-select"
|
||||
[attr.autoComplete]="model.autoComplete"
|
||||
[class.is-invalid]="showErrorMessages"
|
||||
[dynamicId]="bindId && model.id"
|
||||
[name]="model.name"
|
||||
[placeholder]="model.placeholder"
|
||||
[readonly]="model.readOnly"
|
||||
[type]="model.inputType"
|
||||
[value]="currentValue?.display"
|
||||
(focus)="onFocus($event)"
|
||||
(change)="onChange($event)"
|
||||
(click)="openTree($event)"
|
||||
(keydown)="$event.preventDefault()"
|
||||
(keypress)="$event.preventDefault()"
|
||||
(keyup)="$event.preventDefault()">
|
||||
|
@@ -16,3 +16,8 @@
|
||||
color: $dropdown-link-hover-color !important;
|
||||
background-color: $dropdown-link-hover-bg !important;
|
||||
}
|
||||
|
||||
.treeview .modal-body {
|
||||
max-height: 85vh !important;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
@@ -2,13 +2,23 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, View
|
||||
import { FormGroup } from '@angular/forms';
|
||||
|
||||
import { DynamicFormLayoutService, DynamicFormValidationService } from '@ng-dynamic-forms/core';
|
||||
import { catchError, debounceTime, distinctUntilChanged, filter, map, merge, switchMap, tap } from 'rxjs/operators';
|
||||
import { Observable, of as observableOf, Subject } from 'rxjs';
|
||||
import { NgbTypeahead, NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap';
|
||||
import {
|
||||
catchError,
|
||||
debounceTime,
|
||||
distinctUntilChanged,
|
||||
filter,
|
||||
map,
|
||||
merge,
|
||||
switchMap,
|
||||
take,
|
||||
tap
|
||||
} from 'rxjs/operators';
|
||||
import { Observable, of as observableOf, Subject, Subscription } from 'rxjs';
|
||||
import { NgbModal, NgbModalRef, NgbTypeahead, NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap';
|
||||
|
||||
import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service';
|
||||
import { DynamicTypeaheadModel } from './dynamic-typeahead.model';
|
||||
import { isEmpty, isNotEmpty, isNotNull } from '../../../../../empty.util';
|
||||
import { hasValue, isEmpty, isNotEmpty, isNotNull } from '../../../../../empty.util';
|
||||
import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model';
|
||||
import { ConfidenceType } from '../../../../../../core/shared/confidence-type';
|
||||
import { getFirstSucceededRemoteDataPayload } from '../../../../../../core/shared/operators';
|
||||
@@ -16,6 +26,9 @@ import { PaginatedList } from '../../../../../../core/data/paginated-list';
|
||||
import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model';
|
||||
import { PageInfo } from '../../../../../../core/shared/page-info.model';
|
||||
import { DsDynamicVocabularyComponent } from '../dynamic-vocabulary.component';
|
||||
import { Vocabulary } from '../../../../../../core/submission/vocabularies/models/vocabulary.model';
|
||||
import { VocabularyTreeviewComponent } from '../../../../../vocabulary-treeview/vocabulary-treeview.component';
|
||||
import { VocabularyEntryDetail } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-dynamic-typeahead',
|
||||
@@ -40,10 +53,15 @@ export class DsDynamicTypeaheadComponent extends DsDynamicVocabularyComponent im
|
||||
click$ = new Subject<string>();
|
||||
currentValue: any;
|
||||
inputValue: any;
|
||||
preloadLevel: number;
|
||||
|
||||
private vocabulary$: Observable<Vocabulary>;
|
||||
private subs: Subscription[] = [];
|
||||
|
||||
constructor(protected vocabularyService: VocabularyService,
|
||||
private cdr: ChangeDetectorRef,
|
||||
protected cdr: ChangeDetectorRef,
|
||||
protected layoutService: DynamicFormLayoutService,
|
||||
protected modalService: NgbModal,
|
||||
protected validationService: DynamicFormValidationService
|
||||
) {
|
||||
super(vocabularyService, layoutService, validationService);
|
||||
@@ -100,6 +118,10 @@ export class DsDynamicTypeaheadComponent extends DsDynamicVocabularyComponent im
|
||||
this.setCurrentValue(this.model.value, true);
|
||||
}
|
||||
|
||||
this.vocabulary$ = this.vocabularyService.findVocabularyById(this.model.vocabularyOptions.name).pipe(
|
||||
getFirstSucceededRemoteDataPayload()
|
||||
);
|
||||
|
||||
this.group.get(this.model.id).valueChanges.pipe(
|
||||
filter((value) => this.currentValue !== value))
|
||||
.subscribe((value) => {
|
||||
@@ -116,6 +138,15 @@ export class DsDynamicTypeaheadComponent extends DsDynamicVocabularyComponent im
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if configured vocabulary is Hierarchical or not
|
||||
*/
|
||||
isHierarchicalVocabulary(): Observable<boolean> {
|
||||
return this.vocabulary$.pipe(
|
||||
map((result: Vocabulary) => result.hierarchical)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the input value with a FormFieldMetadataValueObject
|
||||
* @param event
|
||||
@@ -169,6 +200,28 @@ export class DsDynamicTypeaheadComponent extends DsDynamicVocabularyComponent im
|
||||
this.dispatchUpdate(event.item);
|
||||
}
|
||||
|
||||
openTree(event) {
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
this.subs.push(this.vocabulary$.pipe(
|
||||
map((vocabulary: Vocabulary) => vocabulary.preloadLevel),
|
||||
take(1)
|
||||
).subscribe((preloadLevel) => {
|
||||
const modalRef: NgbModalRef = this.modalService.open(VocabularyTreeviewComponent, { size: 'lg', windowClass: 'treeview' });
|
||||
modalRef.componentInstance.vocabularyOptions = this.model.vocabularyOptions;
|
||||
modalRef.componentInstance.preloadLevel = preloadLevel;
|
||||
modalRef.componentInstance.selectedItem = this.currentValue ? this.currentValue : '';
|
||||
modalRef.result.then((result: VocabularyEntryDetail) => {
|
||||
if (result) {
|
||||
this.currentValue = result;
|
||||
this.dispatchUpdate(result);
|
||||
}
|
||||
}, () => {
|
||||
return;
|
||||
});
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback functions for whenClickOnConfidenceNotAccepted event
|
||||
*/
|
||||
@@ -204,4 +257,10 @@ export class DsDynamicTypeaheadComponent extends DsDynamicVocabularyComponent im
|
||||
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.subs
|
||||
.filter((sub) => hasValue(sub))
|
||||
.forEach((sub) => sub.unsubscribe());
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user