fix start new description dialog

This commit is contained in:
amentis 2024-03-19 18:27:30 +02:00
parent c425da9a5f
commit b66932b413
15 changed files with 192 additions and 105 deletions

View File

@ -73,6 +73,7 @@ public class DmpDescriptionTemplateBuilder extends BaseBuilder<DmpDescriptionTem
if (fields.hasField(this.asIndexer(DmpDescriptionTemplate._descriptionTemplateGroupId))) m.setDescriptionTemplateGroupId(d.getDescriptionTemplateGroupId()); if (fields.hasField(this.asIndexer(DmpDescriptionTemplate._descriptionTemplateGroupId))) m.setDescriptionTemplateGroupId(d.getDescriptionTemplateGroupId());
if (fields.hasField(this.asIndexer(DmpDescriptionTemplate._createdAt))) m.setCreatedAt(d.getCreatedAt()); if (fields.hasField(this.asIndexer(DmpDescriptionTemplate._createdAt))) m.setCreatedAt(d.getCreatedAt());
if (fields.hasField(this.asIndexer(DmpDescriptionTemplate._updatedAt))) m.setUpdatedAt(d.getUpdatedAt()); if (fields.hasField(this.asIndexer(DmpDescriptionTemplate._updatedAt))) m.setUpdatedAt(d.getUpdatedAt());
if (fields.hasField(this.asIndexer(DmpDescriptionTemplate._isActive))) m.setIsActive(d.getIsActive());
if (fields.hasField(this.asIndexer(DmpDescriptionTemplate._hash))) m.setHash(this.hashValue(d.getUpdatedAt())); if (fields.hasField(this.asIndexer(DmpDescriptionTemplate._hash))) m.setHash(this.hashValue(d.getUpdatedAt()));
if (!templateFields.isEmpty() && templateItemsMap != null && templateItemsMap.containsKey(d.getDescriptionTemplateGroupId())) m.setDescriptionTemplates(templateItemsMap.get(d.getDescriptionTemplateGroupId())); if (!templateFields.isEmpty() && templateItemsMap != null && templateItemsMap.containsKey(d.getDescriptionTemplateGroupId())) m.setDescriptionTemplates(templateItemsMap.get(d.getDescriptionTemplateGroupId()));
if (!currentDescriptionTemplateFields.isEmpty() && currentDescriptionTemplateItemsMap != null && currentDescriptionTemplateItemsMap.containsKey(d.getDescriptionTemplateGroupId())) m.setCurrentDescriptionTemplate(currentDescriptionTemplateItemsMap.get(d.getDescriptionTemplateGroupId())); if (!currentDescriptionTemplateFields.isEmpty() && currentDescriptionTemplateItemsMap != null && currentDescriptionTemplateItemsMap.containsKey(d.getDescriptionTemplateGroupId())) m.setCurrentDescriptionTemplate(currentDescriptionTemplateItemsMap.get(d.getDescriptionTemplateGroupId()));

View File

@ -239,6 +239,7 @@ public class DmpDescriptionTemplateQuery extends QueryBase<DmpDescriptionTemplat
item.setSectionId(QueryBase.convertSafe(tuple, columns, DmpDescriptionTemplateEntity._sectionId, UUID.class)); item.setSectionId(QueryBase.convertSafe(tuple, columns, DmpDescriptionTemplateEntity._sectionId, UUID.class));
item.setCreatedAt(QueryBase.convertSafe(tuple, columns, DmpDescriptionTemplateEntity._createdAt, Instant.class)); item.setCreatedAt(QueryBase.convertSafe(tuple, columns, DmpDescriptionTemplateEntity._createdAt, Instant.class));
item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, DmpDescriptionTemplateEntity._updatedAt, Instant.class)); item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, DmpDescriptionTemplateEntity._updatedAt, Instant.class));
item.setIsActive(QueryBase.convertSafe(tuple, columns, DmpDescriptionTemplateEntity._isActive, IsActive.class));
return item; return item;
} }
@ -256,6 +257,7 @@ public class DmpDescriptionTemplateQuery extends QueryBase<DmpDescriptionTemplat
else if (item.match(DmpDescriptionTemplate._hash)) return DmpDescriptionTemplateEntity._updatedAt; else if (item.match(DmpDescriptionTemplate._hash)) return DmpDescriptionTemplateEntity._updatedAt;
else if (item.match(DmpDescriptionTemplate._createdAt)) return DmpDescriptionTemplateEntity._createdAt; else if (item.match(DmpDescriptionTemplate._createdAt)) return DmpDescriptionTemplateEntity._createdAt;
else if (item.match(DmpDescriptionTemplate._updatedAt)) return DmpDescriptionTemplateEntity._updatedAt; else if (item.match(DmpDescriptionTemplate._updatedAt)) return DmpDescriptionTemplateEntity._updatedAt;
else if (item.match(DmpDescriptionTemplate._isActive)) return DmpDescriptionTemplateEntity._isActive;
else return null; else return null;
} }

View File

