diff --git a/dmp-frontend/src/app/ui/admin/prefilling-source/editor/prefilling-source-editor.component.scss b/dmp-frontend/src/app/ui/admin/prefilling-source/editor/prefilling-source-editor.component.scss index df9e3a45f..74d11d8d1 100644 --- a/dmp-frontend/src/app/ui/admin/prefilling-source/editor/prefilling-source-editor.component.scss +++ b/dmp-frontend/src/app/ui/admin/prefilling-source/editor/prefilling-source-editor.component.scss @@ -40,4 +40,10 @@ color: #FFF; border: 0px; } -} \ No newline at end of file +} + +::ng-deep .mdc-form-field { + label { + margin: 0; + } +} diff --git a/dmp-frontend/src/app/ui/description/editor/description-editor.component.html b/dmp-frontend/src/app/ui/description/editor/description-editor.component.html index f6b272edd..0a57f409e 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-editor.component.html +++ b/dmp-frontend/src/app/ui/description/editor/description-editor.component.html @@ -93,7 +93,7 @@
0. {{'DESCRIPTION-EDITOR.TOC.MAIN-INFO' | translate}} (done)
- +
diff --git a/dmp-frontend/src/app/ui/description/editor/description-editor.component.ts b/dmp-frontend/src/app/ui/description/editor/description-editor.component.ts index 8b2e8b501..00270acaa 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-editor.component.ts +++ b/dmp-frontend/src/app/ui/description/editor/description-editor.component.ts @@ -6,7 +6,7 @@ import { DescriptionStatus } from '@app/core/common/enum/description-status'; import { DmpStatus } from '@app/core/common/enum/dmp-status'; import { IsActive } from '@app/core/common/enum/is-active.enum'; import { AppPermission } from '@app/core/common/enum/permission.enum'; -import { Description, DescriptionPersist, DescriptionSectionPermissionResolver, DescriptionStatusPersist } from '@app/core/model/description/description'; +import { Description, DescriptionPersist, DescriptionPropertyDefinitionFieldSet, DescriptionSectionPermissionResolver, DescriptionStatusPersist } from '@app/core/model/description/description'; import { AuthService } from '@app/core/services/auth/auth.service'; import { DescriptionTemplateService } from '@app/core/services/description-template/description-template.service'; import { DescriptionService } from '@app/core/services/description/description.service'; @@ -32,7 +32,7 @@ import { FilterService } from '@common/modules/text-filter/filter-service'; import { Guid } from '@common/types/guid'; import { TranslateService } from '@ngx-translate/core'; import { map, takeUntil } from 'rxjs/operators'; -import { DescriptionEditorModel, DescriptionPropertyDefinitionEditorModel } from './description-editor.model'; +import { DescriptionEditorModel, DescriptionFieldIndicator, DescriptionPropertyDefinitionEditorModel } from './description-editor.model'; import { DescriptionEditorResolver } from './description-editor.resolver'; import { DescriptionEditorService } from './description-editor.service'; import { PrefillDescriptionDialogComponent } from './prefill-description/prefill-description.component'; @@ -44,8 +44,11 @@ import { ConfigurationService } from '@app/core/services/configuration/configura import { LockTargetType } from '@app/core/common/enum/lock-target-type'; import { FileTransformerService } from '@app/core/services/file-transformer/file-transformer.service'; import { DmpBlueprintDefinitionSection } from '@app/core/model/dmp-blueprint/dmp-blueprint'; -import { DescriptionTemplate } from '@app/core/model/description-template/description-template'; +import { DescriptionTemplate, DescriptionTemplateField, DescriptionTemplateFieldSet, DescriptionTemplatePage, DescriptionTemplateSection } from '@app/core/model/description-template/description-template'; import { DmpDescriptionTemplate } from '@app/core/model/dmp/dmp'; +import { BehaviorSubject } from 'rxjs'; +import { UUID } from 'crypto'; +import { AbstractControl } from '@angular/forms'; @Component({ selector: 'app-description-editor-component', @@ -67,6 +70,7 @@ export class DescriptionEditorComponent extends BaseEditor = new Map(); constructor( // BaseFormEditor injected dependencies @@ -205,8 +209,8 @@ export class DescriptionEditorComponent extends BaseEditor x.sectionId == sectionId && x.descriptionTemplateGroupId == result.descriptionTemplate.groupId); - this.prepareForm(result); + // this.descriptionModel = this.descriptionModel.fromModel(result); // this.descriptionModel.dmp = data; // this.descriptionModel.dmpSectionIndex = this.dmpSectionIndex; @@ -848,6 +852,10 @@ export class DescriptionEditorComponent extends BaseEditor { + const pageToFieldSetMap = new Map(); + + descriptionTemplate.definition.pages?.forEach((page: DescriptionTemplatePage) => { + page.sections?.forEach((section: DescriptionTemplateSection) => { + const fieldsets = this.getFieldsetsFromSection(section); + const value = fieldsets?.flatMap((fieldset: DescriptionTemplateFieldSet) => + fieldset.fields?.flatMap((field: DescriptionTemplateField) => + new DescriptionFieldIndicator(page.id, section.id, fieldset.id, field.id, field.data.fieldType, field.data.multipleSelect) + // 'properties.fieldSets.' + fieldset.id + '.items.0.fields.' + field.id// + '.textValue' + )); + pageToFieldSetMap.set(page.id, + value + ); + }); + }); + + return pageToFieldSetMap; + } + + getFieldsetsFromSection(section: DescriptionTemplateSection): DescriptionTemplateFieldSet[] { + if (section.sections) { + return section.sections.flatMap((subsection: DescriptionTemplateSection) => this.getFieldsetsFromSection(subsection)); + } + + else return section.fieldSets; + } + // // this._listenersSubscription.add(dmpSubscription); // // this._listenersSubscription.add(profileSubscription); // // this._listenersSubscription.add(labelSubscription); diff --git a/dmp-frontend/src/app/ui/description/editor/description-editor.model.ts b/dmp-frontend/src/app/ui/description/editor/description-editor.model.ts index 4f70e929b..cf75a00f5 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-editor.model.ts +++ b/dmp-frontend/src/app/ui/description/editor/description-editor.model.ts @@ -1,5 +1,6 @@ import { FormControl, UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms"; import { DescriptionStatus } from "@app/core/common/enum/description-status"; +import { DescriptionTemplateFieldType } from "@app/core/common/enum/description-template-field-type"; import { IsActive } from "@app/core/common/enum/is-active.enum"; import { DescriptionTemplate, DescriptionTemplateField, DescriptionTemplateFieldSet, DescriptionTemplateSection } from "@app/core/model/description-template/description-template"; import { Description, DescriptionExternalIdentifier, DescriptionExternalIdentifierPersist, DescriptionField, DescriptionFieldPersist, DescriptionPersist, DescriptionPropertyDefinition, DescriptionPropertyDefinitionFieldSet, DescriptionPropertyDefinitionFieldSetItem, DescriptionPropertyDefinitionFieldSetItemPersist, DescriptionPropertyDefinitionFieldSetPersist, DescriptionPropertyDefinitionPersist, DescriptionReference, DescriptionReferencePersist } from "@app/core/model/description/description"; @@ -671,4 +672,60 @@ export class DescriptionReferenceEditorModel implements DescriptionReferencePers control?.addValidators(context.getValidation(keyField).validators); }); } -} \ No newline at end of file +} + +export class DescriptionFieldIndicator { + pageId: string; + sectionId: string; + fieldSetId: string; + fieldId: string; + type: string; + + constructor(pageId: string, sectionId: string, fieldSetId: string, fieldId: string, type: DescriptionTemplateFieldType, multipleSelect: boolean = false) { + this.pageId = pageId; + this.sectionId = sectionId; + this.fieldSetId = fieldSetId; + this.fieldId = fieldId; + + switch (type) { + case DescriptionTemplateFieldType.FREE_TEXT: + case DescriptionTemplateFieldType.BOOLEAN_DECISION: + case DescriptionTemplateFieldType.CHECK_BOX: + case DescriptionTemplateFieldType.RADIO_BOX: + case DescriptionTemplateFieldType.TEXT_AREA: + case DescriptionTemplateFieldType.UPLOAD: + case DescriptionTemplateFieldType.RICH_TEXT_AREA: + this.type = "textValue"; + break; + case DescriptionTemplateFieldType.DATASET_IDENTIFIER: + case DescriptionTemplateFieldType.VALIDATION: + this.type = "externalIdentifier"; + break; + case DescriptionTemplateFieldType.DATE_PICKER: + this.type = "dateValue"; + break; + case DescriptionTemplateFieldType.EXTERNAL_DATASETS: + this.type = ""; + break; + case DescriptionTemplateFieldType.INTERNAL_ENTRIES_DESCRIPTIONS: + if (multipleSelect) this.type = "textListValue"; + else this.type = "textValue" + break; + case DescriptionTemplateFieldType.INTERNAL_ENTRIES_DMPS: + if (multipleSelect) this.type = "textListValue"; + else this.type = "textValue"; + break; + case DescriptionTemplateFieldType.REFERENCE_TYPES: + if (multipleSelect) this.type = "references"; + else this.type = "reference"; + break; + case DescriptionTemplateFieldType.SELECT: + if (multipleSelect) this.type = "textListValue"; + else this.type = "textValue"; + break; + case DescriptionTemplateFieldType.TAGS: + this.type = "textListValue"; + break; + } + } +} diff --git a/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents-internal/table-of-contents-internal.html b/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents-internal/table-of-contents-internal.html index 8653b61f4..d5a3845c7 100644 --- a/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents-internal/table-of-contents-internal.html +++ b/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents-internal/table-of-contents-internal.html @@ -39,6 +39,9 @@ [showErrors]="showErrors" [hiddenEntries]="hiddenEntries" [visibilityRulesService]="visibilityRulesService" + [propertiesFormGroup]="propertiesFormGroup" + [parentId]="entry.id" + [parentMap]="updatedMap" > diff --git a/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents-internal/table-of-contents-internal.scss b/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents-internal/table-of-contents-internal.scss index 91152786d..c9978f6a4 100644 --- a/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents-internal/table-of-contents-internal.scss +++ b/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents-internal/table-of-contents-internal.scss @@ -22,8 +22,9 @@ background-color: #ececec; border-radius: 6px; } + .selected { - color: #212121 !important; + color: #212121; font-weight: 700 !important; opacity: 1 !important; } diff --git a/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents-internal/table-of-contents-internal.ts b/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents-internal/table-of-contents-internal.ts index 5547ecfa2..4bc9f3c62 100644 --- a/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents-internal/table-of-contents-internal.ts +++ b/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents-internal/table-of-contents-internal.ts @@ -4,6 +4,7 @@ import { VisibilityRulesService } from '@app/ui/description/editor/description-f import { Guid } from '@common/types/guid'; import { ToCEntry } from '../models/toc-entry'; import { ToCEntryType } from '../models/toc-entry-type.enum'; +import { DescriptionFieldIndicator } from '../../description-editor.model'; @Component({ selector: 'table-of-contents-internal', @@ -26,6 +27,10 @@ export class TableOfContentsInternal implements OnInit { @Input() visibilityRulesService: VisibilityRulesService; @ViewChildren(TableOfContentsInternal) internalTables: QueryList; + @Input() parentId: string; + @Input() parentMap: Map = new Map(); + @Input() updatedMap: Map = new Map(); + constructor() { } ngOnInit(): void { @@ -42,6 +47,11 @@ export class TableOfContentsInternal implements OnInit { } } } + + if (this.parentMap) { + this.updatedMap = this.updateMap(this.tocentries, this.parentMap); + console.log(this.updatedMap); + } } } @@ -64,6 +74,47 @@ export class TableOfContentsInternal implements OnInit { // } } + updateMap(entries: ToCEntry[], parentMap:Map): Map { + if (this.parentId == null) return parentMap; + + let updatedMap = new Map(); + + parentMap.forEach((fields: DescriptionFieldIndicator[], parentId: string) => { + if (this.parentId === parentId) { + for (let entry of entries) { + let entryFields = fields.filter((field: DescriptionFieldIndicator) => field.sectionId === entry.id || field.fieldSetId === entry.id || field.fieldId === entry.id ) + + updatedMap.set(entry.id, entryFields); + } + } + }); + + return updatedMap; + } + + hasErrors(entryId: string): boolean { + if (this.updatedMap.size == 0) return true; + + const fields: DescriptionFieldIndicator[] = this.updatedMap.get(entryId); + + for (let field of fields) { + let formFieldName: string = `fieldSets.${field.fieldSetId}.items.0.fields.${field.fieldId}.${field.type}`; + if (this.isFormFieldValid(formFieldName) === false) { + return true; + } + } + + return false; + } + + isFormFieldValid(formFildName: string):boolean { + if (this.propertiesFormGroup?.get(formFildName) == null) return true; + + if (this.propertiesFormGroup.get(formFildName).touched === false) return true; + + return this.propertiesFormGroup.get(formFildName).valid; + } + toggleExpand(index) { this.expandChildren[index] = !this.expandChildren[index]; // console.log(this.expandChildren); @@ -113,6 +164,9 @@ export class TableOfContentsInternal implements OnInit { myClass['section'] = true; } + if(this.hasErrors(entry.id)) { + myClass['text-danger'] = true; + } return myClass; } diff --git a/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents.component.html b/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents.component.html index 2fb7f2929..62de7a1cb 100644 --- a/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents.component.html +++ b/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents.component.html @@ -15,7 +15,8 @@ [selected]="tocentrySelected" [hiddenEntries]="hiddenEntries" [visibilityRulesService]="visibilityRulesService" - [propertiesFormGroup]="propertiesFormGroup" + [propertiesFormGroup]="formGroup" + [parentMap]="pageToFieldSetMap" > diff --git a/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents.component.ts b/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents.component.ts index adbcae0ae..a88095d80 100644 --- a/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents.component.ts +++ b/dmp-frontend/src/app/ui/description/editor/table-of-contents/table-of-contents.component.ts @@ -9,6 +9,7 @@ import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators'; import { ToCEntry } from './models/toc-entry'; import { ToCEntryType } from './models/toc-entry-type.enum'; import { TableOfContentsInternal } from './table-of-contents-internal/table-of-contents-internal'; +import { DescriptionFieldIndicator } from '../description-editor.model'; export interface Link { /* id of the section*/ @@ -65,12 +66,14 @@ export class TableOfContentsComponent extends BaseComponent implements OnInit, O this._tocentrySelected = value; } - @Input() propertiesFormGroup: UntypedFormGroup; + @Input() formGroup: UntypedFormGroup; @Input() descriptionTemplate: DescriptionTemplate; @Input() hasFocus: boolean = false; @Input() visibilityRulesService: VisibilityRulesService; show: boolean = false; + @Input() pageToFieldSetMap: Map; + constructor( @Inject(DOCUMENT) private _document: Document, // public visibilityRulesService: VisibilityRulesService