mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-08 02:24:11 +00:00
[CST-3088] added management of hierarchical vocabulary on typeahead component
This commit is contained in:
@@ -20,7 +20,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</ng-template>
|
</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" 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"
|
<i *ngIf="!searching"
|
||||||
dsAuthorityConfidenceState
|
dsAuthorityConfidenceState
|
||||||
@@ -49,3 +49,20 @@
|
|||||||
|
|
||||||
<div class="invalid-feedback" *ngIf="searchFailed">Sorry, suggestions could not be loaded.</div>
|
<div class="invalid-feedback" *ngIf="searchFailed">Sorry, suggestions could not be loaded.</div>
|
||||||
</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;
|
color: $dropdown-link-hover-color !important;
|
||||||
background-color: $dropdown-link-hover-bg !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 { FormGroup } from '@angular/forms';
|
||||||
|
|
||||||
import { DynamicFormLayoutService, DynamicFormValidationService } from '@ng-dynamic-forms/core';
|
import { DynamicFormLayoutService, DynamicFormValidationService } from '@ng-dynamic-forms/core';
|
||||||
import { catchError, debounceTime, distinctUntilChanged, filter, map, merge, switchMap, tap } from 'rxjs/operators';
|
import {
|
||||||
import { Observable, of as observableOf, Subject } from 'rxjs';
|
catchError,
|
||||||
import { NgbTypeahead, NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap';
|
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 { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service';
|
||||||
import { DynamicTypeaheadModel } from './dynamic-typeahead.model';
|
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 { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model';
|
||||||
import { ConfidenceType } from '../../../../../../core/shared/confidence-type';
|
import { ConfidenceType } from '../../../../../../core/shared/confidence-type';
|
||||||
import { getFirstSucceededRemoteDataPayload } from '../../../../../../core/shared/operators';
|
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 { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model';
|
||||||
import { PageInfo } from '../../../../../../core/shared/page-info.model';
|
import { PageInfo } from '../../../../../../core/shared/page-info.model';
|
||||||
import { DsDynamicVocabularyComponent } from '../dynamic-vocabulary.component';
|
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({
|
@Component({
|
||||||
selector: 'ds-dynamic-typeahead',
|
selector: 'ds-dynamic-typeahead',
|
||||||
@@ -40,10 +53,15 @@ export class DsDynamicTypeaheadComponent extends DsDynamicVocabularyComponent im
|
|||||||
click$ = new Subject<string>();
|
click$ = new Subject<string>();
|
||||||
currentValue: any;
|
currentValue: any;
|
||||||
inputValue: any;
|
inputValue: any;
|
||||||
|
preloadLevel: number;
|
||||||
|
|
||||||
|
private vocabulary$: Observable<Vocabulary>;
|
||||||
|
private subs: Subscription[] = [];
|
||||||
|
|
||||||
constructor(protected vocabularyService: VocabularyService,
|
constructor(protected vocabularyService: VocabularyService,
|
||||||
private cdr: ChangeDetectorRef,
|
protected cdr: ChangeDetectorRef,
|
||||||
protected layoutService: DynamicFormLayoutService,
|
protected layoutService: DynamicFormLayoutService,
|
||||||
|
protected modalService: NgbModal,
|
||||||
protected validationService: DynamicFormValidationService
|
protected validationService: DynamicFormValidationService
|
||||||
) {
|
) {
|
||||||
super(vocabularyService, layoutService, validationService);
|
super(vocabularyService, layoutService, validationService);
|
||||||
@@ -100,6 +118,10 @@ export class DsDynamicTypeaheadComponent extends DsDynamicVocabularyComponent im
|
|||||||
this.setCurrentValue(this.model.value, true);
|
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(
|
this.group.get(this.model.id).valueChanges.pipe(
|
||||||
filter((value) => this.currentValue !== value))
|
filter((value) => this.currentValue !== value))
|
||||||
.subscribe((value) => {
|
.subscribe((value) => {
|
||||||
@@ -116,6 +138,15 @@ export class DsDynamicTypeaheadComponent extends DsDynamicVocabularyComponent im
|
|||||||
this.cdr.detectChanges();
|
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
|
* Update the input value with a FormFieldMetadataValueObject
|
||||||
* @param event
|
* @param event
|
||||||
@@ -169,6 +200,28 @@ export class DsDynamicTypeaheadComponent extends DsDynamicVocabularyComponent im
|
|||||||
this.dispatchUpdate(event.item);
|
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
|
* 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