@ -13,6 +13,8 @@ import { TranslateService } from '@ngx-translate/core';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
import { StartNewDmpDialogComponent } from '../dmp/new/start-new-dmp-dialogue/start-new-dmp-dialog.component'; import { StartNewDmpDialogComponent } from '../dmp/new/start-new-dmp-dialogue/start-new-dmp-dialog.component';
import { ReferenceTypeService } from '@app/core/services/reference-type/reference-type.service'; import { ReferenceTypeService } from '@app/core/services/reference-type/reference-type.service';
import { StartNewDescriptionDialogComponent } from '../description/start-new-description-dialog/start-new-description-dialog.component';
import { UntypedFormBuilder, Validators } from '@angular/forms';
@Component({ @Component({
@ -36,7 +38,8 @@ export class DashboardComponent extends BaseComponent implements OnInit {
private language: TranslateService, private language: TranslateService,
private guidedTourService: GuidedTourService, private guidedTourService: GuidedTourService,
private matomoService: MatomoService, private matomoService: MatomoService,
public referenceTypeService: ReferenceTypeService public referenceTypeService: ReferenceTypeService,
private fb: UntypedFormBuilder,
) { ) {
super(); super();
} }
@ -123,24 +126,28 @@ export class DashboardComponent extends BaseComponent implements OnInit {
} }
addNewDescription() { addNewDescription() {
//TODO: add this const formGroup = this.fb.group({
// const dialogRef = this.dialog.open(StartNewDescriptionDialogComponent, { dmpId: this.fb.control(null, Validators.required),
// disableClose: false, sectionId: this.fb.control(null, Validators.required),
// restoreFocus: false, })
// data: {
// startNewDmp: false, const dialogRef = this.dialog.open(StartNewDescriptionDialogComponent, {
// formGroup: new DescriptionWizardEditorModel().buildForm() disableClose: false,
// } restoreFocus: false,
// }); data: {
// dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { startNewDmp: false,
// if (result) { formGroup: formGroup
// if (result.startNewDmp) { }
// this.openNewDmpDialog(); });
// } else { dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
// this.router.navigate(['/plans', 'edit', result.formGroup.get('dmp').value.id]); if (result) {
// } if (result.startNewDmp) {
// } this.openNewDmpDialog();
// }); } else {
this.router.navigate(['/descriptions', 'edit', result.formGroup.get('dmpId').value, result.formGroup.get('sectionId').value]);
}
}
});
} }
public dashboardTour: GuidedTour = { public dashboardTour: GuidedTour = {

View File

@ -5,9 +5,17 @@
</div> </div>
<div mat-dialog-content class="confirmation-message"> <div mat-dialog-content class="confirmation-message">
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<app-single-auto-complete [formControl]="data.formGroup.get('dmpId')" placeholder="{{'DESCRIPTION-COPY-DIALOG.PLACEHOLDER' | translate}}" [configuration]="dmpAutoCompleteConfiguration"> <app-single-auto-complete [formControl]="data.formGroup.get('dmpId')" placeholder="{{'DESCRIPTION-COPY-DIALOG.SELECT-DMP' | translate}}" [configuration]="dmpAutoCompleteConfiguration">
</app-single-auto-complete> </app-single-auto-complete>
</mat-form-field> </mat-form-field>
<div *ngIf="this.sections.length > 1">
<mat-form-field>
<mat-label>{{'DESCRIPTION-COPY-DIALOG.DMP-SECTION' | translate}}</mat-label>
<mat-select [formControl]="data.formGroup.get('sectionId')">
<mat-option *ngFor="let section of sections" [value]="section.id">{{section.label}}</mat-option>
</mat-select>
</mat-form-field>
</div>
<!-- <mat-error *ngIf="data.formControl.hasError('incorrect')">{{getErrorMessage()}}</mat-error> --> <!-- <mat-error *ngIf="data.formControl.hasError('incorrect')">{{getErrorMessage()}}</mat-error> -->
</div> </div>
<div mat-dialog-actions class="row"> <div mat-dialog-actions class="row">

View File

@ -17,6 +17,7 @@ import { DmpStatus } from '@app/core/common/enum/dmp-status';
import { nameof } from 'ts-simple-nameof'; import { nameof } from 'ts-simple-nameof';
import { FilterService } from '@common/modules/text-filter/filter-service'; import { FilterService } from '@common/modules/text-filter/filter-service';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { DescriptionTemplatesInSection, DmpBlueprint, DmpBlueprintDefinition, DmpBlueprintDefinitionSection } from '@app/core/model/dmp-blueprint/dmp-blueprint';
@Component({ @Component({
selector: 'description-copy-dialog-component', selector: 'description-copy-dialog-component',
@ -26,10 +27,11 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms
export class DescriptionCopyDialogComponent { export class DescriptionCopyDialogComponent {
dmpModel: Dmp; dmpModel: Dmp;
sections: DmpBlueprintDefinitionSection[] = [];
descriptionDescriptionTemplateLabel: String; descriptionDescriptionTemplateLabel: String;
dmpAutoCompleteConfiguration: SingleAutoCompleteConfiguration = { //TODO: add filter to only get DMPs that have connection with the same Description Template group. dmpAutoCompleteConfiguration: SingleAutoCompleteConfiguration = { //TODO: add filter to only get DMPs that have connection with the same Description Template group.
initialItems: (data?: any) => this.dmpService.query(this.buildDmpLookup(null,null,null,null, this.dmpDescriptionTemplateLookup)).pipe(map(x => x.items)), initialItems: (data?: any) => this.dmpService.query(this.buildDmpLookup(null,null,null, this.dmpDescriptionTemplateLookup)).pipe(map(x => x.items)),
filterFn: (searchQuery: string, data?: any) => this.dmpService.query(this.buildDmpLookup(searchQuery, null, null, null, this.dmpDescriptionTemplateLookup)).pipe(map(x => x.items)), filterFn: (searchQuery: string, data?: any) => this.dmpService.query(this.buildDmpLookup(searchQuery, null, null, this.dmpDescriptionTemplateLookup)).pipe(map(x => x.items)),
getSelectedItem: (selectedItem: any) => this.dmpService.query(this.buildDmpLookup(null, null, [selectedItem])).pipe(map(x => x.items[0])), getSelectedItem: (selectedItem: any) => this.dmpService.query(this.buildDmpLookup(null, null, [selectedItem])).pipe(map(x => x.items[0])),
displayFn: (item: Dmp) => item.label, displayFn: (item: Dmp) => item.label,
titleFn: (item: Dmp) => item.label, titleFn: (item: Dmp) => item.label,
@ -41,19 +43,22 @@ export class DescriptionCopyDialogComponent {
isActive: [IsActive.Active] isActive: [IsActive.Active]
} as DmpDescriptionTemplateLookup; } as DmpDescriptionTemplateLookup;
private buildDmpLookup(like?: string, excludedIds?: Guid[], ids?: Guid[], statuses?: DmpStatus[], dmpDescriptionTemplateSubQuery?: DmpDescriptionTemplateLookup): DmpLookup { private buildDmpLookup(like?: string, excludedIds?: Guid[], ids?: Guid[], dmpDescriptionTemplateSubQuery?: DmpDescriptionTemplateLookup): DmpLookup {
const lookup: DmpLookup = new DmpLookup(); const lookup: DmpLookup = new DmpLookup();
lookup.page = { size: 100, offset: 0 }; lookup.page = { size: 100, offset: 0 };
if (excludedIds && excludedIds.length > 0) { lookup.excludedIds = excludedIds; } if (excludedIds && excludedIds.length > 0) { lookup.excludedIds = excludedIds; }
if (ids && ids.length > 0) { lookup.ids = ids; } if (ids && ids.length > 0) { lookup.ids = ids; }
lookup.isActive = [IsActive.Active]; lookup.isActive = [IsActive.Active];
lookup.statuses = statuses; lookup.statuses = [DmpStatus.Draft];
lookup.project = { lookup.project = {
fields: [ fields: [
nameof<Dmp>(x => x.id), nameof<Dmp>(x => x.id),
nameof<Dmp>(x => x.label), nameof<Dmp>(x => x.label),
[nameof<Dmp>(x => x.dmpDescriptionTemplates), nameof<DmpDescriptionTemplate>(x => x.sectionId)].join('.'), [nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.definition), nameof<DmpBlueprintDefinition>(x => x.sections), nameof<DmpBlueprintDefinitionSection>(x => x.id)].join('.'),
[nameof<Dmp>(x => x.dmpDescriptionTemplates), nameof<DmpDescriptionTemplate>(x => x.descriptionTemplateGroupId)].join('.'), [nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.definition), nameof<DmpBlueprintDefinition>(x => x.sections), nameof<DmpBlueprintDefinitionSection>(x => x.label)].join('.'),
[nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.definition), nameof<DmpBlueprintDefinition>(x => x.sections), nameof<DmpBlueprintDefinitionSection>(x => x.ordinal)].join('.'),
[nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.definition), nameof<DmpBlueprintDefinition>(x => x.sections), nameof<DmpBlueprintDefinitionSection>(x => x.hasTemplates)].join('.'),
[nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.definition), nameof<DmpBlueprintDefinition>(x => x.sections), nameof<DmpBlueprintDefinitionSection>(x => x.descriptionTemplates), nameof<DescriptionTemplatesInSection>(x => x.descriptionTemplateGroupId)].join('.'),
] ]
}; };
@ -76,10 +81,11 @@ export class DescriptionCopyDialogComponent {
} }
findSection(dmp: Dmp){ findSection(dmp: Dmp){
if(dmp.dmpDescriptionTemplates.length == 1){ this.sections = dmp.blueprint.definition.sections.filter(x => x.hasTemplates == true);
this.data.formGroup.get('sectionId').setValue(dmp.dmpDescriptionTemplates[0].sectionId); if(this.sections.length == 1){
}else if(dmp.dmpDescriptionTemplates.length > 1){ this.data.formGroup.get('sectionId').setValue(this.sections[0].id);
//TODO }else {
this.data.formGroup.get('sectionId').setValue(null);
} }
return dmp.id return dmp.id

View File

@ -1,7 +1,7 @@
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Component, OnInit, ViewChild } from '@angular/core'; import { Component, OnInit, ViewChild } from '@angular/core';
import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { MatPaginator } from '@angular/material/paginator'; import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
@ -34,6 +34,7 @@ import { Guid } from '@common/types/guid';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { debounceTime, takeUntil } from 'rxjs/operators'; import { debounceTime, takeUntil } from 'rxjs/operators';
import { nameof } from 'ts-simple-nameof'; import { nameof } from 'ts-simple-nameof';
import { StartNewDescriptionDialogComponent } from '../start-new-description-dialog/start-new-description-dialog.component';
@Component({ @Component({
selector: 'app-description-listing-component', selector: 'app-description-listing-component',
@ -83,7 +84,8 @@ export class DescriptionListingComponent extends BaseComponent implements OnInit
private authentication: AuthService, private authentication: AuthService,
private guidedTourService: GuidedTourService, private guidedTourService: GuidedTourService,
private httpClient: HttpClient, private httpClient: HttpClient,
private matomoService: MatomoService private matomoService: MatomoService,
private fb: UntypedFormBuilder,
) { ) {
super(); super();
} }
@ -355,25 +357,28 @@ export class DescriptionListingComponent extends BaseComponent implements OnInit
} }
addNewDescription() { addNewDescription() {
//TODO: Add new description dialog const formGroup = this.fb.group({
dmpId: this.fb.control(null, Validators.required),
sectionId: this.fb.control(null, Validators.required),
})
// const dialogRef = this.dialog.open(StartNewDescriptionDialogComponent, { const dialogRef = this.dialog.open(StartNewDescriptionDialogComponent, {
// disableClose: false, disableClose: false,
// restoreFocus: false, restoreFocus: false,
// data: { data: {
// startNewDmp: false, startNewDmp: false,
// formGroup: new DescriptionWizardEditorModel().buildForm() formGroup: formGroup,
// } }
// }); });
// dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
// if (result) { if (result) {
// if (result.startNewDmp) { if (result.startNewDmp) {
// this.openNewDmpDialog(); this.openNewDmpDialog();
// } else { } else {
// this.router.navigate(['/plans', 'edit', result.formGroup.get('dmp').value.id]); this.router.navigate(['/descriptions', 'edit', result.formGroup.get('dmpId').value, result.formGroup.get('sectionId').value]);
// } }
// } }
// }); });
} }
hasLikeCriteria(): boolean { hasLikeCriteria(): boolean {

View File

@ -6,6 +6,7 @@ import { CommonFormsModule } from '@common/forms/common-forms.module';
import { CommonUiModule } from '@common/ui/common-ui.module'; import { CommonUiModule } from '@common/ui/common-ui.module';
import { DescriptionListingRoutingModule } from './description-listing.routing'; import { DescriptionListingRoutingModule } from './description-listing.routing';
import { DescriptionCopyDialogModule } from '../description-copy-dialog/description-copy-dialog.module'; import { DescriptionCopyDialogModule } from '../description-copy-dialog/description-copy-dialog.module';
import { StartNewDescriptionDialogModule } from '../start-new-description-dialog/start-new-description-dialog.module';
@NgModule({ @NgModule({
imports: [ imports: [
@ -13,6 +14,7 @@ import { DescriptionCopyDialogModule } from '../description-copy-dialog/descript
CommonFormsModule, CommonFormsModule,
FormattingModule, FormattingModule,
DescriptionCopyDialogModule, DescriptionCopyDialogModule,
StartNewDescriptionDialogModule,
DescriptionListingRoutingModule DescriptionListingRoutingModule
], ],
declarations: [ declarations: [

View File

@ -6,7 +6,15 @@
<div class="row content"> <div class="row content">
<div class="col dmp-form p-0"> <div class="col dmp-form p-0">
<mat-form-field> <mat-form-field>
<app-single-auto-complete [required]="true" [formControl]="formGroup.get('dmp')" placeholder="{{'DATASET-EDITOR.FIELDS.SELECT-DMP' | translate}}" [configuration]="dmpAutoCompleteConfiguration"></app-single-auto-complete> <app-single-auto-complete [required]="true" [formControl]="formGroup.get('dmpId')" placeholder="{{'START-NEW-DESCRIPTION-DIALOG.SELECT-DMP' | translate}}" [configuration]="dmpAutoCompleteConfiguration"></app-single-auto-complete>
</mat-form-field>
</div>
<div *ngIf="this.sections.length > 1">
<mat-form-field>
<mat-label>{{'START-NEW-DESCRIPTION-DIALOG.DMP-SECTION' | translate}}</mat-label>
<mat-select [formControl]="formGroup.get('sectionId')">
<mat-option *ngFor="let section of sections" [value]="section.id">{{section.label}}</mat-option>
</mat-select>
</mat-form-field> </mat-form-field>
</div> </div>
</div> </div>
@ -18,11 +26,11 @@
<div class="row"> <div class="row">
<div class="col actions"> <div class="col actions">
<div class="col-auto ml-auto"> <div class="col-auto ml-auto">
<button mat-button type="button" class="cancel-btn" (click)="cancel()">{{ 'DATASET-WIZARD.DIALOGUE.CANCEL' | translate }}</button> <button mat-button type="button" class="cancel-btn" (click)="cancel()">{{ 'START-NEW-DESCRIPTION-DIALOG.ACTIONS.CANCEL' | translate }}</button>
</div> </div>
<div class="col-auto p-0"> <div class="col-auto p-0">
<button mat-button *ngIf="formGroup.get('dmp').value" type="button" class="next-btn" (click)="next()">{{ 'DATASET-WIZARD.DIALOGUE.NEXT' | translate }}</button> <button mat-button *ngIf="formGroup.valid" type="button" class="next-btn" (click)="next()">{{ 'START-NEW-DESCRIPTION-DIALOG.ACTIONS.NEXT' | translate }}</button>
<button mat-button *ngIf="!formGroup.get('dmp').value" type="button" class="disabled-btn">{{ 'DATASET-WIZARD.DIALOGUE.NEXT' | translate }}</button> <button mat-button *ngIf="!formGroup.valid" type="button" class="disabled-btn">{{ 'START-NEW-DESCRIPTION-DIALOG.ACTIONS.NEXT' | translate }}</button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -2,13 +2,19 @@ import { Component, Inject } from '@angular/core';
import { UntypedFormGroup } from '@angular/forms'; import { UntypedFormGroup } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
import { DmpStatus } from '@app/core/common/enum/dmp-status'; import { DmpStatus } from '@app/core/common/enum/dmp-status';
import { IsActive } from '@app/core/common/enum/is-active.enum';
import { DescriptionTemplatesInSection, DmpBlueprint, DmpBlueprintDefinition, DmpBlueprintDefinitionSection } from '@app/core/model/dmp-blueprint/dmp-blueprint';
import { Dmp } from '@app/core/model/dmp/dmp'; import { Dmp } from '@app/core/model/dmp/dmp';
import { DmpDescriptionTemplateLookup } from '@app/core/query/dmp-description-template.lookup';
import { DmpLookup } from '@app/core/query/dmp.lookup';
import { DmpService } from '@app/core/services/dmp/dmp.service'; import { DmpService } from '@app/core/services/dmp/dmp.service';
import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration';
import { BaseComponent } from '@common/base/base.component'; import { BaseComponent } from '@common/base/base.component';
import { FilterService } from '@common/modules/text-filter/filter-service';
import { Guid } from '@common/types/guid';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { nameof } from 'ts-simple-nameof';
@Component({ @Component({
selector: 'app-start-new-description-dialog', selector: 'app-start-new-description-dialog',
@ -19,21 +25,49 @@ export class StartNewDescriptionDialogComponent extends BaseComponent {
public isDialog: boolean = false; public isDialog: boolean = false;
public formGroup: UntypedFormGroup; public formGroup: UntypedFormGroup;
public sections: DmpBlueprintDefinitionSection[] = [];
dmpAutoCompleteConfiguration: SingleAutoCompleteConfiguration = { dmpAutoCompleteConfiguration: SingleAutoCompleteConfiguration = {
filterFn: this.searchDmp.bind(this), initialItems: (data?: any) => this.dmpService.query(this.buildAutocompleteLookup()).pipe(map(x => x.items)),
initialItems: (extraData) => this.searchDmp(''), filterFn: (searchQuery: string, data?: any) => this.dmpService.query(this.buildAutocompleteLookup(searchQuery)).pipe(map(x => x.items)),
displayFn: (item) => this.getDatasetDisplay(item), getSelectedItem: (selectedItem: any) => this.dmpService.query(this.buildAutocompleteLookup(null, null, [selectedItem])).pipe(map(x => x.items[0])),
titleFn: (item) => item['label'], displayFn: (item: Dmp) => item.label,
subtitleFn: (item) => { try { return this.language.instant('DATASET-WIZARD.FIRST-STEP.SUB-TITLE') + new Date(item['creationTime']).toISOString(); } catch { return '-'; } } titleFn: (item: Dmp) => item.label,
valueAssign: (item: Dmp) => this.findSection(item),
}; };
private buildAutocompleteLookup(like?: string, excludedIds?: Guid[], ids?: Guid[], statuses?: DmpStatus[], dmpDescriptionTemplateSubQuery?: DmpDescriptionTemplateLookup): DmpLookup {
const lookup: DmpLookup = new DmpLookup();
lookup.page = { size: 100, offset: 0 };
if (excludedIds && excludedIds.length > 0) { lookup.excludedIds = excludedIds; }
if (ids && ids.length > 0) { lookup.ids = ids; }
lookup.isActive = [IsActive.Active];
lookup.statuses = [DmpStatus.Draft];
lookup.project = {
fields: [
nameof<Dmp>(x => x.id),
nameof<Dmp>(x => x.label),
nameof<Dmp>(x => x.createdAt),
[nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.definition), nameof<DmpBlueprintDefinition>(x => x.sections), nameof<DmpBlueprintDefinitionSection>(x => x.id)].join('.'),
[nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.definition), nameof<DmpBlueprintDefinition>(x => x.sections), nameof<DmpBlueprintDefinitionSection>(x => x.label)].join('.'),
[nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.definition), nameof<DmpBlueprintDefinition>(x => x.sections), nameof<DmpBlueprintDefinitionSection>(x => x.ordinal)].join('.'),
[nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.definition), nameof<DmpBlueprintDefinition>(x => x.sections), nameof<DmpBlueprintDefinitionSection>(x => x.hasTemplates)].join('.'),
[nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.definition), nameof<DmpBlueprintDefinition>(x => x.sections), nameof<DmpBlueprintDefinitionSection>(x => x.descriptionTemplates), nameof<DescriptionTemplatesInSection>(x => x.descriptionTemplateGroupId)].join('.'),
]
};
if (dmpDescriptionTemplateSubQuery != null) lookup.dmpDescriptionTemplateSubQuery = dmpDescriptionTemplateSubQuery;
lookup.order = { items: [nameof<Dmp>(x => x.label)] };
if (like) { lookup.like = this.filterService.transformLike(like); }
return lookup;
}
constructor( constructor(
public dialogRef: MatDialogRef<StartNewDescriptionDialogComponent>, public dialogRef: MatDialogRef<StartNewDescriptionDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any, @Inject(MAT_DIALOG_DATA) public data: any,
public dialog: MatDialog, public dialog: MatDialog,
private language: TranslateService, private language: TranslateService,
private dmpService: DmpService private dmpService: DmpService,
private filterService: FilterService,
) { ) {
super(); super();
this.formGroup = data.formGroup; this.formGroup = data.formGroup;
@ -60,16 +94,15 @@ export class StartNewDescriptionDialogComponent extends BaseComponent {
this.dialogRef.close(this.data); this.dialogRef.close(this.data);
} }
searchDmp(query: string): Observable<Dmp[]> { findSection(dmp: Dmp){
// TODO refactor this.sections = dmp.blueprint.definition.sections.filter(x => x.hasTemplates == true);
// const fields: Array<string> = new Array<string>(); if(this.sections.length == 1){
// fields.push('-created'); this.formGroup.get('sectionId').setValue(this.sections[0].id);
// const dmpDataTableRequest: DataTableRequest<DmpCriteria> = new DataTableRequest(0, null, { fields: fields }); }else {
// dmpDataTableRequest.criteria = new DmpCriteria(); this.formGroup.get('sectionId').setValue(null);
// dmpDataTableRequest.criteria.like = query; }
// dmpDataTableRequest.criteria.status = DmpStatus.Draft;
// return this.dmpService.getPaged(dmpDataTableRequest, "autocomplete").pipe(map(x => x.data)); return dmp.id
return null;
} }
getDatasetDisplay(item: any): string { getDatasetDisplay(item: any): string {

View File

@ -3,12 +3,14 @@ import { FormattingModule } from '@app/core/formatting.module';
import { CommonFormsModule } from '@common/forms/common-forms.module'; import { CommonFormsModule } from '@common/forms/common-forms.module';
import { CommonUiModule } from '@common/ui/common-ui.module'; import { CommonUiModule } from '@common/ui/common-ui.module';
import { StartNewDescriptionDialogComponent } from './start-new-description-dialog.component'; import { StartNewDescriptionDialogComponent } from './start-new-description-dialog.component';
import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module';
@NgModule({ @NgModule({
imports: [ imports: [
CommonUiModule, CommonUiModule,
CommonFormsModule, CommonFormsModule,
FormattingModule, FormattingModule,
AutoCompleteModule
], ],
declarations: [ declarations: [
StartNewDescriptionDialogComponent, StartNewDescriptionDialogComponent,

View File

@ -22,7 +22,7 @@
{{'DMP-EDITOR.ACTIONS.SAVE' | translate}} {{'DMP-EDITOR.ACTIONS.SAVE' | translate}}
</button> </button>
</div> </div>
<button *ngIf="lockStatus" mat-raised-button disabled class="dataset-save-btn cursor-default" type="button">{{ 'DMP-EDITOR.LOCKED' | translate}}</button> <button *ngIf="lockStatus" mat-raised-button disabled class="description-save-btn cursor-default" type="button">{{ 'DMP-EDITOR.LOCKED' | translate}}</button>
</div> </div>
</div> </div>
</div> </div>
@ -86,18 +86,18 @@
<!-- <div *ngIf="selectedBlueprint?.definition"> --> <!-- <div *ngIf="selectedBlueprint?.definition"> -->
<div *ngFor="let section of selectedBlueprint?.definition?.sections; let i=index"> <div *ngFor="let section of selectedBlueprint?.definition?.sections; let i=index">
<li (click)="changeStep(i + 1)" [ngClass]="{'active': this.step === (i + 1)}">{{section.label}}</li> <li (click)="changeStep(i + 1)" [ngClass]="{'active': this.step === (i + 1)}">{{section.label}}</li>
<ol class="datasetsInSection"> <ol class="descriptionsInSection">
<li *ngFor="let description of descriptionsInSection(section.id); let descriptionIndex = index" (click)="editDescription(description.id, false)" class="active-dataset"> <li *ngFor="let description of descriptionsInSection(section.id); let descriptionIndex = index" (click)="editDescription(description.id, false)" class="active-description">
<div class="d-flex flex-direction-row"> <div class="d-flex flex-direction-row">
<div class="label" matTooltip="{{description.label}}">{{'DMP-EDITOR.DESCRIPTION' | translate}}: {{ description.label }}</div> <div class="label" matTooltip="{{description.label}}">{{'DMP-EDITOR.DESCRIPTION' | translate}}: {{ description.label }}</div>
<mat-icon *ngIf="description.status !== descriptionStatusEnum.Finalized && canDeleteSection(section.id)" class="ml-2 mr-2 remove-dataset size-16" matTooltip="{{'DMP-EDITOR.ACTIONS.DELETE' | translate}}" (click)="$event.stopPropagation(); removeDescription(description.id)">close</mat-icon> <mat-icon *ngIf="description.status !== descriptionStatusEnum.Finalized && canDeleteSection(section.id)" class="ml-2 mr-2 remove-description size-16" matTooltip="{{'DMP-EDITOR.ACTIONS.DELETE' | translate}}" (click)="$event.stopPropagation(); removeDescription(description.id)">close</mat-icon>
<mat-icon *ngIf="description.status === descriptionStatusEnum.Finalized" class="ml-2 mr-2 status-icon check-icon size-16" matTooltip="{{'TYPES.DATASET-STATUS.FINALISED' | translate}}">check</mat-icon> <mat-icon *ngIf="description.status === descriptionStatusEnum.Finalized" class="ml-2 mr-2 status-icon check-icon size-16" matTooltip="{{'TYPES.DESCRIPTION-STATUS.FINALISED' | translate}}">check</mat-icon>
</div> </div>
</li> </li>
</ol> </ol>
<ul *ngIf="item.id && section.hasTemplates && canEditSection(section.id)" class="add-dataset-option"> <ul *ngIf="item.id && section.hasTemplates && canEditSection(section.id)" class="add-description-option">
<li> <li>
<a class="add-dataset-action" [routerLink]="['/descriptions/edit/' + item.id + '/' + section.id]"> <a class="add-description-action" [routerLink]="['/descriptions/edit/' + item.id + '/' + section.id]">
<mat-icon>add</mat-icon>{{'DMP-EDITOR.ACTIONS.ADD-DESCRIPTION-IN-SECTION' | translate}} <mat-icon>add</mat-icon>{{'DMP-EDITOR.ACTIONS.ADD-DESCRIPTION-IN-SECTION' | translate}}
</a> </a>
</li> </li>
@ -111,7 +111,7 @@
<span class="material-icons">chevron_left</span> <span class="material-icons">chevron_left</span>
<div>{{'DMP-EDITOR.ACTIONS.PREVIOUS-STEP' | translate}}</div> <div>{{'DMP-EDITOR.ACTIONS.PREVIOUS-STEP' | translate}}</div>
</div> </div>
<div *ngIf="this.step < this.maxStep" mat-raised-button type="button" class="col-auto stepper-btn ml-auto" [ngClass]="{ 'next-disabled': this.step === this.maxStep, 'next': this.step < selectedBlueprint?.definition?.sections?.length, 'dataset-next': this.step >= selectedBlueprint?.definition?.sections?.length }" (click)="nextStep()"> <div *ngIf="this.step < this.maxStep" mat-raised-button type="button" class="col-auto stepper-btn ml-auto" [ngClass]="{ 'next-disabled': this.step === this.maxStep, 'next': this.step < selectedBlueprint?.definition?.sections?.length, 'description-next': this.step >= selectedBlueprint?.definition?.sections?.length }" (click)="nextStep()">
<div>{{'DMP-EDITOR.ACTIONS.NEXT-STEP' | translate}}</div> <div>{{'DMP-EDITOR.ACTIONS.NEXT-STEP' | translate}}</div>
<span class="material-icons">chevron_right</span> <span class="material-icons">chevron_right</span>
</div> </div>

View File

@ -38,7 +38,7 @@
} }
} }
.datasetsInSection { .descriptionsInSection {
counter-reset: item counter-reset: item
} }
@ -116,7 +116,7 @@
opacity: 1; opacity: 1;
} }
.stepper-list .active-dataset { .stepper-list .active-description {
color: #212121; color: #212121;
font-weight: 700; font-weight: 700;
opacity: 1; opacity: 1;
@ -149,11 +149,11 @@ mat-icon.size-16 {
margin-top: 0.4rem; margin-top: 0.4rem;
} }
.remove-dataset { .remove-description {
color: #f16868; color: #f16868;
} }
.remove-dataset:hover { .remove-description:hover {
color: #f16868; color: #f16868;
} }
@ -186,7 +186,7 @@ mat-icon.size-16 {
cursor: pointer; cursor: pointer;
} }
.add-dataset-btn { .add-description-btn {
background: var(--secondary-color) 0% 0% no-repeat padding-box; background: var(--secondary-color) 0% 0% no-repeat padding-box;
box-shadow: 0px 3px 6px #1e202029; box-shadow: 0px 3px 6px #1e202029;
font-weight: 500; font-weight: 500;
@ -197,11 +197,11 @@ mat-icon.size-16 {
font-size: 13.8px; font-size: 13.8px;
} }
.add-dataset-option { .add-description-option {
list-style-type: none; list-style-type: none;
} }
.add-dataset-action { .add-description-action {
display: flex; display: flex;
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
@ -215,7 +215,7 @@ mat-icon.size-16 {
cursor: pointer; cursor: pointer;
} }
.dataset-next { .description-next {
background: var(--secondary-color) 0% 0% no-repeat padding-box; background: var(--secondary-color) 0% 0% no-repeat padding-box;
color: #212121; color: #212121;
box-shadow: 0px 3px 6px #1e202029; box-shadow: 0px 3px 6px #1e202029;
@ -224,7 +224,7 @@ mat-icon.size-16 {
} }
.previous-disabled, .previous-disabled,
.add-dataset-btn-disabled { .add-description-btn-disabled {
border: 1px solid #b5b5b5; border: 1px solid #b5b5b5;
color: #b5b5b5 !important; color: #b5b5b5 !important;
cursor: auto !important; cursor: auto !important;

View File

@ -205,7 +205,7 @@ export class DmpEditorComponent extends BaseEditor<DmpEditorModel, Dmp> implemen
prepareForm(data: Dmp) { prepareForm(data: Dmp) {
try { try {
this.editorModel = data ? new DmpEditorModel().fromModel(data) : new DmpEditorModel(); this.editorModel = data ? new DmpEditorModel().fromModel(data) : new DmpEditorModel();
if (data.descriptions) { if (data && data.descriptions) {
if (data.status == DmpStatus.Finalized) { if (data.status == DmpStatus.Finalized) {
data.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status === DescriptionStatus.Finalized); data.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status === DescriptionStatus.Finalized);
} else { } else {
@ -217,19 +217,23 @@ export class DmpEditorComponent extends BaseEditor<DmpEditorModel, Dmp> implemen
this.selectedBlueprint = data?.blueprint; this.selectedBlueprint = data?.blueprint;
this.isDeleted = data ? data.isActive === IsActive.Inactive : false; this.isDeleted = data ? data.isActive === IsActive.Inactive : false;
const descriptionSectionPermissionResolverModel: DescriptionSectionPermissionResolver = { if (data){
dmpId: data.id, const descriptionSectionPermissionResolverModel: DescriptionSectionPermissionResolver = {
sectionIds: data?.blueprint?.definition?.sections?.map(x => x.id), dmpId: data.id,
permissions: [AppPermission.EditDescription, AppPermission.DeleteDescription] sectionIds: data?.blueprint?.definition?.sections?.map(x => x.id),
permissions: [AppPermission.EditDescription, AppPermission.DeleteDescription]
}
this.descriptionService.getDescriptionSectionPermissions(descriptionSectionPermissionResolverModel)
.pipe(takeUntil(this._destroyed)).subscribe(
complete => {
this.permissionPerSection = complete,
this.buildForm();
},
error => this.onCallbackError(error)
);
}else{
this.buildForm();
} }
this.descriptionService.getDescriptionSectionPermissions(descriptionSectionPermissionResolverModel)
.pipe(takeUntil(this._destroyed)).subscribe(
complete => {
this.permissionPerSection = complete,
this.buildForm();
},
error => this.onCallbackError(error)
);
} catch (error) { } catch (error) {
this.logger.error('Could not parse Dmp item: ' + data + error); this.logger.error('Could not parse Dmp item: ' + data + error);

View File

@ -123,9 +123,9 @@ export class DmpEditorModel extends BaseEditorModel implements DmpPersist {
baseValidationArray.push({ key: 'status', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'status')] }); baseValidationArray.push({ key: 'status', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'status')] });
baseValidationArray.push({ key: 'properties', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'properties')] }); baseValidationArray.push({ key: 'properties', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'properties')] });
baseValidationArray.push({ key: 'description', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'description')] }); baseValidationArray.push({ key: 'description', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'description')] });
baseValidationArray.push({ key: 'language', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'language')] }); baseValidationArray.push({ key: 'language', validators: [BackendErrorValidator(this.validationErrorModel, 'language')] });
baseValidationArray.push({ key: 'blueprint', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'blueprint')] }); baseValidationArray.push({ key: 'blueprint', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'blueprint')] });
baseValidationArray.push({ key: 'accessType', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'accessType')] }); baseValidationArray.push({ key: 'accessType', validators: [BackendErrorValidator(this.validationErrorModel, 'accessType')] });
baseValidationArray.push({ key: 'descriptionTemplates', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'descriptionTemplates')] }); baseValidationArray.push({ key: 'descriptionTemplates', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'descriptionTemplates')] });
baseValidationArray.push({ key: 'users', validators: [BackendErrorValidator(this.validationErrorModel, `users`)] }); baseValidationArray.push({ key: 'users', validators: [BackendErrorValidator(this.validationErrorModel, `users`)] });
baseValidationArray.push({ key: 'hash', validators: [] }); baseValidationArray.push({ key: 'hash', validators: [] });

View File

@ -1127,7 +1127,8 @@
}, },
"DESCRIPTION-COPY-DIALOG": { "DESCRIPTION-COPY-DIALOG": {
"TITLE": "Copy Description to DMP", "TITLE": "Copy Description to DMP",
"PLACEHOLDER": "Search DMP" "SELECT-DMP": "Select DMP",
"DMP-SECTION": "Select Section"
}, },
"PREFILL-DESCRIPTION-DIALOG": { "PREFILL-DESCRIPTION-DIALOG": {
"TITLE": "Initialize your Dataset", "TITLE": "Initialize your Dataset",
@ -2776,7 +2777,7 @@
"LATEST-ACTIVITY": "Latest Activity", "LATEST-ACTIVITY": "Latest Activity",
"DMP-ABOUT-BEG": "A DMP in {{ APP_NAME }} consists of key information about research, such as purpose, objectives and researchers involved, but also about documentation of research datasets, namely", "DMP-ABOUT-BEG": "A DMP in {{ APP_NAME }} consists of key information about research, such as purpose, objectives and researchers involved, but also about documentation of research datasets, namely",
"DMP-ABOUT-END": ", that highlight the steps followed and the means used across data management activities.", "DMP-ABOUT-END": ", that highlight the steps followed and the means used across data management activities.",
"SELECT-DMP": "Select a DMP for your Dataset", "SELECT-DMP": "Select a DMP for your Description",
"ACTIONS": { "ACTIONS": {
"ADD-DESCRIPTION": "Add Description", "ADD-DESCRIPTION": "Add Description",
"ADD-DMP-DESCRIPTION": "Add DMP Description" "ADD-DMP-DESCRIPTION": "Add DMP Description"
@ -2941,6 +2942,14 @@
"CANCEL": "Cancel" "CANCEL": "Cancel"
} }
}, },
"START-NEW-DESCRIPTION-DIALOG": {
"SELECT-DMP": "Select DMP",
"DMP-SECTION": "Select Section",
"ACTIONS": {
"NEXT": "Next",
"CANCEL": "Cancel"
}
},
"DRAFTS": { "DRAFTS": {
"FOR-DMP": "For DMP:", "FOR-DMP": "For DMP:",
"FOR-GRANT": "For Grant:" "FOR-GRANT": "For Grant:"