2024-02-09 21:46:05 +01:00
|
|
|
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
|
2023-12-28 16:18:49 +01:00
|
|
|
import { DatePipe } from '@angular/common';
|
2024-04-04 17:27:59 +02:00
|
|
|
import { Component, EventEmitter, OnInit } from '@angular/core';
|
2024-02-09 21:46:05 +01:00
|
|
|
import { FormArray, UntypedFormArray, UntypedFormGroup } from '@angular/forms';
|
2023-12-28 16:18:49 +01:00
|
|
|
import { MatDialog } from '@angular/material/dialog';
|
2024-03-20 11:35:55 +01:00
|
|
|
import { ActivatedRoute, Router } from '@angular/router';
|
2023-12-28 16:18:49 +01:00
|
|
|
import { DescriptionStatus } from '@app/core/common/enum/description-status';
|
2024-02-09 21:46:05 +01:00
|
|
|
import { DmpAccessType } from '@app/core/common/enum/dmp-access-type';
|
|
|
|
import { DmpBlueprintFieldCategory } from '@app/core/common/enum/dmp-blueprint-field-category';
|
2023-12-28 16:18:49 +01:00
|
|
|
import { DmpBlueprintExtraFieldDataType } from '@app/core/common/enum/dmp-blueprint-field-type';
|
2024-02-09 21:46:05 +01:00
|
|
|
import { DmpBlueprintStatus } from '@app/core/common/enum/dmp-blueprint-status';
|
2023-12-28 16:18:49 +01:00
|
|
|
import { DmpBlueprintSystemFieldType } from '@app/core/common/enum/dmp-blueprint-system-field-type';
|
2024-02-09 21:46:05 +01:00
|
|
|
import { DmpContactType } from '@app/core/common/enum/dmp-contact-type';
|
2023-12-28 16:18:49 +01:00
|
|
|
import { DmpStatus } from '@app/core/common/enum/dmp-status';
|
2024-03-20 11:35:55 +01:00
|
|
|
import { DmpUserRole } from '@app/core/common/enum/dmp-user-role';
|
|
|
|
import { DmpUserType } from '@app/core/common/enum/dmp-user-type';
|
2023-12-28 16:18:49 +01:00
|
|
|
import { IsActive } from '@app/core/common/enum/is-active.enum';
|
2024-03-20 11:35:55 +01:00
|
|
|
import { LockTargetType } from '@app/core/common/enum/lock-target-type';
|
2023-12-28 16:18:49 +01:00
|
|
|
import { AppPermission } from '@app/core/common/enum/permission.enum';
|
2024-03-20 11:35:55 +01:00
|
|
|
import { DescriptionSectionPermissionResolver } from '@app/core/model/description/description';
|
2024-04-03 16:50:47 +02:00
|
|
|
import { DmpBlueprint, DmpBlueprintDefinitionSection } from '@app/core/model/dmp-blueprint/dmp-blueprint';
|
2023-12-28 16:18:49 +01:00
|
|
|
import { Dmp, DmpPersist } from '@app/core/model/dmp/dmp';
|
2024-02-09 21:46:05 +01:00
|
|
|
import { LanguageInfo } from '@app/core/model/language-info';
|
2023-12-28 16:18:49 +01:00
|
|
|
import { AuthService } from '@app/core/services/auth/auth.service';
|
|
|
|
import { ConfigurationService } from '@app/core/services/configuration/configuration.service';
|
2024-02-09 21:46:05 +01:00
|
|
|
import { LanguageInfoService } from '@app/core/services/culture/language-info-service';
|
|
|
|
import { DescriptionTemplateService } from '@app/core/services/description-template/description-template.service';
|
2024-03-20 11:35:55 +01:00
|
|
|
import { DescriptionService } from '@app/core/services/description/description.service';
|
2023-12-28 16:18:49 +01:00
|
|
|
import { DmpBlueprintService } from '@app/core/services/dmp/dmp-blueprint.service';
|
2023-12-29 16:04:16 +01:00
|
|
|
import { DmpService } from '@app/core/services/dmp/dmp.service';
|
2023-12-28 16:18:49 +01:00
|
|
|
import { LockService } from '@app/core/services/lock/lock.service';
|
|
|
|
import { LoggingService } from '@app/core/services/logging/logging-service';
|
|
|
|
import { MatomoService } from '@app/core/services/matomo/matomo-service';
|
|
|
|
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
|
2024-02-09 21:46:05 +01:00
|
|
|
import { UserService } from '@app/core/services/user/user.service';
|
|
|
|
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
|
2023-12-28 16:18:49 +01:00
|
|
|
import { QueryParamsService } from '@app/core/services/utilities/query-params.service';
|
2024-02-09 21:46:05 +01:00
|
|
|
import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration';
|
2023-12-28 16:18:49 +01:00
|
|
|
import { PopupNotificationDialogComponent } from '@app/library/notification/popup/popup-notification.component';
|
|
|
|
import { isNullOrUndefined } from '@app/utilities/enhancers/utils';
|
|
|
|
import { BaseEditor } from '@common/base/base-editor';
|
|
|
|
import { FormService } from '@common/forms/form-service';
|
|
|
|
import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component';
|
|
|
|
import { HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service';
|
|
|
|
import { FilterService } from '@common/modules/text-filter/filter-service';
|
|
|
|
import { Guid } from '@common/types/guid';
|
|
|
|
import { TranslateService } from '@ngx-translate/core';
|
2024-04-04 17:27:59 +02:00
|
|
|
import { Observable, interval, of } from 'rxjs';
|
2023-12-28 16:18:49 +01:00
|
|
|
import { map, takeUntil } from 'rxjs/operators';
|
|
|
|
import { DmpEditorModel } from './dmp-editor.model';
|
|
|
|
import { DmpEditorResolver } from './dmp-editor.resolver';
|
|
|
|
import { DmpEditorService } from './dmp-editor.service';
|
2024-03-29 16:37:08 +01:00
|
|
|
import { DescriptionTemplatePreviewDialogComponent } from '@app/ui/admin/description-template/description-template-preview/description-template-preview-dialog.component';
|
2023-12-28 16:18:49 +01:00
|
|
|
|
|
|
|
@Component({
|
|
|
|
selector: 'app-dmp-editor',
|
|
|
|
templateUrl: './dmp-editor.component.html',
|
|
|
|
styleUrls: ['./dmp-editor.component.scss'],
|
|
|
|
providers: [DmpEditorService]
|
|
|
|
})
|
|
|
|
export class DmpEditorComponent extends BaseEditor<DmpEditorModel, Dmp> implements OnInit {
|
|
|
|
|
|
|
|
isNew = true;
|
|
|
|
isDeleted = false;
|
2024-04-05 10:11:31 +02:00
|
|
|
goToNextStep = true;
|
2023-12-28 16:18:49 +01:00
|
|
|
item: Dmp;
|
|
|
|
selectedBlueprint: DmpBlueprint;
|
|
|
|
step: number = 0;
|
2024-03-20 11:35:55 +01:00
|
|
|
|
|
|
|
//Enums
|
2023-12-28 16:18:49 +01:00
|
|
|
descriptionStatusEnum = DescriptionStatus;
|
2024-02-09 21:46:05 +01:00
|
|
|
dmpBlueprintSectionFieldCategoryEnum = DmpBlueprintFieldCategory;
|
2023-12-28 16:18:49 +01:00
|
|
|
dmpBlueprintSystemFieldTypeEnum = DmpBlueprintSystemFieldType;
|
|
|
|
dmpBlueprintExtraFieldDataTypeEnum = DmpBlueprintExtraFieldDataType;
|
2024-01-15 17:47:34 +01:00
|
|
|
dmpAccessTypeEnum = DmpAccessType;
|
|
|
|
dmpAccessTypeEnumValues = this.enumUtils.getEnumValues<DmpAccessType>(DmpAccessType);
|
2024-01-31 10:27:36 +01:00
|
|
|
dmpContactTypeEnum = DmpContactType;
|
|
|
|
dmpContactTypeEnumValues = this.enumUtils.getEnumValues<DmpContactType>(DmpContactType);
|
2024-02-21 12:10:18 +01:00
|
|
|
dmpUserTypeEnum = DmpUserType;
|
|
|
|
dmpUserTypeEnumValues = this.enumUtils.getEnumValues<DmpUserType>(DmpUserType);
|
2024-02-20 16:00:20 +01:00
|
|
|
dmpUserRoleEnumValues = this.enumUtils.getEnumValues<DmpUserRole>(DmpUserRole);
|
2024-03-19 16:21:50 +01:00
|
|
|
|
|
|
|
permissionPerSection: Map<Guid, string[]>;
|
|
|
|
|
2024-03-26 09:34:51 +01:00
|
|
|
hoveredContact: number = -1;
|
|
|
|
|
2024-01-31 16:07:16 +01:00
|
|
|
singleAutocompleteBlueprintConfiguration: SingleAutoCompleteConfiguration = {
|
|
|
|
initialItems: (data?: any) => this.dmpBlueprintService.query(this.dmpBlueprintService.buildAutocompleteLookup(null, null, null, [DmpBlueprintStatus.Finalized])).pipe(map(x => x.items)),
|
|
|
|
filterFn: (searchQuery: string, data?: any) => this.dmpBlueprintService.query(this.dmpBlueprintService.buildAutocompleteLookup(searchQuery, null, null, [DmpBlueprintStatus.Finalized])).pipe(map(x => x.items)),
|
|
|
|
getSelectedItem: (selectedItem: any) => this.dmpBlueprintService.query(this.dmpBlueprintService.buildAutocompleteLookup(null, null, [selectedItem])).pipe(map(x => x.items[0])),
|
|
|
|
displayFn: (item: DmpBlueprint) => item.label,
|
2024-04-03 16:50:47 +02:00
|
|
|
subtitleFn: (item: DmpBlueprint) => this.language.instant('DMP-EDITOR.FIELDS.DMP-BLUEPRINT-VERSION') + ' '+ item.version,
|
2024-01-31 16:07:16 +01:00
|
|
|
titleFn: (item: DmpBlueprint) => item.label,
|
|
|
|
valueAssign: (item: DmpBlueprint) => item.id,
|
|
|
|
};
|
2023-12-28 16:18:49 +01:00
|
|
|
|
|
|
|
protected get canDelete(): boolean {
|
2024-03-20 11:35:55 +01:00
|
|
|
return !this.isDeleted && !this.isNew && (this.hasPermission(this.authService.permissionEnum.DeleteDmp) || this.item?.authorizationFlags?.some(x => x === AppPermission.DeleteDmp));
|
2023-12-28 16:18:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
protected get canSave(): boolean {
|
2024-03-20 11:35:55 +01:00
|
|
|
return !this.isDeleted && (this.hasPermission(this.authService.permissionEnum.EditDmp) || this.item?.authorizationFlags?.some(x => x === AppPermission.EditDmp));
|
2023-12-28 16:18:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
protected get canFinalize(): boolean {
|
2024-03-20 11:35:55 +01:00
|
|
|
return !this.isDeleted && (this.hasPermission(this.authService.permissionEnum.EditDmp) || this.item?.authorizationFlags?.some(x => x === AppPermission.EditDmp));
|
2023-12-28 16:18:49 +01:00
|
|
|
}
|
|
|
|
|
2024-03-19 16:21:50 +01:00
|
|
|
protected canEditSection(id: Guid): boolean {
|
|
|
|
return !this.isDeleted && (this.hasPermission(this.authService.permissionEnum.EditDescription) || this.item?.authorizationFlags?.some(x => x === AppPermission.EditDescription) || (
|
|
|
|
this.permissionPerSection && this.permissionPerSection[id.toString()] && this.permissionPerSection[id.toString()].some(x => x === AppPermission.EditDescription)
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
protected canDeleteSection(id: Guid): boolean {
|
|
|
|
return !this.isDeleted && (this.hasPermission(this.authService.permissionEnum.DeleteDescription) || this.item?.authorizationFlags?.some(x => x === AppPermission.DeleteDescription) || (
|
|
|
|
this.permissionPerSection && this.permissionPerSection[id.toString()] && this.permissionPerSection[id.toString()].some(x => x === AppPermission.DeleteDescription)
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-12-28 16:18:49 +01:00
|
|
|
|
|
|
|
private hasPermission(permission: AppPermission): boolean {
|
2024-03-20 11:35:55 +01:00
|
|
|
return this.authService.hasPermission(permission) || this.item?.authorizationFlags?.some(x => x === permission) || this.editorModel?.permissions?.includes(permission);
|
2023-12-28 16:18:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
constructor(
|
|
|
|
// BaseFormEditor injected dependencies
|
|
|
|
protected dialog: MatDialog,
|
|
|
|
protected language: TranslateService,
|
|
|
|
protected formService: FormService,
|
|
|
|
protected router: Router,
|
|
|
|
protected uiNotificationService: UiNotificationService,
|
|
|
|
protected httpErrorHandlingService: HttpErrorHandlingService,
|
|
|
|
protected filterService: FilterService,
|
|
|
|
protected datePipe: DatePipe,
|
|
|
|
protected route: ActivatedRoute,
|
|
|
|
protected queryParamsService: QueryParamsService,
|
2024-03-21 08:46:18 +01:00
|
|
|
protected lockService: LockService,
|
|
|
|
protected authService: AuthService,
|
|
|
|
protected configurationService: ConfigurationService,
|
2023-12-28 16:18:49 +01:00
|
|
|
// Rest dependencies. Inject any other needed deps here:
|
2023-12-29 16:04:16 +01:00
|
|
|
private dmpService: DmpService,
|
2023-12-28 16:18:49 +01:00
|
|
|
private logger: LoggingService,
|
|
|
|
public dmpBlueprintService: DmpBlueprintService,
|
|
|
|
private matomoService: MatomoService,
|
2024-01-15 17:47:34 +01:00
|
|
|
// public visibilityRulesService: VisibilityRulesService,
|
|
|
|
private languageInfoService: LanguageInfoService,
|
2024-01-31 16:07:16 +01:00
|
|
|
public enumUtils: EnumUtils,
|
2024-01-31 10:27:36 +01:00
|
|
|
public descriptionTemplateService: DescriptionTemplateService,
|
2024-03-15 17:28:39 +01:00
|
|
|
public userService: UserService,
|
|
|
|
public descriptionService: DescriptionService
|
2023-12-28 16:18:49 +01:00
|
|
|
|
|
|
|
) {
|
2024-03-21 08:46:18 +01:00
|
|
|
super(dialog, language, formService, router, uiNotificationService, httpErrorHandlingService, filterService, datePipe, route, queryParamsService, lockService, authService, configurationService);
|
2023-12-28 16:18:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ngOnInit(): void {
|
|
|
|
this.matomoService.trackPageView('DMP Editor');
|
|
|
|
super.ngOnInit();
|
|
|
|
}
|
|
|
|
|
|
|
|
getItem(itemId: Guid, successFunction: (item: Dmp) => void) {
|
|
|
|
this.dmpService.getSingle(itemId, DmpEditorResolver.lookupFields())
|
|
|
|
.pipe(map(data => data as Dmp), takeUntil(this._destroyed))
|
|
|
|
.subscribe(
|
|
|
|
data => successFunction(data),
|
|
|
|
error => this.onCallbackError(error)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
prepareForm(data: Dmp) {
|
|
|
|
try {
|
|
|
|
this.editorModel = data ? new DmpEditorModel().fromModel(data) : new DmpEditorModel();
|
2024-04-05 08:44:26 +02:00
|
|
|
if (data) {
|
|
|
|
if(data.descriptions){
|
|
|
|
if (data.status == DmpStatus.Finalized) {
|
|
|
|
data.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status === DescriptionStatus.Finalized);
|
|
|
|
} else {
|
|
|
|
data.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status !== DescriptionStatus.Canceled);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(data.dmpDescriptionTemplates){
|
|
|
|
data.dmpDescriptionTemplates = data.dmpDescriptionTemplates.filter(x => x.isActive === IsActive.Active);
|
2024-03-15 17:28:39 +01:00
|
|
|
}
|
2024-04-05 08:44:26 +02:00
|
|
|
|
2024-03-15 17:28:39 +01:00
|
|
|
}
|
2023-12-28 16:18:49 +01:00
|
|
|
this.item = data;
|
2024-03-19 16:21:50 +01:00
|
|
|
|
2023-12-28 16:18:49 +01:00
|
|
|
this.selectedBlueprint = data?.blueprint;
|
|
|
|
this.isDeleted = data ? data.isActive === IsActive.Inactive : false;
|
2024-03-19 16:21:50 +01:00
|
|
|
|
2024-03-21 17:44:19 +01:00
|
|
|
if (data && data.id) {
|
2024-03-19 17:27:30 +01:00
|
|
|
const descriptionSectionPermissionResolverModel: DescriptionSectionPermissionResolver = {
|
|
|
|
dmpId: data.id,
|
|
|
|
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,
|
2024-03-20 11:35:55 +01:00
|
|
|
this.buildForm();
|
|
|
|
},
|
2024-03-19 17:27:30 +01:00
|
|
|
error => this.onCallbackError(error)
|
|
|
|
);
|
2024-03-20 11:35:55 +01:00
|
|
|
} else {
|
2024-03-19 17:27:30 +01:00
|
|
|
this.buildForm();
|
2024-03-19 16:21:50 +01:00
|
|
|
}
|
|
|
|
|
2024-03-21 16:36:55 +01:00
|
|
|
if (this.item && this.item.id != null) {
|
2024-03-21 12:06:59 +01:00
|
|
|
this.checkLock(this.item.id, LockTargetType.Dmp, 'DMP-EDITOR.LOCKED-DIALOG.TITLE', 'DMP-EDITOR.LOCKED-DIALOG.MESSAGE');
|
2024-03-20 11:35:55 +01:00
|
|
|
}
|
2023-12-28 16:18:49 +01:00
|
|
|
} catch (error) {
|
|
|
|
this.logger.error('Could not parse Dmp item: ' + data + error);
|
|
|
|
this.uiNotificationService.snackBarNotification(this.language.instant('COMMONS.ERRORS.DEFAULT'), SnackBarNotificationLevel.Error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
buildForm() {
|
2024-03-14 10:23:46 +01:00
|
|
|
const canedit = this.isNew ? this.authService.hasPermission(AppPermission.NewDmp) : this.item.authorizationFlags?.some(x => x === AppPermission.EditDmp) || this.authService.hasPermission(AppPermission.EditDmp);
|
2024-03-13 16:45:25 +01:00
|
|
|
this.formGroup = this.editorModel.buildForm(null, this.isDeleted || !canedit);
|
2023-12-28 16:18:49 +01:00
|
|
|
|
2024-01-25 19:55:42 +01:00
|
|
|
if (this.editorModel.status == DmpStatus.Finalized || this.isDeleted) {
|
2023-12-28 16:18:49 +01:00
|
|
|
this.formGroup.disable();
|
|
|
|
}
|
|
|
|
|
2024-04-05 10:11:31 +02:00
|
|
|
if (this.item != null && this.goToNextStep) {
|
2023-12-28 16:18:49 +01:00
|
|
|
this.nextStep();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
refreshData(): void {
|
|
|
|
this.getItem(this.editorModel.id, (data: Dmp) => this.prepareForm(data));
|
|
|
|
}
|
|
|
|
|
|
|
|
refreshOnNavigateToData(id?: Guid): void {
|
|
|
|
this.formGroup.markAsPristine();
|
|
|
|
|
2024-01-18 13:23:20 +01:00
|
|
|
if (this.isNew) {
|
|
|
|
let route = [];
|
2024-01-29 14:25:59 +01:00
|
|
|
route.push('/plans/overview/' + id);
|
2024-01-18 13:23:20 +01:00
|
|
|
this.router.navigate(route, { queryParams: { 'lookup': this.queryParamsService.serializeLookup(this.lookupParams), 'lv': ++this.lv }, replaceUrl: true, relativeTo: this.route });
|
2023-12-28 16:18:49 +01:00
|
|
|
} else {
|
2024-01-18 13:23:20 +01:00
|
|
|
this.refreshData();
|
2023-12-28 16:18:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
persistEntity(onSuccess?: (response) => void): void {
|
|
|
|
const formData = this.formService.getValue(this.formGroup.value) as DmpPersist;
|
|
|
|
|
2024-01-18 13:23:20 +01:00
|
|
|
//Transform to persist
|
|
|
|
//Transform descriptionTemplates
|
|
|
|
formData.descriptionTemplates = [];
|
2024-01-19 17:28:53 +01:00
|
|
|
for (const sectionId in (this.formGroup.get('descriptionTemplates') as UntypedFormGroup).controls) {
|
|
|
|
formData.descriptionTemplates.push(
|
|
|
|
...(this.formGroup.get('descriptionTemplates').get(sectionId).value as Guid[]).map(x => { return { sectionId: Guid.parse(sectionId), descriptionTemplateGroupId: x } })
|
|
|
|
);
|
2024-01-18 13:23:20 +01:00
|
|
|
}
|
|
|
|
|
2023-12-28 16:18:49 +01:00
|
|
|
this.dmpService.persist(formData)
|
|
|
|
.pipe(takeUntil(this._destroyed)).subscribe(
|
|
|
|
complete => onSuccess ? onSuccess(complete) : this.onCallbackSuccess(complete),
|
|
|
|
error => this.onCallbackError(error)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
formSubmit(): void {
|
2024-03-11 14:20:09 +01:00
|
|
|
this.formService.removeAllBackEndErrors(this.formGroup);
|
2023-12-28 16:18:49 +01:00
|
|
|
this.formService.touchAllFormFields(this.formGroup);
|
2024-03-11 14:20:09 +01:00
|
|
|
if (!this.isFormValid()) {
|
|
|
|
return;
|
|
|
|
}
|
2023-12-28 16:18:49 +01:00
|
|
|
|
|
|
|
this.persistEntity();
|
|
|
|
}
|
|
|
|
|
|
|
|
public delete() {
|
|
|
|
const value = this.formGroup.value;
|
|
|
|
if (value.id) {
|
|
|
|
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
|
|
|
maxWidth: '300px',
|
|
|
|
data: {
|
|
|
|
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'),
|
|
|
|
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
|
|
|
|
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL')
|
|
|
|
}
|
|
|
|
});
|
|
|
|
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
|
|
|
|
if (result) {
|
|
|
|
this.dmpService.delete(value.id).pipe(takeUntil(this._destroyed))
|
|
|
|
.subscribe(
|
|
|
|
complete => this.onCallbackSuccess(),
|
|
|
|
error => this.onCallbackError(error)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
clearErrorModel() {
|
|
|
|
this.editorModel.validationErrorModel.clear();
|
|
|
|
this.formService.validateAllFormFields(this.formGroup);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Steps
|
|
|
|
//
|
|
|
|
//
|
|
|
|
changeStep(index: number) {
|
|
|
|
this.step = index;
|
|
|
|
this.resetScroll();
|
|
|
|
}
|
|
|
|
|
|
|
|
nextStep() {
|
|
|
|
this.step = this.step < this.selectedBlueprint.definition.sections.length ? this.step + 1 : this.step;
|
|
|
|
this.resetScroll();
|
|
|
|
}
|
|
|
|
|
|
|
|
previousStep() {
|
|
|
|
this.step = this.step !== 1 ? this.step - 1 : this.step;
|
|
|
|
this.resetScroll();
|
|
|
|
}
|
|
|
|
|
|
|
|
private resetScroll() {
|
2024-03-20 11:35:55 +01:00
|
|
|
if (document.getElementById('editor-form') != null) document.getElementById('editor-form').scrollTop = 0;
|
2023-12-28 16:18:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Blueprint
|
|
|
|
//
|
|
|
|
//
|
|
|
|
selectBlueprint() {
|
|
|
|
this.dmpBlueprintService.getSingle(this.formGroup.get('blueprint').value, DmpEditorResolver.blueprintLookupFields()).pipe(takeUntil(this._destroyed)).subscribe(data => {
|
|
|
|
this.selectedBlueprint = data;
|
2024-01-18 13:23:20 +01:00
|
|
|
this.buildFormAfterBlueprintSelection();
|
2023-12-28 16:18:49 +01:00
|
|
|
this.nextStep();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-04-04 17:27:59 +02:00
|
|
|
selectDefaultBlueprint(): void {
|
2023-12-28 16:18:49 +01:00
|
|
|
this.dmpBlueprintService.getSingle(this.configurationService.defaultBlueprintId, DmpEditorResolver.blueprintLookupFields()).pipe(takeUntil(this._destroyed)).subscribe(data => {
|
|
|
|
this.selectedBlueprint = data;
|
|
|
|
this.formGroup.get('blueprint').setValue(this.selectedBlueprint.id);
|
2024-04-05 10:11:31 +02:00
|
|
|
|
|
|
|
const goToNextStep: boolean = this.formGroup.get('label').valid && this.formGroup.get('description').valid;
|
|
|
|
this.buildFormAfterBlueprintSelection(goToNextStep);
|
2023-12-28 16:18:49 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-04-05 10:11:31 +02:00
|
|
|
private buildFormAfterBlueprintSelection(goToNextStep: boolean = true) {
|
2024-01-18 13:23:20 +01:00
|
|
|
const dmp: Dmp = {
|
|
|
|
label: this.formGroup.get('label').value,
|
|
|
|
description: this.formGroup.get('description').value,
|
|
|
|
blueprint: this.selectedBlueprint,
|
2024-01-29 14:25:59 +01:00
|
|
|
status: DmpStatus.Draft
|
2024-01-18 13:23:20 +01:00
|
|
|
}
|
2024-04-05 10:11:31 +02:00
|
|
|
|
2024-01-18 13:23:20 +01:00
|
|
|
this.prepareForm(dmp);
|
2024-04-05 10:11:31 +02:00
|
|
|
this.goToNextStep = true; //reset
|
2024-01-18 13:23:20 +01:00
|
|
|
}
|
|
|
|
|
2024-01-31 10:27:36 +01:00
|
|
|
//
|
|
|
|
//
|
|
|
|
// Contacts
|
|
|
|
//
|
|
|
|
//
|
2024-03-26 09:34:51 +01:00
|
|
|
|
|
|
|
isContactSelected(contactId: number): boolean {
|
|
|
|
return this.hoveredContact === contactId;
|
|
|
|
}
|
|
|
|
|
|
|
|
onContactHover(contactIndex: number): void {
|
|
|
|
this.hoveredContact = contactIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
clearHoveredContact(): void {
|
|
|
|
this.hoveredContact = -1;
|
|
|
|
}
|
|
|
|
|
2024-01-31 10:27:36 +01:00
|
|
|
addContact(): void {
|
|
|
|
const contactArray = this.formGroup.get('properties').get('contacts') as FormArray;
|
|
|
|
(this.formGroup.get('properties').get('contacts') as FormArray).push(this.editorModel.createChildContact(contactArray.length));
|
|
|
|
}
|
|
|
|
|
|
|
|
removeContact(contactIndex: number): void {
|
|
|
|
(this.formGroup.get('properties').get('contacts') as FormArray).removeAt(contactIndex);
|
|
|
|
|
|
|
|
DmpEditorModel.reApplyPropertiesValidators(
|
|
|
|
{
|
|
|
|
formGroup: this.formGroup,
|
|
|
|
validationErrorModel: this.editorModel.validationErrorModel
|
|
|
|
}
|
|
|
|
);
|
|
|
|
this.formGroup.get('properties').get('contacts').markAsDirty();
|
|
|
|
}
|
|
|
|
|
|
|
|
dropContacts(event: CdkDragDrop<string[]>) {
|
2024-02-20 16:00:20 +01:00
|
|
|
const contactsFormArray = (this.formGroup.get('properties').get('contacts') as FormArray);
|
2024-01-31 10:27:36 +01:00
|
|
|
|
2024-02-20 16:00:20 +01:00
|
|
|
moveItemInArray(contactsFormArray.controls, event.previousIndex, event.currentIndex);
|
|
|
|
contactsFormArray.updateValueAndValidity();
|
2024-01-31 10:27:36 +01:00
|
|
|
|
|
|
|
DmpEditorModel.reApplyPropertiesValidators(
|
|
|
|
{
|
|
|
|
formGroup: this.formGroup,
|
|
|
|
validationErrorModel: this.editorModel.validationErrorModel
|
|
|
|
}
|
|
|
|
);
|
|
|
|
this.formGroup.get('properties').get('contacts').markAsDirty();
|
|
|
|
}
|
2023-12-28 16:18:49 +01:00
|
|
|
|
2024-02-20 16:00:20 +01:00
|
|
|
|
2023-12-28 16:18:49 +01:00
|
|
|
//
|
|
|
|
//
|
|
|
|
// Descriptions
|
|
|
|
//
|
|
|
|
//
|
|
|
|
public descriptionsInSection(sectionId: Guid) {
|
2024-04-05 08:44:26 +02:00
|
|
|
return this.item?.descriptions?.filter(x => x.isActive == IsActive.Active && x?.dmpDescriptionTemplate?.sectionId === sectionId && x.dmpDescriptionTemplate.isActive == IsActive.Active) || [];
|
2023-12-28 16:18:49 +01:00
|
|
|
}
|
|
|
|
|
2024-03-20 11:35:55 +01:00
|
|
|
editDescription(id: string, isNew: boolean) {
|
|
|
|
if (!isNew) {
|
|
|
|
this.router.navigate(['/descriptions', 'edit', id]);
|
2023-12-28 16:18:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 11:35:55 +01:00
|
|
|
public removeDescription(descriptionId: Guid) {
|
|
|
|
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
|
|
|
maxWidth: '300px',
|
|
|
|
restoreFocus: false,
|
|
|
|
data: {
|
|
|
|
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'),
|
|
|
|
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.DELETE'),
|
|
|
|
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
|
|
|
|
isDeleteConfirmation: true
|
|
|
|
}
|
|
|
|
});
|
|
|
|
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
|
|
|
|
if (result) {
|
|
|
|
if (descriptionId) {
|
|
|
|
this.descriptionService.delete(descriptionId)
|
|
|
|
.pipe(takeUntil(this._destroyed))
|
|
|
|
.subscribe(
|
|
|
|
complete => {
|
|
|
|
this.onCallbackSuccess();
|
|
|
|
},
|
|
|
|
error => this.onCallbackError(error)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
// this.formGroup.get('datasets')['controls'].splice(index, 1);
|
|
|
|
this.step = 0;
|
|
|
|
}
|
|
|
|
});
|
2023-12-28 16:18:49 +01:00
|
|
|
}
|
|
|
|
|
2024-04-03 16:50:47 +02:00
|
|
|
canAddDescription(section: DmpBlueprintDefinitionSection ): boolean{
|
|
|
|
if(section.hasTemplates){
|
|
|
|
if (section.descriptionTemplates?.length > 0){
|
|
|
|
const descriptions = this.descriptionsInSection(section.id)
|
|
|
|
|
2024-04-05 08:44:26 +02:00
|
|
|
if (this.item.dmpDescriptionTemplates.filter(x => x.sectionId == section.id).length > descriptions.map(x => x.dmpDescriptionTemplate).length){
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-04-03 16:50:47 +02:00
|
|
|
let multiplicityValidResults :boolean[] = [];
|
|
|
|
section.descriptionTemplates.forEach(sectionDescriptionTemplate => {
|
|
|
|
if (sectionDescriptionTemplate.maxMultiplicity != null){
|
|
|
|
const count = descriptions.filter(x => x.dmpDescriptionTemplate.descriptionTemplateGroupId == sectionDescriptionTemplate.descriptionTemplateGroupId).length || 0;
|
|
|
|
if (count >= sectionDescriptionTemplate.maxMultiplicity) multiplicityValidResults.push(false);
|
|
|
|
else multiplicityValidResults.push(true);
|
|
|
|
}else{
|
|
|
|
multiplicityValidResults.push(true);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
if(multiplicityValidResults.includes(true)) return true
|
|
|
|
else return false;
|
|
|
|
}else{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-15 17:47:34 +01:00
|
|
|
//
|
|
|
|
//
|
|
|
|
// Description Template
|
|
|
|
//
|
|
|
|
//
|
|
|
|
|
2024-03-29 16:37:08 +01:00
|
|
|
onPreviewDescriptionTemplate(event, sectionId: Guid) {
|
|
|
|
const dialogRef = this.dialog.open(DescriptionTemplatePreviewDialogComponent, {
|
|
|
|
width: '590px',
|
|
|
|
minHeight: '200px',
|
|
|
|
restoreFocus: false,
|
|
|
|
data: {
|
|
|
|
descriptionTemplateId: event.id
|
|
|
|
},
|
|
|
|
panelClass: 'custom-modalbox'
|
|
|
|
});
|
|
|
|
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
|
|
|
|
if (result) {
|
|
|
|
// this.addProfile(event, sectionIndex);
|
|
|
|
// this.profilesAutoCompleteConfiguration = {
|
|
|
|
// filterFn: this.filterProfiles.bind(this),
|
|
|
|
// initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))),
|
|
|
|
// displayFn: (item) => item['label'],
|
|
|
|
// titleFn: (item) => item['label'],
|
|
|
|
// subtitleFn: (item) => item['description'],
|
|
|
|
// popupItemActionIcon: 'visibility'
|
|
|
|
// };
|
|
|
|
}
|
|
|
|
});
|
2024-01-15 17:47:34 +01:00
|
|
|
}
|
|
|
|
|
2023-12-28 16:18:49 +01:00
|
|
|
//
|
|
|
|
//
|
|
|
|
// Misc
|
|
|
|
//
|
|
|
|
//
|
|
|
|
public isDirty(): boolean {
|
|
|
|
return this.formGroup && this.formGroup.dirty; //&& this.hasChanges;
|
|
|
|
}
|
|
|
|
|
2024-01-15 17:47:34 +01:00
|
|
|
getLanguageInfos(): LanguageInfo[] {
|
|
|
|
return this.languageInfoService.getLanguageInfoValues();
|
|
|
|
}
|
2023-12-28 16:18:49 +01:00
|
|
|
}
|