argos/dmp-frontend/src/app/ui/description/listing/description-listing.compone...

387 lines
15 KiB
TypeScript

import { HttpClient } from '@angular/common/http';
import { Component, OnInit, ViewChild } from '@angular/core';
import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { DescriptionStatus } from '@app/core/common/enum/description-status';
import { IsActive } from '@app/core/common/enum/is-active.enum';
import { AppPermission } from '@app/core/common/enum/permission.enum';
import { RecentActivityOrder } from '@app/core/common/enum/recent-activity-order';
import { DescriptionTemplate } from '@app/core/model/description-template/description-template';
import { Description } from '@app/core/model/description/description';
import { Dmp, DmpDescriptionTemplate, DmpUser } from '@app/core/model/dmp/dmp';
import { DmpReference } from '@app/core/model/dmp/dmp-reference';
import { ReferenceType } from '@app/core/model/reference-type/reference-type';
import { Reference } from '@app/core/model/reference/reference';
import { DescriptionLookup } from '@app/core/query/description.lookup';
import { DmpLookup } from '@app/core/query/dmp.lookup';
import { AuthService } from '@app/core/services/auth/auth.service';
import { DescriptionService } from '@app/core/services/description/description.service';
import { DmpService } from '@app/core/services/dmp/dmp.service';
import { MatomoService } from '@app/core/services/matomo/matomo-service';
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
import { GuidedTour, Orientation } from '@app/library/guided-tour/guided-tour.constants';
import { GuidedTourService } from '@app/library/guided-tour/guided-tour.service';
import { StartNewDmpDialogComponent } from '@app/ui/dmp/new/start-new-dmp-dialogue/start-new-dmp-dialog.component';
// import { IBreadCrumbComponent } from '@app/ui/misc/breadcrumb/definition/IBreadCrumbComponent';
// import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item';
import { BaseComponent } from '@common/base/base.component';
import { Guid } from '@common/types/guid';
import { TranslateService } from '@ngx-translate/core';
import { debounceTime, takeUntil } from 'rxjs/operators';
import { nameof } from 'ts-simple-nameof';
import { StartNewDescriptionDialogComponent } from '../start-new-description-dialog/start-new-description-dialog.component';
@Component({
selector: 'app-description-listing-component',
templateUrl: 'description-listing.component.html',
styleUrls: ['./description-listing.component.scss']
})
export class DescriptionListingComponent extends BaseComponent implements OnInit {//IBreadCrumbComponent
@ViewChild(MatPaginator, { static: true }) _paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
// @ViewChild(DescriptionCriteriaComponent, { static: true }) criteria: DescriptionCriteriaComponent;
// breadCrumbs: Observable<BreadcrumbItem[]>;
titlePrefix: String;
dmpId: string;
status: Number;
totalCount: number;
dmpSearchEnabled = true;
listingItems: any[] = [];
hasListingItems = null;
isPublic: boolean = false;
public isVisible = true
pageSize: number = 5;
lookup: DescriptionLookup = new DescriptionLookup();
criteriaFormGroup: UntypedFormGroup;
public formGroup = new UntypedFormBuilder().group({
like: new UntypedFormControl(),
order: new UntypedFormControl()
});
scrollbar: boolean;
order = RecentActivityOrder;
dmpText: string;
descriptionText: string;
constructor(
private descriptionService: DescriptionService,
private router: Router,
private route: ActivatedRoute,
public dialog: MatDialog,
private language: TranslateService,
private authService: AuthService,
public enumUtils: EnumUtils,
private authentication: AuthService,
private guidedTourService: GuidedTourService,
private httpClient: HttpClient,
private matomoService: MatomoService,
private fb: UntypedFormBuilder,
) {
super();
}
ngOnInit() {
this.matomoService.trackPageView('Descriptions');
this.isPublic = this.router.url === '/explore-descriptions';
if (this.isPublic) {
//TODO: refactor
// this.formGroup.get('order').setValue(this.order.DATASETPUBLISHED);
} else {
this.formGroup.get('order').setValue(this.order.UpdatedAt);
}
if (!this.isPublic && !this.authService.currentAccountIsAuthenticated()) {
this.router.navigateByUrl("/explore");
}
this.route.params
.pipe(takeUntil(this._destroyed))
.subscribe(async (params: Params) => {
const queryParams = this.route.snapshot.queryParams;
this.dmpId = queryParams['dmpId'];
this.status = queryParams['status'];
this.lookup.page = { size: this.pageSize, offset: 0 };
this.lookup.order = { items: ['-' + nameof<Description>(x => x.updatedAt)] };
this.lookup.metadata = { countAll: true };
this.lookup.isActive = [IsActive.Active];
if (this.dmpId != null && Guid.isGuid(this.dmpId)) {
this.dmpSearchEnabled = false;
//const dmp = await this.dmpService.getSingle(this.dmpId).toPromise();
this.lookup.dmpSubQuery = new DmpLookup();
this.lookup.dmpSubQuery.ids = [Guid.parse(this.dmpId)];
if (params['dmpLabel'] !== undefined) {
this.titlePrefix = 'for ' + params['dmpLabel'];
}
}
if (this.status != null && this.status == DescriptionStatus.Draft) { //TODO: chack if actually used
this.lookup.statuses = [DescriptionStatus.Draft]
}
this.refresh(this.lookup);
});
this.formGroup.get('like').valueChanges
.pipe(takeUntil(this._destroyed), debounceTime(500))
.subscribe(x => this.controlModified());
this.formGroup.get('order').valueChanges
.pipe(takeUntil(this._destroyed))
.subscribe(x => {
const fields: Array<string> = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '' : "-") + this.formGroup.get('order').value];
this.lookup.order = { items: fields };
this.lookup.page = { size: this.pageSize, offset: 0 };
this.refresh(this.lookup);
});
}
ngAfterContentChecked(): void {
this.scrollbar = this.hasScrollbar();
}
public dashboardTour: GuidedTour = {
tourId: 'dmp-description-tour',
useOrb: true,
steps: [
{
selector: '.dmp-tour',
content: 'Step 1',
orientation: Orientation.Right,
isStepUnique: false
},
{
selector: '.description-tour',
content: 'Step 2',
orientation: Orientation.Right,
isStepUnique: false
}
]
};
public isAuthenticated(): boolean {
return this.authService.currentAccountIsAuthenticated();
}
controlModified(): void {
this.lookup.like = this.formGroup.get("like").value;
this.lookup.page = { size: this.pageSize, offset: 0 };
this.refresh(this.lookup);
}
loadMore() {
this.lookup.page = { size: this.pageSize, offset: this.lookup.page.offset + this.pageSize };
this.refresh(this.lookup);
}
orderByChanged(){
if (this.formGroup.get('order').value == RecentActivityOrder.Status){
this.lookup.order = { items: ['-' + nameof<Dmp>(x => x.status)] };
} else if(this.formGroup.get('order').value == RecentActivityOrder.Label){
this.lookup.order = { items: ['-' + nameof<Dmp>(x => x.label)] };
}else{
this.lookup.order = { items: ['-' + nameof<Dmp>(x => x.updatedAt)] };
}
this.refresh(this.lookup);
}
private refresh(lookup: DescriptionLookup) {
lookup.project = {
fields: [
nameof<Description>(x => x.id),
nameof<Description>(x => x.label),
nameof<Description>(x => x.status),
nameof<Description>(x => x.updatedAt),
[nameof<Description>(x => x.authorizationFlags), AppPermission.EditDescription].join('.'),
[nameof<Description>(x => x.authorizationFlags), AppPermission.DeleteDescription].join('.'),
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.id)].join('.'),
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.label)].join('.'),
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.groupId)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.id)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.label)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.status)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.accessType)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.id)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.user.id)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.role)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.id)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.id)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.label)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.type), nameof<ReferenceType>(x => x.id)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.reference)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.isActive)].join('.'),
[nameof<Description>(x => x.dmpDescriptionTemplate), nameof<DmpDescriptionTemplate>(x => x.id)].join('.'),
[nameof<Description>(x => x.dmpDescriptionTemplate), nameof<DmpDescriptionTemplate>(x => x.dmp), nameof<Dmp>(x => x.id)].join('.'),
[nameof<Description>(x => x.dmpDescriptionTemplate), nameof<DmpDescriptionTemplate>(x => x.descriptionTemplateGroupId)].join('.'),
[nameof<Description>(x => x.dmpDescriptionTemplate), nameof<DmpDescriptionTemplate>(x => x.sectionId)].join('.'),
]
};
if(this.isPublic){
this.descriptionService.publicQuery(lookup).pipe(takeUntil(this._destroyed))
.subscribe(result => {
if (!result) { return []; }
this.totalCount = result.count;
if (lookup?.page?.offset === 0) this.listingItems = [];
this.listingItems.push(...result.items);
this.hasListingItems = true;
});
}else{
this.descriptionService.query(lookup).pipe(takeUntil(this._destroyed))
.subscribe(result => {
if (!result) { return []; }
this.totalCount = result.count;
if (lookup?.page?.offset === 0) this.listingItems = [];
result.items.forEach(description => {
if (description.status != DescriptionStatus.Canceled) this.listingItems.push(description);
})
this.hasListingItems = true;
});
}
}
openFiltersDialog(): void {
//TODO: Add filters dialog
// const dialogRef = this.dialog.open(DescriptionCriteriaDialogComponent, {
// width: '456px',
// height: '100%',
// id: 'filters',
// restoreFocus: false,
// data: {
// isPublic: this.isPublic,
// status: this.status,
// criteria: this.criteria,
// formGroup: this.criteriaFormGroup,
// // criteria: this.grantId ? this.criteria : this.getDefaultCriteria(),
// updateDataFn: this.updateDataFn.bind(this)
// },
// position: { right: '0px;' },
// panelClass: 'dialog-side-panel'
// });
// dialogRef.afterClosed().subscribe(result => {
// });
}
// updateDataFn(criteria: DescriptionCriteriaComponent): void {
// this.criteriaFormGroup = criteria.formGroup;
// this.toDescriptionCriteria(criteria);
// this.refresh();
// }
// toDescriptionCriteria(criteria: DescriptionCriteriaComponent) {
// let formGroup = criteria.formGroup;
// this.criteria = {
// like: formGroup.get("like").value,
// status: formGroup.get("status").value,
// allVersions: formGroup.get("allVersions").value,
// role: formGroup.get("role").value
// }
// if (formGroup.get("tags") && formGroup.get("tags").value) {
// this.criteria.tags = formGroup.get("tags").value.map(x => (<ExternalTagEditorModel>x));
// }
// if (formGroup.get("collaborators") && formGroup.get("collaborators").value) {
// this.criteria.collaborators = formGroup.get("collaborators").value.map(x => x.id);
// }
// if (formGroup.get("dmpIds") && formGroup.get("dmpIds").value) {
// this.criteria.dmpIds = formGroup.get("dmpIds").value.map(x => x.id);
// }
// if (formGroup.get("groupIds") && formGroup.get("groupIds").value) {
// this.criteria.groupIds = formGroup.get("groupIds").value.map(x => x.groupId);
// }
// if (formGroup.get("grants") && formGroup.get("grants").value) {
// this.criteria.grants = formGroup.get("grants").value.map(x => x.id);
// }
// if (formGroup.get("organisations") && formGroup.get("organisations").value) {
// this.criteria.organisations = formGroup.get("organisations").value.map(x => x.id);
// }
// if (formGroup.get("descriptionTemplates") && formGroup.get("descriptionTemplates").value) {
// this.criteria.descriptionTemplates = formGroup.get("descriptionTemplates").value.map(x => x.id)
// }
// if (formGroup.get("grantStatus") && formGroup.get("grantStatus").value) {
// this.criteria.grantStatus = formGroup.get("grantStatus").value;
// }
// this.criteria.isPublic = this.isPublic;
// }
hasScrollbar(): boolean {
return document.getElementById("main-page").scrollHeight > document.documentElement.clientHeight
}
public restartTour(): void {
this.setDashboardTourDmpText();
this.setDashboardTourDescriptionText();
this.guidedTourService.startTour(this.dashboardTour);
}
public setDashboardTourDmpText(): void {
this.dmpText = this.language.instant('DESCRIPTION-LISTING.TEXT-INFO') + '\n\n' +
this.language.instant('DESCRIPTION-LISTING.TEXT-INFO-QUESTION') + ' ' +
this.language.instant('DESCRIPTION-LISTING.LINK-ZENODO') + ' ' +
this.language.instant('DESCRIPTION-LISTING.GET-IDEA');
this.dashboardTour.steps[0].title = this.dmpText;
}
public setDashboardTourDescriptionText(): void {
this.descriptionText = this.language.instant('DESCRIPTION-LISTING.TEXT-INFO') +
this.language.instant('DESCRIPTION-LISTING.LINK-PUBLIC-DATASETS') + ' ' +
this.language.instant('DESCRIPTION-LISTING.TEXT-INFO-REST') + '\n\n' +
this.language.instant('DESCRIPTION-LISTING.TEXT-INFO-PAR');
this.dashboardTour.steps[1].title = this.descriptionText;
}
openNewDmpDialog() {
if (this.dialog.openDialogs.length > 0) {
this.dialog.closeAll();
}
else {
const dialogRef = this.dialog.open(StartNewDmpDialogComponent, {
disableClose: false,
data: {
isDialog: true
}
});
}
}
addNewDescription() {
const formGroup = this.fb.group({
dmpId: this.fb.control(null, Validators.required),
})
const dialogRef = this.dialog.open(StartNewDescriptionDialogComponent, {
disableClose: false,
restoreFocus: false,
data: {
startNewDmp: false,
formGroup: formGroup,
}
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
if (result) {
if (result.startNewDmp) {
this.openNewDmpDialog();
} else {
this.router.navigate(['/plans', 'edit', result.formGroup.get('dmpId').value]);
}
}
});
}
hasLikeCriteria(): boolean {
return this.lookup.like !== undefined && this.lookup.like !== null;
}
}