table of contents error indicator

This commit is contained in:
Sofia Papacharalampous 2024-04-19 18:37:06 +03:00
parent 3ec12fdf59
commit 79817e63e0
9 changed files with 175 additions and 10 deletions

View File

@ -41,3 +41,9 @@
border: 0px;
}
}
::ng-deep .mdc-form-field {
label {
margin: 0;
}
}

View File

@ -93,7 +93,7 @@
<div (click)="table0fContents.onToCentrySelected()" *ngIf="descriptionInfoValid()" class="main-info" [ngClass]="{'active': this.step === 0}">0. {{'DESCRIPTION-EDITOR.TOC.MAIN-INFO' | translate}} (<mat-icon class="done-icon">done</mat-icon>)</div>
<div class="row toc-pane-container" #boundary>
<div #spacer></div>
<app-table-of-contents [visibilityRulesService]="visibilityRulesService" [selectedFieldsetId]="fieldsetIdWithFocus" #table0fContents [showErrors]="showtocentriesErrors" [TOCENTRY_ID_PREFIX]="TOCENTRY_ID_PREFIX" [hasFocus]="step > 0" [propertiesFormGroup]="formGroup.get('properties')" [descriptionTemplate]="item.descriptionTemplate" *ngIf="formGroup" [links]="links" [boundary]="boundary" [spacer]="spacer" [isActive]="step !== 0" stickyThing (stepFound)="onStepFound($event)" (currentLinks)="getLinks($event)" (entrySelected)="changeStep($event.entry, $event.execute)"></app-table-of-contents>
<app-table-of-contents [visibilityRulesService]="visibilityRulesService" [selectedFieldsetId]="fieldsetIdWithFocus" #table0fContents [showErrors]="showtocentriesErrors" [TOCENTRY_ID_PREFIX]="TOCENTRY_ID_PREFIX" [hasFocus]="step > 0" [formGroup]="formGroup.get('properties')" [descriptionTemplate]="item.descriptionTemplate" *ngIf="formGroup" [links]="links" [boundary]="boundary" [spacer]="spacer" [isActive]="step !== 0" stickyThing (stepFound)="onStepFound($event)" (currentLinks)="getLinks($event)" (entrySelected)="changeStep($event.entry, $event.execute)" [pageToFieldSetMap]="pageToFieldSetMap"></app-table-of-contents>
</div>
</div>
</div>

View File

@ -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<DescriptionEditorMode
@ViewChild('table0fContents') table0fContents: TableOfContentsComponent;
step: number = 0;
pageToFieldSetMap: Map<string, DescriptionFieldIndicator[]> = new Map<string, DescriptionFieldIndicator[]>();
constructor(
// BaseFormEditor injected dependencies
@ -205,8 +209,8 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
const sectionId = this.item.dmpDescriptionTemplate.sectionId;
result.dmpDescriptionTemplate = this.item.dmp.dmpDescriptionTemplates.find(x => 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<DescriptionEditorMode
// this.formChanged();
}
});
this.checkPagesForErrors();
// // const labelSubscription =
// this.formGroup.get('label').valueChanges
// .pipe(takeUntil(this._destroyed))
@ -903,6 +911,38 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
}
}
checkPagesForErrors(): void {
this.pageToFieldSetMap = this.mapPageToFieldSet(this.item.descriptionTemplate);
}
mapPageToFieldSet(descriptionTemplate: DescriptionTemplate): Map<string, DescriptionFieldIndicator[]> {
const pageToFieldSetMap = new Map<string, DescriptionFieldIndicator[]>();
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);

View File

@ -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";
@ -672,3 +673,59 @@ export class DescriptionReferenceEditorModel implements DescriptionReferencePers
});
}
}
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;
}
}
}

View File

@ -39,6 +39,9 @@
[showErrors]="showErrors"
[hiddenEntries]="hiddenEntries"
[visibilityRulesService]="visibilityRulesService"
[propertiesFormGroup]="propertiesFormGroup"
[parentId]="entry.id"
[parentMap]="updatedMap"
>
</table-of-contents-internal>

View File

@ -22,8 +22,9 @@
background-color: #ececec;
border-radius: 6px;
}
.selected {
color: #212121 !important;
color: #212121;
font-weight: 700 !important;
opacity: 1 !important;
}

View File

@ -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<TableOfContentsInternal>;
@Input() parentId: string;
@Input() parentMap: Map<string, DescriptionFieldIndicator[]> = new Map<string, DescriptionFieldIndicator[]>();
@Input() updatedMap: Map<string, DescriptionFieldIndicator[]> = new Map<string, DescriptionFieldIndicator[]>();
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<string, DescriptionFieldIndicator[]>): Map<string, DescriptionFieldIndicator[]> {
if (this.parentId == null) return parentMap;
let updatedMap = new Map<string, DescriptionFieldIndicator[]>();
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;
}

View File

@ -15,7 +15,8 @@
[selected]="tocentrySelected"
[hiddenEntries]="hiddenEntries"
[visibilityRulesService]="visibilityRulesService"
[propertiesFormGroup]="propertiesFormGroup"
[propertiesFormGroup]="formGroup"
[parentMap]="pageToFieldSetMap"
>
</table-of-contents-internal>

View File

@ -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<string, DescriptionFieldIndicator[]>;
constructor(
@Inject(DOCUMENT) private _document: Document,
// public visibilityRulesService: VisibilityRulesService