Files
dspace-angular/src/app/browse-by/browse-by-taxonomy/browse-by-taxonomy.component.ts
2024-03-06 17:19:31 +01:00

189 lines
5.8 KiB
TypeScript

import { Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core';
import { VocabularyOptions } from '../../core/submission/vocabularies/models/vocabulary-options.model';
import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
import { ActivatedRoute, Params, RouterLink } from '@angular/router';
import { BehaviorSubject, Observable, Subscription } from 'rxjs';
import { BrowseDefinition } from '../../core/shared/browse-definition.model';
import { map } from 'rxjs/operators';
import { HierarchicalBrowseDefinition } from '../../core/shared/hierarchical-browse-definition.model';
import { VocabularyTreeviewComponent } from '../../shared/form/vocabulary-treeview/vocabulary-treeview.component';
import { TranslateModule } from '@ngx-translate/core';
import { BrowseByDataType } from '../browse-by-switcher/browse-by-data-type';
import { Context } from '../../core/shared/context.model';
import { hasValue } from '../../shared/empty.util';
import { VarDirective } from '../../shared/utils/var.directive';
import { AsyncPipe, NgIf } from '@angular/common';
import { ComcolPageHeaderComponent } from '../../shared/comcol/comcol-page-header/comcol-page-header.component';
import { ComcolPageLogoComponent } from '../../shared/comcol/comcol-page-logo/comcol-page-logo.component';
import {
ThemedComcolPageHandleComponent
} from '../../shared/comcol/comcol-page-handle/themed-comcol-page-handle.component';
import { ComcolPageContentComponent } from '../../shared/comcol/comcol-page-content/comcol-page-content.component';
import { DsoEditMenuComponent } from '../../shared/dso-page/dso-edit-menu/dso-edit-menu.component';
import {
ThemedComcolPageBrowseByComponent
} from '../../shared/comcol/comcol-page-browse-by/themed-comcol-page-browse-by.component';
import { BrowseByComponent } from '../../shared/browse-by/browse-by.component';
import { ThemedLoadingComponent } from '../../shared/loading/themed-loading.component';
import { ThemedBrowseByComponent } from '../../shared/browse-by/themed-browse-by.component';
@Component({
selector: 'ds-browse-by-taxonomy',
templateUrl: './browse-by-taxonomy.component.html',
styleUrls: ['./browse-by-taxonomy.component.scss'],
imports: [
VarDirective,
AsyncPipe,
ComcolPageHeaderComponent,
ComcolPageLogoComponent,
NgIf,
ThemedComcolPageHandleComponent,
ComcolPageContentComponent,
DsoEditMenuComponent,
ThemedComcolPageBrowseByComponent,
BrowseByComponent,
TranslateModule,
ThemedLoadingComponent,
ThemedBrowseByComponent,
VocabularyTreeviewComponent,
RouterLink
],
standalone: true
})
/**
* Component for browsing items by metadata in a hierarchical controlled vocabulary
*/
export class BrowseByTaxonomyComponent implements OnInit, OnChanges, OnDestroy {
/**
* The optional context
*/
@Input() context: Context;
/**
* The {@link BrowseByDataType} of this Component
*/
@Input() browseByType: BrowseByDataType;
/**
* The ID of the {@link Community} or {@link Collection} of the scope to display
*/
@Input() scope: string;
/**
* Display the h1 title in the section
*/
@Input() displayTitle = true;
scope$: BehaviorSubject<string> = new BehaviorSubject(undefined);
/**
* The {@link VocabularyOptions} object
*/
vocabularyOptions: VocabularyOptions;
/**
* The selected vocabulary entries
*/
selectedItems: VocabularyEntryDetail[] = [];
/**
* The query parameters, contain the selected entries
*/
filterValues: string[];
/**
* The facet the use when filtering
*/
facetType: string;
/**
* The used vocabulary
*/
vocabularyName: string;
/**
* The parameters used in the URL
*/
queryParams: Params;
/**
* Resolved browse-by definition
*/
browseDefinition$: Observable<BrowseDefinition>;
/**
* Subscriptions to track
*/
subs: Subscription[] = [];
public constructor(
protected route: ActivatedRoute,
) {
}
ngOnInit(): void {
this.browseDefinition$ = this.route.data.pipe(
map((data: { browseDefinition: BrowseDefinition }) => {
return data.browseDefinition;
})
);
this.subs.push(this.browseDefinition$.subscribe((browseDefinition: HierarchicalBrowseDefinition) => {
this.facetType = browseDefinition.facetType;
this.vocabularyName = browseDefinition.vocabulary;
this.vocabularyOptions = {name: this.vocabularyName, closed: true};
}));
this.subs.push(this.scope$.subscribe(() => {
this.updateQueryParams();
}));
}
ngOnChanges(): void {
this.scope$.next(this.scope);
}
/**
* Adds detail to selectedItems, transforms it to be used as query parameter
* and adds that to filterValues.
*
* @param detail VocabularyEntryDetail to be added
*/
onSelect(detail: VocabularyEntryDetail): void {
this.selectedItems.push(detail);
this.filterValues = this.selectedItems
.map((item: VocabularyEntryDetail) => `${item.value},equals`);
this.updateQueryParams();
}
/**
* Removes detail from selectedItems and filterValues.
*
* @param detail VocabularyEntryDetail to be removed
*/
onDeselect(detail: VocabularyEntryDetail): void {
this.selectedItems = this.selectedItems.filter((entry: VocabularyEntryDetail) => {
return entry.id !== detail.id;
});
this.filterValues = this.filterValues.filter((value: string) => {
return value !== `${detail.value},equals`;
});
this.updateQueryParams();
}
/**
* Updates queryParams based on the current facetType and filterValues.
*/
updateQueryParams(): void {
this.queryParams = {
['f.' + this.facetType]: this.filterValues
};
if (hasValue(this.scope)) {
this.queryParams.scope = this.scope;
}
}
ngOnDestroy(): void {
this.subs.forEach((sub: Subscription) => sub.unsubscribe());
}
}