-
+

{{'DMP-LISTING.TEXT-INFO' | translate}}

{{'DMP-LISTING.TEXT-INFO-QUESTION' | translate}} {{'DMP-LISTING.LINK-ZENODO' | translate}} {{'DMP-LISTING.GET-IDEA' | translate}}

diff --git a/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts index d439693ef..4cf8e8ec1 100644 --- a/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts +++ b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts @@ -1,21 +1,16 @@ - -import { HttpClient } from '@angular/common/http'; import { Component, OnInit, ViewChild } from '@angular/core'; import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; -import { ActivatedRoute, Router } from '@angular/router'; -import { DescriptionStatus } from '@app/core/common/enum/description-status'; -import { DmpStatus } from '@app/core/common/enum/dmp-status'; -import { DmpVersionStatus } from '@app/core/common/enum/dmp-version-status'; +import { ActivatedRoute, Params, Router } from '@angular/router'; 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 { DescriptionTemplatesInSection, DmpBlueprint, DmpBlueprintDefinition, DmpBlueprintDefinitionSection } from '@app/core/model/dmp-blueprint/dmp-blueprint'; -import { Dmp, DmpDescriptionTemplate, DmpUser } from '@app/core/model/dmp/dmp'; +import { BaseDmp, 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'; @@ -26,31 +21,37 @@ import { AnalyticsService } from '@app/core/services/matomo/analytics-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 { BaseComponent } from '@common/base/base.component'; import { HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service'; -import { SortDirection } from '@common/modules/hybrid-listing/hybrid-listing.component'; -import { Guid } from '@common/types/guid'; +import { PageLoadEvent, SortDirection } from '@common/modules/hybrid-listing/hybrid-listing.component'; import { TranslateService } from '@ngx-translate/core'; import { NgDialogAnimationService } from "ng-dialog-animation"; -import { debounceTime, takeUntil } from 'rxjs/operators'; +import { debounceTime, takeUntil, tap } from 'rxjs/operators'; import { nameof } from 'ts-simple-nameof'; import { DmpFilterDialogComponent } from './filtering/dmp-filter-dialog/dmp-filter-dialog.component'; +import { BaseListingComponent } from '@common/base/base-listing-component'; +import { QueryResult } from '@common/model/query-result'; +import { Observable } from 'rxjs'; +import { UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { QueryParamsService } from '@app/core/services/utilities/query-params.service'; @Component({ selector: 'app-dmp-listing-component', templateUrl: 'dmp-listing.component.html', styleUrls: ['./dmp-listing.component.scss'], }) -export class DmpListingComponent extends BaseComponent implements OnInit { +export class DmpListingComponent extends BaseListingComponent implements OnInit { + + userSettingsKey = { key: 'DmpListingUserSettings' }; @ViewChild(MatPaginator, { static: true }) _paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; - lookup: DmpLookup = new DmpLookup(); + lookup: DmpLookup; groupId: string; totalCount: number; listingItems: any[] = []; isPublic: boolean = false; hasListingItems = null; + protected ITEMS_PER_PAGE = 5; pageSize: number = 5; public formGroup = new UntypedFormBuilder().group({ like: new UntypedFormControl(), @@ -78,63 +79,59 @@ export class DmpListingComponent extends BaseComponent implements OnInit { } constructor( + protected router: Router, + protected route: ActivatedRoute, + protected uiNotificationService: UiNotificationService, + protected httpErrorHandlingService: HttpErrorHandlingService, + protected queryParamsService: QueryParamsService, private dmpService: DmpService, - private router: Router, - private route: ActivatedRoute, public dialogAnimation: NgDialogAnimationService, public dialog: MatDialog, public enumUtils: EnumUtils, private language: TranslateService, - private httpErrorHandlingService: HttpErrorHandlingService, private authService: AuthService, private guidedTourService: GuidedTourService, - private httpClient: HttpClient, private analyticsService: AnalyticsService, ) { - super(); + super(router, route, uiNotificationService, httpErrorHandlingService, queryParamsService); } ngOnInit() { this.analyticsService.trackPageView(AnalyticsService.DmpListing); - this.isPublic = this.route.snapshot.data['isPublic'] ?? false; - if (this.isPublic) { - //TODO refactor - // this.formGroup.get('order').setValue(this.order.PUBLISHED); - } else { - this.formGroup.get('order').setValue(this.order.UpdatedAt); - } + if (!this.isPublic && !this.authService.currentAccountIsAuthenticated()) { this.router.navigateByUrl("/explore-plans"); } - this.route.params + + this.route.queryParamMap .pipe(takeUntil(this._destroyed)) - .subscribe(async params => { + .subscribe(async (params: Params) => { + const queryParams = this.route.snapshot.queryParams; - this.groupId = params['groupId']; + if (!this.lookup) this.lookup = queryParams['lookup'] ? this._parseLookupFromParams(queryParams) : this.initializeLookup(); - this.lookup.page = { size: this.pageSize, offset: 0 }; - this.lookup.order = { items: ['-' + nameof(x => x.updatedAt)] }; - this.lookup.metadata = { countAll: true }; - this.lookup.isActive = [IsActive.Active]; + if ((this.formGroup.get('order')?.value == null || (!this.isAscending && !this.isDescending)) && this.lookup.order.items && this.lookup.order.items.length > 0) { - if (this.groupId != null && Guid.isGuid(this.groupId)) { - this.lookup.groupIds = [Guid.parse(this.groupId)]; - this.lookup.versionStatuses = null; - } else { - this.lookup.versionStatuses = [DmpVersionStatus.Current, DmpVersionStatus.NotFinalized]; + let ordering = this.lookup.order.items[0]; + let sortBy = ordering.substring(1, ordering.length); + + this.formGroup.get('order').setValue(this._getRecentActivityOrder(sortBy)); + ordering.charAt(0) == '-' ? this.sortDirection = SortDirection.Descending : this.sortDirection = SortDirection.Ascending; } - - this.refresh(this.lookup); + + this.onPageLoad({ offset: this.lookup.page.offset / this.lookup.page.size } as PageLoadEvent); + // this.groupId = params['groupId']; + // if (this.groupId != null && Guid.isGuid(this.groupId)) { + // this.lookup.groupIds = [Guid.parse(this.groupId)]; + // } + // 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 => this.refresh(this.lookup)); } public dashboardTour: GuidedTour = { @@ -165,6 +162,48 @@ export class DmpListingComponent extends BaseComponent implements OnInit { this.scrollbar = this.hasScrollbar(); } + protected loadListing(): Observable> { + if (this.isPublic) { + return this.dmpService.publicQuery(this.lookup).pipe(takeUntil(this._destroyed)) + .pipe(tap(result => { + if (!result) { return []; } + this.totalCount = result.count; + if (this.lookup?.page?.offset === 0) this.listingItems = []; + this.listingItems.push(...result.items); + this.hasListingItems = true; + })); + } else { + return this.dmpService.query(this.lookup).pipe(takeUntil(this._destroyed)) + .pipe(tap(result => { + if (!result) { return []; } + this.totalCount = result.count; + if (this.lookup?.page?.offset === 0) this.listingItems = []; + this.listingItems.push(...result.items); + this.hasListingItems = true; + })); + } + } + + protected initializeLookup(): DmpLookup { + const lookup = new DmpLookup(); + lookup.metadata = { countAll: true }; + lookup.page = { offset: 0, size: this.ITEMS_PER_PAGE }; + lookup.isActive = [IsActive.Active]; + + let recentActivityOrder = this.isPublic ? this.toAscSortField(nameof(x => x.label)) : this.toDescSortField(nameof(x => x.updatedAt)); + lookup.order = { items: [recentActivityOrder] }; + + this.updateOrderUiFields(lookup.order); + + lookup.project = { + fields: this._lookupFields + }; + + return lookup; + } + + protected setupColumns() { } + openTour() { this.language.get('DMP-LISTING.TEXT-INFO').pipe(takeUntil(this._destroyed)).subscribe((x: string) => { this.dashboardTour.steps[0].title = x + '\n\n' + @@ -182,7 +221,8 @@ export class DmpListingComponent extends BaseComponent implements OnInit { loadMore() { this.lookup.page = { size: this.pageSize, offset: this.lookup.page.offset + this.pageSize }; - this.refresh(this.lookup); + + this.filterChanged(this.lookup, true); } orderByChanged() { @@ -193,105 +233,48 @@ export class DmpListingComponent extends BaseComponent implements OnInit { } else { this.lookup.order = { items: [this.sortingDirectionPrefix + nameof(x => x.updatedAt)] }; } - this.refresh(this.lookup); + this.filterChanged(this.lookup); } - private refresh(lookup: DmpLookup) { - lookup.project = { - fields: [ - nameof(x => x.id), - nameof(x => x.label), - nameof(x => x.description), - nameof(x => x.status), - nameof(x => x.accessType), - nameof(x => x.version), - nameof(x => x.versionStatus), - nameof(x => x.groupId), - nameof(x => x.updatedAt), - nameof(x => x.belongsToCurrentTenant), - nameof(x => x.finalizedAt), - nameof(x => x.hash), - [nameof(x => x.authorizationFlags), AppPermission.CreateNewVersionDmp].join('.'), - [nameof(x => x.authorizationFlags), AppPermission.DeleteDmp].join('.'), - [nameof(x => x.authorizationFlags), AppPermission.CloneDmp].join('.'), - [nameof(x => x.authorizationFlags), AppPermission.FinalizeDmp].join('.'), - [nameof(x => x.authorizationFlags), AppPermission.ExportDmp].join('.'), - [nameof(x => x.authorizationFlags), AppPermission.InviteDmpUsers].join('.'), - [nameof(x => x.authorizationFlags), AppPermission.AssignDmpUsers].join('.'), - [nameof(x => x.authorizationFlags), AppPermission.EditDmp].join('.'), + // private refresh(lookup: DmpLookup) { + // if (this.isPublic) { + // this.dmpService.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; + // }, + // error => this.httpErrorHandlingService.handleBackedRequestError(error)); - [nameof(x => x.descriptions), nameof(x => x.id)].join('.'), - [nameof(x => x.descriptions), nameof(x => x.label)].join('.'), - [nameof(x => x.descriptions), nameof(x => x.status)].join('.'), - [nameof(x => x.descriptions), nameof(x => x.descriptionTemplate), nameof(x => x.groupId)].join('.'), - [nameof(x => x.descriptions), nameof(x => x.dmpDescriptionTemplate), nameof(x => x.sectionId)].join('.'), - [nameof(x => x.descriptions), nameof(x => x.isActive)].join('.'), - - [nameof(x => x.blueprint), nameof(x => x.id)].join('.'), - [nameof(x => x.blueprint), nameof(x => x.label)].join('.'), - [nameof(x => x.blueprint), nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.id)].join('.'), - [nameof(x => x.blueprint), nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.label)].join('.'), - [nameof(x => x.blueprint), nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.hasTemplates)].join('.'), - [nameof(x => x.blueprint), nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.descriptionTemplates), nameof(x => x.descriptionTemplateGroupId)].join('.'), - - [nameof(x => x.dmpUsers), nameof(x => x.id)].join('.'), - [nameof(x => x.dmpUsers), nameof(x => x.user.id)].join('.'), - [nameof(x => x.dmpUsers), nameof(x => x.role)].join('.'), - [nameof(x => x.dmpUsers), nameof(x => x.dmp.id)].join('.'), - [nameof(x => x.dmpUsers), nameof(x => x.isActive)].join('.'), - - [nameof(x => x.dmpReferences), nameof(x => x.id)].join('.'), - [nameof(x => x.dmpReferences), nameof(x => x.reference), nameof(x => x.id)].join('.'), - [nameof(x => x.dmpReferences), nameof(x => x.reference), nameof(x => x.label)].join('.'), - [nameof(x => x.dmpReferences), nameof(x => x.reference), nameof(x => x.type), nameof(x => x.id)].join('.'), - [nameof(x => x.dmpReferences), nameof(x => x.isActive)].join('.'), - - [nameof(x => x.dmpDescriptionTemplates), nameof(x => x.sectionId)].join('.'), - [nameof(x => x.dmpDescriptionTemplates), nameof(x => x.descriptionTemplateGroupId)].join('.'), - [nameof(x => x.dmpDescriptionTemplates), nameof(x => x.isActive)].join('.'), - - ] - }; - - if (this.isPublic) { - this.dmpService.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; - }, - error => this.httpErrorHandlingService.handleBackedRequestError(error)); - - } else { - this.dmpService.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(x => { - if (x.descriptions) { - if (x.status == DmpStatus.Finalized) { - x.descriptions = x.descriptions.filter(x => x.isActive === IsActive.Active && x.status === DescriptionStatus.Finalized); - } else { - x.descriptions = x.descriptions.filter(x => x.isActive === IsActive.Active && x.status !== DescriptionStatus.Canceled); - } - } - x.dmpUsers = x.dmpUsers.filter(x => x.isActive === IsActive.Active); - this.listingItems.push(x); - }) - this.hasListingItems = true; - }, - error => this.httpErrorHandlingService.handleBackedRequestError(error)); - } - - } + // } else { + // this.dmpService.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(x => { + // if (x.descriptions) { + // if (x.status == DmpStatus.Finalized) { + // x.descriptions = x.descriptions.filter(x => x.isActive === IsActive.Active && x.status === DescriptionStatus.Finalized); + // } else { + // x.descriptions = x.descriptions.filter(x => x.isActive === IsActive.Active && x.status !== DescriptionStatus.Canceled); + // } + // } + // x.dmpUsers = x.dmpUsers.filter(x => x.isActive === IsActive.Active); + // this.listingItems.push(x); + // }) + // this.hasListingItems = true; + // }, + // error => this.httpErrorHandlingService.handleBackedRequestError(error)); + // } + // } controlModified(): void { this.lookup.like = this.formGroup.get("like").value; this.lookup.page = { size: this.pageSize, offset: 0 }; - this.refresh(this.lookup); + this.filterChanged(this.lookup, true); } @@ -319,9 +302,6 @@ export class DmpListingComponent extends BaseComponent implements OnInit { updateDataFn(filterForm: UntypedFormGroup): void { let testLookup = this.lookup; testLookup.from(filterForm); - // console.log('testLookup: ', testLookup); - // this.lookup.from(filterForm); - // this.refresh(this.lookup); } hasScrollbar(): boolean { @@ -349,12 +329,90 @@ export class DmpListingComponent extends BaseComponent implements OnInit { this.guidedTourService.startTour(this.dashboardTour); } - public hasLikeCriteria(): boolean { + hasLikeFilters(): boolean { return this.lookup.like !== undefined && this.lookup.like !== null; } - + toggleSortDirection(): void { this.sortDirection = this.isAscending ? this.sortDirection = SortDirection.Descending : this.sortDirection = SortDirection.Ascending; this.orderByChanged(); } + + private _parseLookupFromParams(params: Params): DmpLookup { + let lookup: DmpLookup = JSON.parse(params['lookup']); + + if (!lookup) return this.initializeLookup(); + + const queryOffset = 0; + const querySize = (lookup.page?.offset ?? 0) + this.pageSize; + lookup.page = { size: querySize, offset: queryOffset }; + lookup.project = { fields: this._lookupFields }; + lookup.metadata = { countAll: true }; + return lookup; + } + + private _getRecentActivityOrder(recentActivityOrderValue: string): RecentActivityOrder { + switch (recentActivityOrderValue) { + case nameof(x => x.updatedAt): return RecentActivityOrder.UpdatedAt; + case nameof(x => x.label): return RecentActivityOrder.Label; + case nameof(x => x.status): return RecentActivityOrder.Status; + } + } + + + private get _lookupFields(): string[] { + return [ + nameof(x => x.id), + nameof(x => x.label), + nameof(x => x.description), + nameof(x => x.status), + nameof(x => x.accessType), + nameof(x => x.version), + nameof(x => x.versionStatus), + nameof(x => x.groupId), + nameof(x => x.updatedAt), + nameof(x => x.belongsToCurrentTenant), + nameof(x => x.finalizedAt), + nameof(x => x.hash), + [nameof(x => x.authorizationFlags), AppPermission.CreateNewVersionDmp].join('.'), + [nameof(x => x.authorizationFlags), AppPermission.DeleteDmp].join('.'), + [nameof(x => x.authorizationFlags), AppPermission.CloneDmp].join('.'), + [nameof(x => x.authorizationFlags), AppPermission.FinalizeDmp].join('.'), + [nameof(x => x.authorizationFlags), AppPermission.ExportDmp].join('.'), + [nameof(x => x.authorizationFlags), AppPermission.InviteDmpUsers].join('.'), + [nameof(x => x.authorizationFlags), AppPermission.AssignDmpUsers].join('.'), + [nameof(x => x.authorizationFlags), AppPermission.EditDmp].join('.'), + + [nameof(x => x.descriptions), nameof(x => x.id)].join('.'), + [nameof(x => x.descriptions), nameof(x => x.label)].join('.'), + [nameof(x => x.descriptions), nameof(x => x.status)].join('.'), + [nameof(x => x.descriptions), nameof(x => x.descriptionTemplate), nameof(x => x.groupId)].join('.'), + [nameof(x => x.descriptions), nameof(x => x.dmpDescriptionTemplate), nameof(x => x.sectionId)].join('.'), + [nameof(x => x.descriptions), nameof(x => x.isActive)].join('.'), + + [nameof(x => x.blueprint), nameof(x => x.id)].join('.'), + [nameof(x => x.blueprint), nameof(x => x.label)].join('.'), + [nameof(x => x.blueprint), nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.id)].join('.'), + [nameof(x => x.blueprint), nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.label)].join('.'), + [nameof(x => x.blueprint), nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.hasTemplates)].join('.'), + [nameof(x => x.blueprint), nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.descriptionTemplates), nameof(x => x.descriptionTemplateGroupId)].join('.'), + + [nameof(x => x.dmpUsers), nameof(x => x.id)].join('.'), + [nameof(x => x.dmpUsers), nameof(x => x.user.id)].join('.'), + [nameof(x => x.dmpUsers), nameof(x => x.role)].join('.'), + [nameof(x => x.dmpUsers), nameof(x => x.dmp.id)].join('.'), + [nameof(x => x.dmpUsers), nameof(x => x.isActive)].join('.'), + + [nameof(x => x.dmpReferences), nameof(x => x.id)].join('.'), + [nameof(x => x.dmpReferences), nameof(x => x.reference), nameof(x => x.id)].join('.'), + [nameof(x => x.dmpReferences), nameof(x => x.reference), nameof(x => x.label)].join('.'), + [nameof(x => x.dmpReferences), nameof(x => x.reference), nameof(x => x.type), nameof(x => x.id)].join('.'), + [nameof(x => x.dmpReferences), nameof(x => x.isActive)].join('.'), + + [nameof(x => x.dmpDescriptionTemplates), nameof(x => x.sectionId)].join('.'), + [nameof(x => x.dmpDescriptionTemplates), nameof(x => x.descriptionTemplateGroupId)].join('.'), + [nameof(x => x.dmpDescriptionTemplates), nameof(x => x.isActive)].join('.'), + + ]; + } }