fix editing dmp page, add section templates to new dataset page

This commit is contained in:
Bernaldo Mihasi 2023-09-12 15:38:23 +03:00
parent 6154a5fa51
commit 29f5b6a6cc
11 changed files with 405 additions and 112 deletions

View File

@ -9,6 +9,7 @@ import { JsonParserPipe } from './pipes/json-parser.pipe';
import { DateTimeCultureFormatPipe } from './pipes/date-time-culture-format.pipe';
import {FieldValuePipe} from "@app/core/pipes/field-value.pipe";
import {ColumnClassPipe} from "@app/core/pipes/column-class.pipe";
import { DatasetInSectioPipe } from './pipes/dataset-in-section.pipe';
//
//
@ -25,7 +26,8 @@ import {ColumnClassPipe} from "@app/core/pipes/column-class.pipe";
DateTimeCultureFormatPipe,
JsonParserPipe,
FieldValuePipe,
ColumnClassPipe
ColumnClassPipe,
DatasetInSectioPipe
],
exports: [
NgForLimitPipe,
@ -35,7 +37,8 @@ import {ColumnClassPipe} from "@app/core/pipes/column-class.pipe";
DateTimeCultureFormatPipe,
JsonParserPipe,
FieldValuePipe,
ColumnClassPipe
ColumnClassPipe,
DatasetInSectioPipe
],
providers: [
EnumUtils,
@ -47,7 +50,8 @@ import {ColumnClassPipe} from "@app/core/pipes/column-class.pipe";
DateTimeCultureFormatPipe,
JsonParserPipe,
FieldValuePipe,
ColumnClassPipe
ColumnClassPipe,
DatasetInSectioPipe
]
})
export class FormattingModule { }

View File

@ -2,6 +2,7 @@ import { DmpDatasetProfileSectionsFormModel } from "./dmp-dataset-profile-sectio
export interface DmpDatasetProfile {
id: string;
descriptionTemplateId: string;
label: string;
data: DmpDatasetProfileSectionsFormModel;
}

View File

@ -0,0 +1,18 @@
import { Pipe, PipeTransform } from "@angular/core";
import { FormGroup } from "@angular/forms";
@Pipe({
name: 'datasetInSection'
})
export class DatasetInSectioPipe implements PipeTransform{
transform(datasets: FormGroup[], args: string): FormGroup[] {
let values = [];
for(var dataset of datasets){
if(dataset.get('dmpSectionIndex').value == args){
values.push(dataset);
}
}
return values;
}
}

View File

@ -172,7 +172,7 @@
<div class="col-2">
<mat-form-field>
<mat-label>Placeholder</mat-label>
<input matInput type="text" name="placeholder" formControlName="placolder">
<input matInput type="text" name="placeholder" formControlName="placeholder">
</mat-form-field>
</div>
<div class="col-2">

View File

@ -141,7 +141,7 @@
</div>
</div>
<div class="col-auto form" id="dataset-editor-form">
<app-dataset-editor-component [hidden]="this.step !== 0" [formGroup]="formGroup" [dmpId]="formGroup.get('dmp').value.id" [availableProfiles]="formGroup.get('dmp').value.profiles" (formChanged)="formChanged()"></app-dataset-editor-component>
<app-dataset-editor-component [hidden]="this.step !== 0" [formGroup]="formGroup" [dmpId]="formGroup.get('dmp').value.id" [availableProfiles]="availableDescriptionTemplates" (formChanged)="formChanged()"></app-dataset-editor-component>
<app-dataset-description (visibilityRulesInstance)="visRulesService = $event" [TOCENTRY_ID_PREFIX]="TOCENTRY_ID_PREFIX" [hidden]="this.step === 0" *ngIf="formGroup && formGroup.get('datasetProfileDefinition')" [form]="this.formGroup.get('datasetProfileDefinition')" [visibilityRules]="formGroup.get('datasetProfileDefinition').get('rules').value" [datasetProfileId]="formGroup.get('profile').value" [linkToScroll]="linkToScroll" (fieldsetFocusChange)="fieldsetIdWithFocus = $event"></app-dataset-description>
</div>
</div>

View File

