-
+
@@ -29,12 +29,11 @@
- - +
diff --git a/dmp-frontend/src/app/ui/description/listing/description-listing.component.scss b/dmp-frontend/src/app/ui/description/listing/description-listing.component.scss index c8c27591b..0092defe6 100644 --- a/dmp-frontend/src/app/ui/description/listing/description-listing.component.scss +++ b/dmp-frontend/src/app/ui/description/listing/description-listing.component.scss @@ -123,6 +123,12 @@ right: 0px; z-index: 100; width: 37px; + + .filter-icon { + width: 1.5rem; + height: 1.5rem; + font-size: 1.5rem; + } } .filter-btn button { diff --git a/dmp-frontend/src/app/ui/description/listing/description-listing.component.ts b/dmp-frontend/src/app/ui/description/listing/description-listing.component.ts index 70378eaba..f793cb4a6 100644 --- a/dmp-frontend/src/app/ui/description/listing/description-listing.component.ts +++ b/dmp-frontend/src/app/ui/description/listing/description-listing.component.ts @@ -17,7 +17,7 @@ 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 { DescriptionFilter, 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'; @@ -35,6 +35,7 @@ import { debounceTime, map, takeUntil } from 'rxjs/operators'; import { nameof } from 'ts-simple-nameof'; import { StartNewDescriptionDialogComponent } from '../start-new-description-dialog/start-new-description-dialog.component'; import { RouterUtilsService } from '@app/core/services/router/router-utils.service'; +import { DescriptionFilterDialogComponent } from './filtering/description-filter-dialogue/description-filter-dialog.component'; @Component({ selector: 'app-description-listing-component', @@ -59,7 +60,6 @@ export class DescriptionListingComponent extends BaseComponent implements OnInit pageSize: number = 5; lookup: DescriptionLookup = new DescriptionLookup(); - criteriaFormGroup: UntypedFormGroup; public formGroup = new UntypedFormBuilder().group({ like: new UntypedFormControl(), order: new UntypedFormControl() @@ -135,6 +135,7 @@ export class DescriptionListingComponent extends BaseComponent implements OnInit //const dmp = await this.dmpService.getSingle(this.dmpId).toPromise(); this.lookup.dmpSubQuery = new DmpLookup(); this.lookup.dmpSubQuery.ids = [Guid.parse(this.dmpId)]; + this.lookup.associatedDmpIds.push(Guid.parse(this.dmpId)); if (params['dmpLabel'] !== undefined) { this.titlePrefix = 'for ' + params['dmpLabel']; } @@ -280,8 +281,28 @@ export class DescriptionListingComponent extends BaseComponent implements OnInit openFiltersDialog(): void { //TODO: Add filters dialog + const dialogRef = this.dialog.open(DescriptionFilterDialogComponent, { + width: '456px', + height: '100%', + id: 'filters', + restoreFocus: false, + position: { right: '0px;' }, + panelClass: 'dialog-side-panel', + data: { + isPublic: this.isPublic ?? true, + filterForm: this.lookup.buildForm(), + updateDataFn: this.updateDataFn.bind(this) + } + }); } + 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 { return document.getElementById("main-page").scrollHeight > document.documentElement.clientHeight @@ -346,7 +367,7 @@ export class DescriptionListingComponent extends BaseComponent implements OnInit }); } - hasLikeCriteria(): boolean { + hasLikeFilters(): boolean { return this.lookup.like !== undefined && this.lookup.like !== null; } diff --git a/dmp-frontend/src/app/ui/description/listing/description-listing.module.ts b/dmp-frontend/src/app/ui/description/listing/description-listing.module.ts index 921643574..125a4f868 100644 --- a/dmp-frontend/src/app/ui/description/listing/description-listing.module.ts +++ b/dmp-frontend/src/app/ui/description/listing/description-listing.module.ts @@ -7,6 +7,9 @@ import { CommonUiModule } from '@common/ui/common-ui.module'; import { DescriptionListingRoutingModule } from './description-listing.routing'; import { DescriptionCopyDialogModule } from '../description-copy-dialog/description-copy-dialog.module'; import { StartNewDescriptionDialogModule } from '../start-new-description-dialog/start-new-description-dialog.module'; +import { DescriptionFilterDialogComponent } from './filtering/description-filter-dialogue/description-filter-dialog.component'; +import { DescriptionFilterComponent } from './filtering/description-filter.component'; +import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module'; @NgModule({ imports: [ @@ -15,11 +18,14 @@ import { StartNewDescriptionDialogModule } from '../start-new-description-dialog FormattingModule, DescriptionCopyDialogModule, StartNewDescriptionDialogModule, - DescriptionListingRoutingModule + DescriptionListingRoutingModule, + AutoCompleteModule, ], declarations: [ DescriptionListingComponent, DescriptionListingItemComponent, + DescriptionFilterDialogComponent, + DescriptionFilterComponent, ], exports: [ DescriptionListingItemComponent diff --git a/dmp-frontend/src/app/ui/description/listing/filtering/description-filter-dialogue/description-filter-dialog.component.html b/dmp-frontend/src/app/ui/description/listing/filtering/description-filter-dialogue/description-filter-dialog.component.html new file mode 100644 index 000000000..39e50ef77 --- /dev/null +++ b/dmp-frontend/src/app/ui/description/listing/filtering/description-filter-dialogue/description-filter-dialog.component.html @@ -0,0 +1,7 @@ + +clear + diff --git a/dmp-frontend/src/app/ui/description/listing/criteria/dataset-criteria-dialogue/dataset-criteria-dialog.component.scss b/dmp-frontend/src/app/ui/description/listing/filtering/description-filter-dialogue/description-filter-dialog.component.scss similarity index 100% rename from dmp-frontend/src/app/ui/description/listing/criteria/dataset-criteria-dialogue/dataset-criteria-dialog.component.scss rename to dmp-frontend/src/app/ui/description/listing/filtering/description-filter-dialogue/description-filter-dialog.component.scss diff --git a/dmp-frontend/src/app/ui/description/listing/filtering/description-filter-dialogue/description-filter-dialog.component.ts b/dmp-frontend/src/app/ui/description/listing/filtering/description-filter-dialogue/description-filter-dialog.component.ts new file mode 100644 index 000000000..48f37cb96 --- /dev/null +++ b/dmp-frontend/src/app/ui/description/listing/filtering/description-filter-dialogue/description-filter-dialog.component.ts @@ -0,0 +1,44 @@ +import { Component, Inject, OnInit, ViewChild } from '@angular/core'; +import { UntypedFormGroup } from '@angular/forms'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { AnalyticsService } from '@app/core/services/matomo/analytics-service'; +import { DescriptionFilterComponent } from '../description-filter.component'; + +@Component({ + selector: 'description-filter-dialog-component', + templateUrl: './description-filter-dialog.component.html', + styleUrls: ['./description-filter-dialog.component.scss'] +}) + +export class DescriptionFilterDialogComponent implements OnInit { + + @ViewChild(DescriptionFilterComponent, { static: true }) filter: DescriptionFilterComponent; + + constructor( + public dialogRef: MatDialogRef, + private analyticsService: AnalyticsService, + @Inject(MAT_DIALOG_DATA) public data: { + isPublic: boolean, + status: Number, + filterForm: UntypedFormGroup, + updateDataFn: Function, + } + ) { + } + + ngOnInit() { + this.analyticsService.trackPageView(AnalyticsService.DescriptionFilterDialog); + } + + onNoClick(): void { + this.dialogRef.close(); + } + + onClose(): void { + this.dialogRef.close(); + } + + onFilterChanged(formGroup: UntypedFormGroup) { + this.data.updateDataFn(formGroup); + } +} diff --git a/dmp-frontend/src/app/ui/description/listing/criteria/dataset-criteria.component.html b/dmp-frontend/src/app/ui/description/listing/filtering/description-filter.component.html similarity index 68% rename from dmp-frontend/src/app/ui/description/listing/criteria/dataset-criteria.component.html rename to dmp-frontend/src/app/ui/description/listing/filtering/description-filter.component.html index 6498dc3f5..b27bc5e7e 100644 --- a/dmp-frontend/src/app/ui/description/listing/criteria/dataset-criteria.component.html +++ b/dmp-frontend/src/app/ui/description/listing/filtering/description-filter.component.html @@ -1,11 +1,13 @@ +{{formGroup?.value | json}} +
-
+
-
{{'CRITERIA.FILTERS'| translate}}
+
{{'DESCRIPTION-LISTING.FILTERS.NAME'| translate}}
-
+
-
{{'CRITERIA.DATA-SETS.STATUS'| translate}}
- - - {{ 'TYPES.DATASET-STATUS.ANY' | translate }} - - - {{ 'TYPES.DATASET-STATUS.DRAFT' | translate }} - - - {{ 'TYPES.DATASET-STATUS.FINALISED' | translate }} - +
{{ 'DESCRIPTION-LISTING.FILTERS.STATUS.NAME' | translate}}
+ + {{ 'DESCRIPTION-LISTING.FILTERS.STATUS.TYPES.ANY' | translate }} + {{ 'DESCRIPTION-LISTING.FILTERS.STATUS.TYPES.DRAFT' | translate }} + {{ 'DESCRIPTION-LISTING.FILTERS.STATUS.TYPES.FINALIZED' | translate }}
-
+ +
-
{{'CRITERIA.DATA-SETS.RELATED-DATASET-TEMPLATES' | translate}}
- - {{'CRITERIA.DATA-SETS.SELECT-DATASET-TEMPLATES' | translate }} - - +
{{'DESCRIPTION-LISTING.FILTERS.RELATED-DESCRIPTION-TEMPLATES.NAME' | translate}}
+ + {{'DESCRIPTION-LISTING.FILTERS.RELATED-DESCRIPTION-TEMPLATES.PLACEHOLDER' | translate }} +
@@ -66,26 +62,26 @@
-
{{'CRITERIA.DATA-SETS.RELATED-DMP' | translate}}
- - {{'CRITERIA.DATA-SETS.SELECT-DMP' | translate }} - - +
{{'DESCRIPTION-LISTING.FILTERS.ASSOCIATED-DMPS.NAME' | translate}}
+ + {{'DESCRIPTION-LISTING.FILTERS.ASSOCIATED-DMPS.PLACEHOLDER' | translate }} +
+
-
{{'CRITERIA.DATA-SETS.ALL-VERSIONS'| translate}}
- +
{{'DESCRIPTION-LISTING.FILTERS.ALL-VERSIONS'| translate}}
+
-
+ -
+ +
-
{{'CRITERIA.DATA-SETS.ROLE' | translate }}
- - - {{ 'TYPES.DATASET-ROLE.ANY' | translate }} - - - {{ 'TYPES.DATASET-ROLE.OWNER' | translate }} - - - {{ 'TYPES.DATASET-ROLE.MEMBER' | translate }} - +
{{'DESCRIPTION-LISTING.FILTERS.ROLE.NAME' | translate }}
+ + {{ 'DESCRIPTION-LISTING.FILTERS.ROLE.TYPES.ANY' | translate }} + {{ 'DESCRIPTION-LISTING.FILTERS.ROLE.TYPES.OWNER' | translate }} + {{ 'DESCRIPTION-LISTING.FILTERS.ROLE.TYPES.MEMBER' | translate }}
-
+
-
{{'CRITERIA.DATA-SETS.TAGS' | translate }}
- - {{'CRITERIA.DATA-SETS.SELECT-TAGS' | translate}} - +
{{'DESCRIPTION-LISTING.FILTERS.TAGS.NAME' | translate }}
+ + {{'DESCRIPTION-LISTING.FILTERS.TAGS.PLACEHOLDER' | translate}} +
diff --git a/dmp-frontend/src/app/ui/description/listing/criteria/dataset-criteria.component.scss b/dmp-frontend/src/app/ui/description/listing/filtering/description-filter.component.scss similarity index 92% rename from dmp-frontend/src/app/ui/description/listing/criteria/dataset-criteria.component.scss rename to dmp-frontend/src/app/ui/description/listing/filtering/description-filter.component.scss index a8e92de7c..69401730e 100644 --- a/dmp-frontend/src/app/ui/description/listing/criteria/dataset-criteria.component.scss +++ b/dmp-frontend/src/app/ui/description/listing/filtering/description-filter.component.scss @@ -15,12 +15,7 @@ .import { margin: 10px; padding: 0px; -} - -.filters { - // border: 1px solid #e4e4e4; - // border-radius: 5px; -} +} .criteria-title { color: black; @@ -54,3 +49,7 @@ ::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix { padding: 0.3rem 0rem 0.6rem 0rem !important; } + +::ng-deep label { + margin: 0; +} diff --git a/dmp-frontend/src/app/ui/description/listing/filtering/description-filter.component.ts b/dmp-frontend/src/app/ui/description/listing/filtering/description-filter.component.ts new file mode 100644 index 000000000..0732d1b16 --- /dev/null +++ b/dmp-frontend/src/app/ui/description/listing/filtering/description-filter.component.ts @@ -0,0 +1,97 @@ + +import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; +import { UntypedFormGroup } from '@angular/forms'; +import { DescriptionStatus } from '@app/core/common/enum/description-status'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { DescriptionTemplateTypeService } from '@app/core/services/description-template-type/description-template-type.service'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { TagService } from '@app/core/services/tag/tag.service'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { BaseCriteriaComponent } from '@app/ui/misc/criteria/base-criteria.component'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; +import { takeUntil } from 'rxjs/operators'; + +@Component({ + selector: 'app-description-filter-component', + templateUrl: './description-filter.component.html', + styleUrls: ['./description-filter.component.scss'] +}) +export class DescriptionFilterComponent extends BaseCriteriaComponent implements OnInit, OnChanges { + + @Input() status; + @Input() isPublic: boolean; + @Input() filterFormGroup: UntypedFormGroup; + @Output() filterChanged: EventEmitter = new EventEmitter(); + + public criteria: any; + public filteringTagsAsync = false; + + statuses = DescriptionStatus; + options: UntypedFormGroup; + + get tagAutoCompleteConfiguration(): MultipleAutoCompleteConfiguration { + return this.tagService.multipleAutocompleteConfiguration; + }; + + get descriptionTemplateAutoCompleteConfiguration(): MultipleAutoCompleteConfiguration { + return this.descriptionTemplateTypeService.getMultipleAutoCompleteSearchConfiguration(); + }; + + get dmpAutoCompleteConfiguration(): MultipleAutoCompleteConfiguration { + return this.dmpService.multipleAutocompleteConfiguration; + }; + + constructor( + public enumUtils: EnumUtils, + private authentication: AuthService, + private descriptionTemplateTypeService: DescriptionTemplateTypeService, + private dmpService: DmpService, + private tagService: TagService, + ) { + super(new ValidationErrorModel()); + } + + + ngOnInit() { + super.ngOnInit(); + } + + ngOnChanges(changes: SimpleChanges): void { + if (changes['filterFormGroup']) { + this.formGroup = this.filterFormGroup; + this.formGroup.get('status')?.valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => this.controlModified()); + this.formGroup.get('role')?.valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => this.controlModified()); + this.formGroup.get('descriptionTemplates')?.valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => this.controlModified()); + this.formGroup.get('associatedDmpIds')?.valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => this.controlModified()); + this.formGroup.get('showAllVersions')?.valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => this.controlModified()); + this.formGroup.get('tags')?.valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => this.controlModified()); + } + } + + controlModified(): void { + this.clearErrorModel(); + this.filterChanged.emit(this.formGroup); + if (this.refreshCallback != null && + (this.formGroup.get('like')?.value == null || this.formGroup.get('like')?.value.length === 0 || this.formGroup.get('like')?.value.length > 2) + ) { + setTimeout(() => this.refreshCallback(true)); + } + } + + isAuthenticated(): boolean { + return this.authentication.currentAccountIsAuthenticated(); + } +} diff --git a/dmp-frontend/src/app/ui/description/listing/filtering/description-filters-dialogue/description-filter-dialog.component.ts b/dmp-frontend/src/app/ui/description/listing/filtering/description-filters-dialogue/description-filter-dialog.component.ts new file mode 100644 index 000000000..673af1673 --- /dev/null +++ b/dmp-frontend/src/app/ui/description/listing/filtering/description-filters-dialogue/description-filter-dialog.component.ts @@ -0,0 +1,55 @@ +import { HttpClient } from '@angular/common/http'; +import { Component, Inject, OnInit, ViewChild } from '@angular/core'; +import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { AnalyticsService } from '@app/core/services/matomo/analytics-service'; +import { DescriptionFiltersComponent } from '../description-filter.component'; + +@Component({ + selector: 'description-filter-dialog-component', + templateUrl: './description-filter-dialog.component.html', + styleUrls: ['./description-filter-dialog.component.scss'] +}) + +export class DescriptionFilterDialogComponent implements OnInit { + + @ViewChild(DescriptionFiltersComponent, { static: true }) filter: DescriptionFiltersComponent; + + public filtersFormGroup = new UntypedFormBuilder().group({ + status: new UntypedFormControl(), + role: new UntypedFormControl(), + allVersions: new UntypedFormControl(), + descriptionTemplates: new UntypedFormControl(), + relatedDmps: new UntypedFormControl(), + tags: new UntypedFormControl(), + }); + + constructor( + public dialogRef: MatDialogRef, + private httpClient: HttpClient, + private analyticsService: AnalyticsService, + @Inject(MAT_DIALOG_DATA) public data: { + isPublic: boolean, + status: Number, + filterForm: UntypedFormGroup, + updateDataFn: Function } + ) { + } + + ngOnInit() { + this.analyticsService.trackPageView(AnalyticsService.DescriptionFiltersDialog); + // this.filters.setfilters(this.data.filters); + } + + onNoClick(): void { + this.dialogRef.close(); + } + + onClose(): void { + this.dialogRef.close(); + } + + onFiltersChanged(event) { + this.data.updateDataFn(this.filter); + } +} diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index 1cd00ab1e..07bc4bd95 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -840,6 +840,9 @@ "DESCRIPTION": "Description", "GRANT": "Grant", "LOCKED": "Description is Locked by another user", + "PART-OF": "Part of", + "DMP": "Plan", + "EMPTY-LIST": "Nothing here yet.", "ACTIONS": { "ADD-DESCRIPTION": "Add Description", "TAKE-A-TOUR": "Do you need help? Take a tour..", @@ -860,9 +863,38 @@ "COPY": "Copy", "CANCEL": "Cancel" }, - "PART-OF": "Part of", - "DMP": "Plan", - "EMPTY-LIST": "Nothing here yet." + "FILTERS": { + "NAME": "Filters", + "STATUS": { + "NAME": "Status", + "TYPES": { + "ANY": "Any", + "DRAFT": "Draft", + "FINALIZED": "Finalized" + } + }, + "RELATED-DESCRIPTION-TEMPLATES": { + "NAME": "Related Description Templates", + "PLACEHOLDER": "Select Description Templates" + }, + "ASSOCIATED-DMPS": { + "NAME": "Related DMPs", + "PLACEHOLDER": "Select DMPs" + }, + "ALL-VERSIONS": "From All Versions", + "ROLE": { + "NAME": "Role", + "TYPES": { + "ANY": "Any", + "OWNER": "Owner", + "MEMBER": "Member" + } + }, + "TAGS": { + "NAME": "Tags", + "PLACEHOLDER": "Select Tags" + } + } }, "DESCRIPTION-EDITOR": { "TITLE-NEW": "New Description",