@ -62,6 +62,7 @@ import {CheckDeactivateBaseComponent} from '@app/library/deactivate/deactivate.c
import {PrefillDatasetComponent} from "@app/ui/dataset/dataset-wizard/prefill-dataset/prefill-dataset.component";
import {ToCEntry, ToCEntryType} from "@app/ui/misc/dataset-description-form/dataset-description.component";
import {dispatchFakeEvent} from "@angular/cdk/testing/testbed/fake-events";
import { DmpDatasetProfile } from '@app/core/model/dmp/dmp-dataset-profile/dmp-dataset-profile';
@Component({
selector: 'app-dataset-wizard-component',
@ -96,6 +97,7 @@ export class DatasetWizardComponent extends CheckDeactivateBaseComponent impleme
itemId: string;
dmpId: string;
dmpSectionIndex: number;
availableDescriptionTemplates: DatasetProfileModel[] = [];
newDmpId: string;
publicId: string;
profileUpdateId: string;
@ -172,7 +174,7 @@ export class DatasetWizardComponent extends CheckDeactivateBaseComponent impleme
const data: any = this.route.snapshot.data;
this.itemId = params['id'];
this.dmpId = params['dmpId'];
this.dmpSectionIndex = params['dmpSectionIndex'];
this.dmpSectionIndex = parseInt(params['dmpSectionIndex']);
this.newDmpId = queryParams['newDmpId'];
this.publicId = params['publicId'];
this.profileUpdateId = params['updateId'];
@ -270,6 +272,10 @@ export class DatasetWizardComponent extends CheckDeactivateBaseComponent impleme
this.datasetWizardModel.dmp = data;
this.datasetWizardModel.dmpSectionIndex = this.dmpSectionIndex;
this.formGroup = this.datasetWizardModel.buildForm();
let profiles = this.datasetWizardModel.dmp.profiles.filter(profile => profile.data.dmpSectionIndex.includes(this.dmpSectionIndex));
for(var profile of profiles){
this.availableDescriptionTemplates.push({id: profile.descriptionTemplateId, label: profile.label, description: ""})
}
this.formGroupRawValue = JSON.parse(JSON.stringify(this.formGroup.getRawValue()));
this.editMode = this.datasetWizardModel.status === DatasetStatus.Draft;
this.formGroup.get('dmp').disable();
@ -278,7 +284,7 @@ export class DatasetWizardComponent extends CheckDeactivateBaseComponent impleme
minHeight: '200px',
restoreFocus: false,
data: {
availableProfiles: this.formGroup.get('dmp').value.profiles,
availableProfiles: this.availableDescriptionTemplates,
},
panelClass: 'custom-modalbox'
});

View File

@ -1,6 +1,6 @@
<div class="main-content">
<div class="container-fluid">
<div class="form-container">
<div *ngIf="formGroup" [formGroup]="formGroup" class="form-container">
<!-- DMP Header -->
<div [hidden]="false" class="fixed-editor-header">
<div class="card editor-header">
@ -8,25 +8,25 @@
<div class="row">
<div class="col-auto info">
<div class="title">{{'DMP-EDITOR.TITLE.EDIT-DMP' | translate}}</div>
<!-- <div class="subtitle">{{ formGroup.get('label').value }} <span *ngIf="isDirty()" class="changes">({{'DMP-EDITOR.CHANGES' | translate}})</span></div> -->
<div class="subtitle">{{ formGroup.get('label').value }} <span *ngIf="isDirty()" class="changes">({{'DMP-EDITOR.CHANGES' | translate}})</span></div>
</div>
<div class="ml-auto d-flex flex-row">
<!-- <mat-divider *ngIf="formGroup.get('id').value && (isDirty() || isNew || (!isNew && formGroup.enabled && !lockStatus) || lockStatus)"
[vertical]="true" class="ml-2 mr-2">
</mat-divider> -->
<div class="col-auto d-flex align-items-center">
<!-- <button [disabled]="saving" *ngIf="isDirty()" type="button" mat-raised-button class="discard-btn mr-3" (click)="discard()">
<button [disabled]="saving" *ngIf="isDirty()" type="button" mat-raised-button class="discard-btn mr-3" (click)="discard()">
{{'DMP-EDITOR.ACTIONS.DISCARD' | translate}}
</button> -->
</button>
<button [disabled]="saving" *ngIf="isNew" mat-raised-button type="button" (click)="save()" class="save-btn">
{{'DMP-EDITOR.ACTIONS.SAVE' | translate}}
</button>
<!-- <div *ngIf="!isNew && formGroup.enabled && !lockStatus">
<div *ngIf="!isNew && formGroup.enabled && !lockStatus">
<button [disabled]="saving" *ngIf="!isFinalized" mat-raised-button (click)="formSubmit()" class="save-btn">
{{'DMP-EDITOR.ACTIONS.SAVE' | translate}}
</button>
</div> -->
<!-- <button *ngIf="lockStatus" mat-raised-button disabled class="dataset-save-btn cursor-default" type="button">{{ 'DMP-OVERVIEW.LOCKED' | translate}}</button> -->
</div>
<button *ngIf="lockStatus" mat-raised-button disabled class="dataset-save-btn cursor-default" type="button">{{ 'DMP-OVERVIEW.LOCKED' | translate}}</button>
</div>
</div>
</div>
@ -42,9 +42,18 @@
<div *ngIf="selectedDmpBlueprintDefinition && this.step !== 0">
<div *ngFor="let section of selectedDmpBlueprintDefinition.sections; let i=index">
<li (click)="changeStep(i + 1)" [ngClass]="{'active': this.step === (i + 1)}">{{section.label}}</li>
<ol class="datasetsInSection">
<li *ngFor="let dataset of datasets.controls | datasetInSection: i; let datasetIndex = index" (click)="editDataset(dataset.get('id').value, false)" class="active-dataset">
<div class="d-flex flex-direction-row">
<div class="label" matTooltip="{{dataset.get('label').value}}">{{'DMP-EDITOR.STEPPER.DATASET' | translate}}: {{ dataset.get('label').value }}</div>
<mat-icon *ngIf="dataset.get('status').value !== 1" class="ml-2 mr-2 remove-dataset size-16" matTooltip="{{'DMP-EDITOR.ACTIONS.DELETE' | translate}}" (click)="$event.stopPropagation(); removeDataset(dataset.get('id').value, datasetIndex)">close</mat-icon>
<mat-icon *ngIf="dataset.get('status').value === 1" class="ml-2 mr-2 status-icon check-icon size-16" matTooltip="{{'TYPES.DATASET-STATUS.FINALISED' | translate}}">check</mat-icon>
</div>
</li>
</ol>
<ul *ngIf="hasProfile()" class="add-dataset-option">
<li>
<a class="add-dataset-action" [routerLink]="['/datasets/new/' + dmp.id]">
<a class="add-dataset-action" (click)="addDataset(i)">
<mat-icon>add</mat-icon>{{'DMP-LISTING.ACTIONS.ADD-DESCRIPTION-SHORT' | translate}}
</a>
</li>
@ -72,7 +81,7 @@
<app-form-progress-indication class="col-12" *ngIf="formGroup && !formGroup.disabled && !lockStatus" [formGroup]="formGroup" [isDmpEditor]="true"></app-form-progress-indication>
</div>
</div>
<div class="col-auto formForStep0" id="editor-form" *ngIf="this.step ===0">
<div class="col-auto formForStep0" id="editor-form" *ngIf="this.step === 0 && this.isNew">
<div class="col-12 blueprint-section" [hidden]="this.step !== 0">
<div class="input-form">
<div class="heading2">0.1 Title of DMP *</div>
@ -116,7 +125,7 @@
</div>
</div>
</div>
<div class="col-auto form" id="editor-form" *ngIf="this.step !==0">
<div class="col-auto form" id="editor-form" *ngIf="this.step !== 0">
<div *ngIf="selectedDmpBlueprintDefinition">
<div *ngFor="let section of selectedDmpBlueprintDefinition.sections; let i=index">
<div class="section-info" [hidden]="this.step !== (i + 1)">
@ -209,13 +218,13 @@
</div>
</div>
<div *ngIf="field.type == 6">
<funding-info [formGroup]="formGroup" [grantformGroup]="formGroup.get('grant')" [projectFormGroup]="formGroup.get('project')" [funderFormGroup]="formGroup.get('funder')" [isFinalized]="false" [isNew]="true" [isUserOwner]="true" [type]="1" (onFormChanged)="formChanged()"></funding-info>
<funding-info [formGroup]="formGroup" [grantformGroup]="formGroup.get('grant')" [projectFormGroup]="formGroup.get('project')" [funderFormGroup]="formGroup.get('funder')" [isFinalized]="isFinalized" [isNew]="isNew" [isUserOwner]="isUserOwner" [type]="1" (onFormChanged)="formChanged()"></funding-info>
</div>
<div *ngIf="field.type == 7">
<funding-info [formGroup]="formGroup" [grantformGroup]="formGroup.get('grant')" [projectFormGroup]="formGroup.get('project')" [funderFormGroup]="formGroup.get('funder')" [isFinalized]="false" [isNew]="true" [isUserOwner]="true" [type]="2" (onFormChanged)="formChanged()"></funding-info>
<funding-info [formGroup]="formGroup" [grantformGroup]="formGroup.get('grant')" [projectFormGroup]="formGroup.get('project')" [funderFormGroup]="formGroup.get('funder')" [isFinalized]="isFinalized" [isNew]="isNew" [isUserOwner]="isUserOwner" [type]="2" (onFormChanged)="formChanged()"></funding-info>
</div>
<div *ngIf="field.type == 8">
<funding-info [formGroup]="formGroup" [grantformGroup]="formGroup.get('grant')" [projectFormGroup]="formGroup.get('project')" [funderFormGroup]="formGroup.get('funder')" [isFinalized]="false" [isNew]="true" [isUserOwner]="true" [type]="3" (onFormChanged)="formChanged()"></funding-info>
<funding-info [formGroup]="formGroup" [grantformGroup]="formGroup.get('grant')" [projectFormGroup]="formGroup.get('project')" [funderFormGroup]="formGroup.get('funder')" [isFinalized]="isFinalized" [isNew]="isNew" [isUserOwner]="isUserOwner" [type]="3" (onFormChanged)="formChanged()"></funding-info>
</div>
<div *ngIf="field.type == 9">
<mat-form-field>
@ -294,7 +303,7 @@
<div class="heading">Description templates</div>
<mat-form-field>
<mat-label>{{'DMP-EDITOR.FIELDS.SELECT-TEMPLATE' | translate}}</mat-label>
<app-multiple-auto-complete placeholder="{{'DMP-EDITOR.FIELDS.SELECT-TEMPLATE' | translate}}" [hidePlaceholder]="true" required='true' [value]="sectionTemplates[section.ordinal - 1]" [configuration]="profilesAutoCompleteConfiguration" (optionRemoved)="onRemoveTemplate($event)" (optionActionClicked)="onPreviewTemplate($event)" (optionSelected)="onOptionSelected()">
<app-multiple-auto-complete placeholder="{{'DMP-EDITOR.FIELDS.SELECT-TEMPLATE' | translate}}" [hidePlaceholder]="true" required='true' [value]="sectionTemplates[section.ordinal - 1]" [configuration]="profilesAutoCompleteConfiguration" (optionRemoved)="onRemoveTemplate($event)" (optionActionClicked)="onPreviewTemplate($event)" (optionSelected)="onOptionSelected($event, i)">
</app-multiple-auto-complete>
<mat-error *ngIf="formGroup.get('profiles').hasError('backendError')">
{{formGroup.get('profiles').getError('backendError').message}}</mat-error>

View File

@ -38,6 +38,10 @@
}
}
.datasetsInSection {
counter-reset: item
}
.title {
text-align: left;
font-weight: 400;
@ -280,6 +284,24 @@ mat-icon.size-16 {
margin: 3rem 0rem 3rem 0rem;
}
.changes {
font-weight: 400;
color: #ffffff;
}
.discard-btn {
background: transparent;
border: 1px solid #ffffff;
color: white;
border-radius: 30px;
opacity: 1;
width: 110px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
}
a {
color: #000000;
}

View File

@ -13,7 +13,6 @@ import { FunderFormModel } from '../editor/grant-tab/funder-form-model';
import { GrantTabModel } from '../editor/grant-tab/grant-tab-model';
import { ProjectFormModel } from '../editor/grant-tab/project-form-model';
import { AuthService } from '@app/core/services/auth/auth.service';
import { BaseComponent } from '@common/base/base.component';
import { ConfigurationService } from '@app/core/services/configuration/configuration.service';
import { isNullOrUndefined } from '@app/utilities/enhancers/utils';
import { LanguageInfoService } from '@app/core/services/culture/language-info-service';
@ -22,7 +21,7 @@ import { UserModel } from '@app/core/model/user/user';
import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration';
import { TranslateService } from '@ngx-translate/core';
import { ExternalSourcesService } from '@app/core/services/external-sources/external-sources.service';
import { Observable } from 'rxjs';
import { Observable, interval } from 'rxjs';
import { ExternalSourceItemModel } from '@app/core/model/external-sources/external-source-item';
import { OrganisationService } from '@app/core/services/organisation/organisation.service';
import { MatDialog } from '@angular/material/dialog';
@ -40,13 +39,22 @@ import { FormValidationErrorsDialogComponent } from '@common/forms/form-validati
import { DmpStatus } from '@app/core/common/enum/dmp-status';
import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model';
import { DmpModel } from '@app/core/model/dmp/dmp';
import { Router } from '@angular/router';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component';
import { DmpToDatasetDialogComponent } from '../dmp-to-dataset/dmp-to-dataset-dialog.component';
import { UserInfoListingModel } from '@app/core/model/user/user-info-listing';
import { FormService } from '@common/forms/form-service';
import { DmpDatasetProfile } from '@app/core/model/dmp/dmp-dataset-profile/dmp-dataset-profile';
import { DmpDatasetProfileSectionsFormModel } from '@app/core/model/dmp/dmp-dataset-profile/dmp-dataset-profile-sections-form.model';
import { MatomoService } from '@app/core/services/matomo/matomo-service';
import { LockService } from '@app/core/services/lock/lock.service';
import { Principal } from '@app/core/model/auth/principal';
import { Role } from '@app/core/common/enum/role';
import { LockModel } from '@app/core/model/lock/lock.model';
import { Guid } from '@common/types/guid';
import { PopupNotificationDialogComponent } from '@app/library/notification/popup/popup-notification.component';
import { GrantEditorModel } from '@app/ui/grant/editor/grant-editor.model';
import { CheckDeactivateBaseComponent } from '@app/library/deactivate/deactivate.component';
interface Visible {
value: boolean;
@ -58,7 +66,11 @@ interface Visible {
templateUrl: './dmp-editor-blueprint.component.html',
styleUrls: ['./dmp-editor-blueprint.component.scss']
})
export class DmpEditorBlueprintComponent extends BaseComponent implements OnInit {
export class DmpEditorBlueprintComponent extends CheckDeactivateBaseComponent implements OnInit {
canDeactivate(): boolean {
return !this.isDirty();
}
saving = false;
@ -78,10 +90,12 @@ export class DmpEditorBlueprintComponent extends BaseComponent implements OnInit
dmpSectionIndex: number = 0;
formGroup: FormGroup = null;
formGroupRawValue: any;
datasets = new FormArray([]);
associatedUsers: Array<UserModel>;
people: Array<UserInfoListingModel>;
lock: LockModel;
lockStatus: Boolean = false;
step: number = 0;
@ -114,6 +128,7 @@ export class DmpEditorBlueprintComponent extends BaseComponent implements OnInit
constructor(
private dmpProfileService: DmpProfileService,
private authService: AuthService,
private route: ActivatedRoute,
private router: Router,
private configurationService: ConfigurationService,
private languageInfoService: LanguageInfoService,
@ -123,54 +138,150 @@ export class DmpEditorBlueprintComponent extends BaseComponent implements OnInit
private dmpService: DmpService,
private uiNotificationService: UiNotificationService,
private formService: FormService,
private dialog: MatDialog
private dialog: MatDialog,
private lockService: LockService,
private matomoService: MatomoService
) {
super();
}
ngOnInit(): void {
this.dmp = new DmpEditorModel();
this.dmp.grant = new GrantTabModel();
this.dmp.project = new ProjectFormModel();
this.dmp.funder = new FunderFormModel();
this.dmp.extraProperties = new ExtraPropertiesFormModel();
this.dmp.extraProperties.visible = false;
this.dmp.extraProperties.contact = this.authService.current().id;
this.formGroup = this.dmp.buildForm();
this.matomoService.trackPageView('DMP Editor');
this.route.params
.pipe(takeUntil(this._destroyed))
.subscribe((params: Params) => {
const itemId = params['id'];
this.formGroupRawValue = JSON.parse(JSON.stringify(this.formGroup.getRawValue()));
if (itemId != null) {
this.isNew = false;
this.dmpService.getSingle(itemId).pipe(map(data => data as DmpModel))
.pipe(takeUntil(this._destroyed))
.subscribe(async data => {
this.lockService.checkLockStatus(data.id).pipe(takeUntil(this._destroyed)).subscribe(lockStatus => {
this.lockStatus = lockStatus;
if (this.formGroup.get('profile')) { this.selectedDmpBlueprintDefinition = this.formGroup.get('profile').value; }
this.registerFormEventsForDmpBlueprint();
this.dmp = new DmpEditorModel();
this.dmp.grant = new GrantTabModel();
this.dmp.project = new ProjectFormModel();
this.dmp.funder = new FunderFormModel();
this.dmp.extraProperties = new ExtraPropertiesFormModel();
this.dmp.fromModel(data);
this.formGroup = this.dmp.buildForm();
if (!this.isUserOwner) {
this.formGroup.disable();
}
if (isNullOrUndefined(this.formGroup.get('extraProperties').get('publicDate').value)) {
this.formGroup.get('extraProperties').get('publicDate').patchValue(new Date());
}
this.datasets = this.formGroup.get('datasets') as FormArray;
const principal = this.authService.current();
let associate: UserModel = {
id: principal.id,
name: principal.name,
appRoles: principal.authorities,
email: principal.email
};
this.associates.push(associate);
if (isNullOrUndefined(this.formGroup.get('extraProperties').get('contact').value)) {
this.formGroup.get('extraProperties').get('contact').patchValue(associate.id);
}
if (isNullOrUndefined(this.formGroup.get('extraProperties').get('language').value)) {
this.formGroup.get('extraProperties').get('language').patchValue('en');
}
this.formGroupRawValue = JSON.parse(JSON.stringify(this.formGroup.getRawValue()));
if (!isNullOrUndefined(this.formGroup.get('profile').value)) {
this.dmpProfileService.getSingleBlueprint(this.formGroup.get('profile').value.id)
.pipe(takeUntil(this._destroyed))
.subscribe(result => {
this.selectedDmpBlueprintDefinition = result.definition;
this.formGroup.get('profile').setValue(result);
this.maxStep = this.selectedDmpBlueprintDefinition.sections.length;
this.step = 1;
this.addProfiles(this.dmp.profiles);
});
}
this.maxStep = this.formGroup.get('datasets') ? this.maxStep + this.formGroup.get('datasets').value.length - 1 : this.maxStep;
this.setIsUserOwner();
if (!this.isUserOwner) {
if(this.isUserMember()){
this.router.navigate(['plans', 'overview', itemId]);
return;
}
this.isFinalized = true;
this.formGroup.disable();
}
if (this.dmp.status === DmpStatus.Finalized || lockStatus) {
this.isFinalized = true;
this.formGroup.disable();
}
if (this.authService.current() != null) {
if (!lockStatus) {
this.lock = new LockModel(data.id, this.getUserFromDMP());
this.lockService.createOrUpdate(this.lock).pipe(takeUntil(this._destroyed)).subscribe(async result => {
this.lock.id = Guid.parse(result);
interval(this.configurationService.lockInterval).pipe(takeUntil(this._destroyed)).subscribe(() => this.pumpLock());
});
}
}
this.associatedUsers = data.associatedUsers;
this.people = data.users;
this.formGroup.valueChanges.pipe(takeUntil(this._destroyed))
.subscribe(x => {
this.formChanged();
});
if(this.lockStatus){
this.dialog.open(PopupNotificationDialogComponent,{data:{
title:this.language.instant('DMP-EDITOR.LOCKED.TITLE'),
message:this.language.instant('DMP-EDITOR.LOCKED.MESSAGE')
}, maxWidth:'30em'});
}
});
});
}
else {
this.dmp = new DmpEditorModel();
this.dmp.grant = new GrantTabModel();
this.dmp.project = new ProjectFormModel();
this.dmp.funder = new FunderFormModel();
this.dmp.extraProperties = new ExtraPropertiesFormModel();
this.dmp.extraProperties.visible = false;
this.dmp.extraProperties.contact = this.authService.current().id;
this.formGroup = this.dmp.buildForm();
this.formGroupRawValue = JSON.parse(JSON.stringify(this.formGroup.getRawValue()));
if (!isNullOrUndefined(this.formGroup.get('profile').value)) {
this.dmpProfileService.getSingleBlueprint(this.formGroup.get('profile').value.id)
.pipe(takeUntil(this._destroyed))
.subscribe(result => {
this.selectedDmpBlueprintDefinition = result.definition;
this.formGroup.get('profile').setValue(result);
this.maxStep = this.selectedDmpBlueprintDefinition.sections.length;
this.step = 1;
this.addProfiles();
});
}
this.registerFormEventsForDmpBlueprint();
if (!this.isUserOwner) {
this.formGroup.disable();
}
if (isNullOrUndefined(this.formGroup.get('extraProperties').get('publicDate').value)) {
this.formGroup.get('extraProperties').get('publicDate').patchValue(new Date());
}
const principal = this.authService.current();
let associate: UserModel = {
id: principal.id,
name: principal.name,
appRoles: principal.authorities,
email: principal.email
};
this.associates.push(associate);
if (isNullOrUndefined(this.formGroup.get('extraProperties').get('contact').value)) {
this.formGroup.get('extraProperties').get('contact').patchValue(associate.id);
}
if (isNullOrUndefined(this.formGroup.get('extraProperties').get('language').value)) {
this.formGroup.get('extraProperties').get('language').patchValue('en');
}
try{
const profiles = this.formGroup.get('profiles').value as DmpDatasetProfile[];
profiles.sort((a,b)=>a.label.localeCompare(b.label));
}catch{
console.info('Could not sort profiles');
}
}
});
try{
const profiles = this.formGroup.get('profiles').value as DmpDatasetProfile[];
profiles.sort((a,b)=>a.label.localeCompare(b.label));
}catch{
console.info('Could not sort profiles');
}
this.profilesAutoCompleteConfiguration = {
filterFn: this.filterProfiles.bind(this),
@ -182,8 +293,104 @@ export class DmpEditorBlueprintComponent extends BaseComponent implements OnInit
};
}
setIsUserOwner() {
if (this.dmp) {
const principal: Principal = this.authService.current();
this.isUserOwner = !!this.dmp.users.find(x => (x.role === Role.Owner) && (x.id === principal.id) );
}
}
isUserMember(): boolean{
try{
const principal: Principal = this.authService.current();
return !!this.dmp.users.find(x => (x.role === Role.Member) && (x.id === principal.id) );
}catch{
return false;
}
}
getUserFromDMP(): any {
if (this.dmp) {
const principal: Principal = this.authService.current();
return this.dmp.users.find(x => x.id === principal.id);
}
}
private pumpLock() {
this.lock.touchedAt = new Date();
this.lockService.createOrUpdate(this.lock).pipe(takeUntil(this._destroyed)).subscribe(async result => this.lock.id = Guid.parse(result));
}
public isDirty(): boolean {
return this.formGroup && this.formGroup.dirty && this.hasChanges;
}
public discard() {
let messageText = "";
let confirmButtonText = "";
let cancelButtonText = "";
if (this.isNew) {
messageText = this.language.instant('DATASET-EDITOR.ACTIONS.DISCARD.DISCARD-NEW-MESSAGE');
confirmButtonText = this.language.instant('DATASET-EDITOR.ACTIONS.DISCARD.DISCARD-NEW-CONFIRM');
cancelButtonText = this.language.instant('DATASET-EDITOR.ACTIONS.DISCARD.DISCARD-NEW-DENY');
} else {
messageText = this.language.instant('DATASET-EDITOR.ACTIONS.DISCARD.DISCARD-EDITED-MESSAGE');
confirmButtonText = this.language.instant('DATASET-EDITOR.ACTIONS.DISCARD.DISCARD-EDITED-CONFIRM');
cancelButtonText = this.language.instant('DATASET-EDITOR.ACTIONS.DISCARD.DISCARD-EDITED-DENY');
}
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
restoreFocus: false,
data: {
message: messageText,
confirmButton: confirmButtonText,
cancelButton: cancelButtonText,
isDeleteConfirmation: true
},
maxWidth: '40em'
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
if (result) {
// this.backToDmp(this.formGroup.get('dmp').value.id)
setTimeout(x => {
this.discardChanges();
});
}
});
}
public discardChanges() {
this.isDiscarded = true;
this.hasChanges = false;
if (!this.isNew) {
let grantControl;
if (this.formGroup.get('grant').get('existGrant')) {
grantControl = new GrantTabModel();
grantControl.fromModel(this.formGroup.get('grant').get('existGrant').value);
} else {
grantControl = new GrantEditorModel();
grantControl.fromModel(this.formGroup.get('grant').value);
}
grantControl.buildForm()
this.formGroup.patchValue(JSON.parse(JSON.stringify(this.formGroupRawValue)));
if (this.formGroup.get('grant').get('existGrant')) {
this.formGroup.get('grant').get('existGrant').setValue(grantControl.existGrant);
} else {
this.formGroup.get('grant').setValue(grantControl);
}
} else {
this.formGroup.reset();
this.formGroup.get("status").setValue(DmpStatus.Draft);
this.formGroup.get('extraProperties').get('visible').setValue(false);
this.formGroup.get('extraProperties').get('contact').setValue(this.authService.current().id);
this.formGroup.get('associatedUsers').setValue([]);
}
this.isDiscarded = false;
}
save() {
this.formSubmit(true);
this.formSubmit(false);
}
formSubmit(addNew?: boolean, showAddDatasetDialog?: boolean): void {
@ -349,6 +556,9 @@ export class DmpEditorBlueprintComponent extends BaseComponent implements OnInit
// On save keep editor position
this.uiNotificationService.snackBarNotification(this.isNew ? this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-CREATION') : this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success);
if (dmp) {
if(this.isNew){
this.router.navigate(['/plans', 'edit', dmp.id]);
}
let dmpEditorModel: DmpEditorModel;
dmpEditorModel = new DmpEditorModel();
dmpEditorModel.grant = new GrantTabModel();
@ -572,30 +782,7 @@ export class DmpEditorBlueprintComponent extends BaseComponent implements OnInit
.subscribe(Option => {
if (Option instanceof Object) {
this.selectedDmpBlueprintDefinition = Option.definition;
for(let i = 0; i < this.selectedDmpBlueprintDefinition.sections.length; i++){
this.sectionTemplates.push(new Array<DatasetProfileModel>());
}
const templates: Array<DmpDatasetProfile> = new Array<DmpDatasetProfile>();
this.selectedDmpBlueprintDefinition.sections.forEach(section => {
section.descriptionTemplates.forEach(template => {
this.sectionTemplates[section.ordinal - 1].push({id: template.descriptionTemplateId, label: template.label, description: ""})
let data: DmpDatasetProfileSectionsFormModel= new DmpDatasetProfileSectionsFormModel();
data.dmpSectionIndex.push(section.ordinal - 1);
let profile: DmpDatasetProfile = {
id: template.descriptionTemplateId,
label: template.label,
data: data
};
let found: DmpDatasetProfile = templates.find(dmpDatasetProfile => dmpDatasetProfile.id == profile.id);
if (found === undefined) {
templates.push(profile);
}
else {
found.data.dmpSectionIndex.push(section.ordinal - 1);
}
});
});
this.formGroup.get('profiles').setValue(templates);
this.addProfiles();
}
else {
this.selectedDmpBlueprintDefinition = null;
@ -603,6 +790,47 @@ export class DmpEditorBlueprintComponent extends BaseComponent implements OnInit
})
}
private addProfiles(profiles?: DmpDatasetProfile[]) {
for(let i = 0; i < this.selectedDmpBlueprintDefinition.sections.length; i++){
this.sectionTemplates.push(new Array<DatasetProfileModel>());
}
const templates: Array<DmpDatasetProfile> = new Array<DmpDatasetProfile>();
this.selectedDmpBlueprintDefinition.sections.forEach(section => {
if (profiles !== undefined) {
profiles.filter(profile => profile.data.dmpSectionIndex.includes(section.ordinal - 1)).forEach(profile => this.sectionTemplates[section.ordinal - 1].push({id: profile.descriptionTemplateId, label: profile.label, description: ""}));
}
else {
section.descriptionTemplates.forEach(template => {
this.sectionTemplates[section.ordinal - 1].push({id: template.descriptionTemplateId, label: template.label, description: ""})
let found: DmpDatasetProfile = templates.find(dmpDatasetProfile => dmpDatasetProfile.id == template.descriptionTemplateId);
if (found === undefined) {
let data: DmpDatasetProfileSectionsFormModel= new DmpDatasetProfileSectionsFormModel();
data.dmpSectionIndex.push(section.ordinal - 1);
let id = null;
if (profiles !== undefined) {
let existedProfile = profiles.find(profile => profile.descriptionTemplateId == template.descriptionTemplateId);
if (existedProfile !== undefined) {
id = existedProfile.id;
}
}
let profile: DmpDatasetProfile = {
id: id,
descriptionTemplateId: template.descriptionTemplateId,
label: template.label,
data: data
};
templates.push(profile);
}
else {
found.data.dmpSectionIndex.push(section.ordinal - 1);
}
});
}
});
(profiles !== undefined) ? this.formGroup.get('profiles').setValue(profiles) : this.formGroup.get('profiles').setValue(templates);
}
dmpBlueprintAutoCompleteConfiguration: SingleAutoCompleteConfiguration = {
filterFn: this.dmpBlueprintSearch.bind(this),
initialItems: (extraData) => this.dmpBlueprintSearch(''),
@ -788,20 +1016,35 @@ export class DmpEditorBlueprintComponent extends BaseComponent implements OnInit
}
});
}
onOptionSelected(){
onOptionSelected(event, sectionIndex: number){
try{
const profiles = this.formGroup.get('profiles').value as {id:string, label:string}[];
const profileCounts: Map<String, number> = new Map<String, number>();
profiles.forEach((value) => profileCounts.set(value.id, (profileCounts.get(value.id) !== undefined ? profileCounts.get(value.id): 0 ) + 1));
const duplicateProfiles = profiles.filter((value) => {
let isOk = profileCounts.get(value.id) > 1;
if (isOk) {
profileCounts.set(value.id, 0);
const profiles = this.formGroup.get('profiles').value as DmpDatasetProfile[];
let found = profiles.find((value) => value.id === event.id);
if(found !== undefined) {
if(found.data.dmpSectionIndex.indexOf(sectionIndex) === -1){
found.data.dmpSectionIndex.push(sectionIndex);
}
return isOk;
});
duplicateProfiles.forEach((value) => profiles.splice(profiles.lastIndexOf(value), 1));
profiles.sort((a,b)=> a.label.localeCompare(b.label));
else{
this.sectionTemplates[sectionIndex].pop();
}
}
else{
let dmpDatasetProfileSection: DmpDatasetProfileSectionsFormModel = new DmpDatasetProfileSectionsFormModel();
dmpDatasetProfileSection.dmpSectionIndex = [sectionIndex];
profiles.push({id: null, descriptionTemplateId: event.id, label: event.label, data: dmpDatasetProfileSection});
}
this.formGroup.get('profiles').setValue(profiles);
// const profileCounts: Map<String, number> = new Map<String, number>();
// profiles.forEach((value) => profileCounts.set(value.id, (profileCounts.get(value.id) !== undefined ? profileCounts.get(value.id): 0 ) + 1));
// const duplicateProfiles = profiles.filter((value) => {
// let isOk = profileCounts.get(value.id) > 1;
// if (isOk) {
// profileCounts.set(value.id, 0);
// }
// return isOk;
// });
// duplicateProfiles.forEach((value) => profiles.splice(profiles.lastIndexOf(value), 1));
// profiles.sort((a,b)=> a.label.localeCompare(b.label));
}catch{
console.info('Could not sort Dataset Templates')
}

View File

@ -35,7 +35,7 @@ const routes: Routes = [
},
{
path: 'edit/:id',
component: DmpEditorComponent,
component: DmpEditorBlueprintComponent,
data: {
breadcrumb: true,
title: 'GENERAL.TITLES.DMP-EDIT'
@ -75,16 +75,6 @@ const routes: Routes = [
// breadcrumbs: 'new'
// }
// },
// {
// path: 'new',
// component: DmpEditorComponent,
// canActivate: [AuthGuard],
// data: {
// breadcrumbs: 'new',
// title: 'GENERAL.TITLES.DMP-NEW'
// },
// canDeactivate:[CanDeactivateGuard]
// },
{
path: 'new',
component: DmpEditorBlueprintComponent,

View File

@ -24,7 +24,7 @@ export class DmpEditorWizardModel {
this.label = item.label;
this.status = item.status;
this.description = item.description;
this.datasetProfile = item.profiles[0];
this.datasetProfile = {id: item.profiles[0].descriptionTemplateId, label: item.profiles[0].label, description: ""};
this.language = item.language;
return this;
}