Merge branch 'dmp-refactoring' of code-repo.d4science.org:MaDgiK-CITE/argos into dmp-refactoring

This commit is contained in:
Efstratios Giannopoulos 2024-04-22 10:00:31 +03:00
commit ada4dcfe99
19 changed files with 287 additions and 15 deletions

View File

@ -40,4 +40,10 @@
color: #FFF;
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,7 +44,7 @@ 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 { FileTransformerEntityType } from '@app/core/common/enum/file-transformer-entity-type';
@ -69,6 +69,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
@ -207,8 +208,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;
@ -850,6 +851,10 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
// this.formChanged();
}
});
this.checkPagesForErrors();
// // const labelSubscription =
// this.formGroup.get('label').valueChanges
// .pipe(takeUntil(this._destroyed))
@ -905,6 +910,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";
@ -691,3 +692,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

View File

@ -2,6 +2,7 @@
"label": "Administration",
"position": 4,
"link": {
"type": "generated-index"
"type": "doc",
"id": "index"
}
}

View File

@ -2,6 +2,7 @@
"label": "Blueprints",
"position": 2,
"link": {
"type": "generated-index"
"type": "doc",
"id": "index"
}
}

View File

@ -0,0 +1,5 @@
# Blueprints
import DocCardList from '@theme/DocCardList';
<DocCardList />

View File

@ -0,0 +1,9 @@
# Administration
There are a lot of tools developed that can help administrators better manage a lot of aspects of the application or get a better idea about the usage of the platform.
These tools will be described in this section.
import DocCardList from '@theme/DocCardList';
<DocCardList />

View File

@ -2,4 +2,11 @@
sidebar_position: 1
---
# Introduction
# Introduction
There are a lot of views in the application available only for users that are given elevated privileges. In the pages that follow we will discover all the configuration options available in these views for an administrator, with the most important being the following:
- **Users**: Being able to control the users of the platform.
- **Tenants**: Being able to control the tenants of the platform. Think of tenants as different organisations that can use the application independently at the same time without the need of different deployments.
- **Notification Templates**: Being able to modify the structure of notifications sent to users based on different events.
- **Languages**: Being able to add support for more languages or modify existing ones.

View File

@ -2,6 +2,7 @@
"label": "Templates",
"position": 4,
"link": {
"type": "generated-index"
"type": "doc",
"id": "index"
}
}

View File

@ -0,0 +1,5 @@
# Templates
import DocCardList from '@theme/DocCardList';
<DocCardList />

View File

@ -2,4 +2,36 @@
sidebar_position: 7
---
# Tenants
# Tenants
In this page, there is a listing where you can view details about all the available tenants.
The information displayed by default is: the `display name` of the tenants, the `status`, the `identification code` and timestamps for the `creation` and `updates` of the records. At the top right corner of the listing you can also select which columns to display.
:::tip
For tenants, all the columns are visible by default.
:::
You can also create new or edit / remove tenants by clicking to the `Create Tenant` button at the top right of the page or to the three dots at the last column, respectively.
## Authorization
Only users that have the **Admin** role can access this page.
## Pagination
Not all the records are being displayed at once. By default, there is a pagination of 10 records applied to them.
You can control how many records are being displayed at any time, by adjusting the `items per page` control at the bottom left corner of the table.
## Filtering
There is a filtering option available for tenants.
- **Is Active**: By toggling this control you can view only the active or only the disabled tenants.<br/>*By default, this option is set to true.*
In order for the filters to apply, you have to click the `Apply filters` button.
You can also clear any filters already applied, by pressing the `clear all filters` option, located at the top of the popup.

View File

@ -2,4 +2,37 @@
sidebar_position: 6
---
# Users
# Users
In this page, there is a listing where you can view details about all the registered users.
The information displayed by default is: the `name` of the users, the `status` of their accounts and timestamps for the `creation` and `updates` of the records. At the top right corner of the listing you can also select which columns to display.
:::tip
For users, there is a column for `emails`, hidden by default.
:::
You can also assign new or remove assigned roles from users by clicking to the icon next to the roles column. When you click it, a multiselect dropdown is made available in the roles column.
## Authorization
Only users that have the **Admin** role can access this page.
## Pagination
Not all the records are being displayed at once. By default, there is a pagination of 10 records applied to them.
You can control how many records are being displayed at any time, by adjusting the `items per page` control at the bottom left corner of the table.
## Filtering
There are some filtering options available for users.
- **Is Active**: By toggling this control you can view only the active or only the disabled users.<br/>*By default, this option is set to true.*
- **Roles**: You can filter users by their assigned roles. You can select one or more roles.<br/>*By default, no role is selected.*
In order for the filters to apply, you have to click the `Apply filters` button.
You can also clear any filters already applied, by pressing the `clear all filters` option, located at the top of the popup.

View File

@ -93,6 +93,22 @@ const config: Config = {
label: 'Getting Started',
to: '/docs/category/getting-started',
},
{
label: 'Application',
to: '/docs/category/application',
},
{
label: 'Supplementary Services',
to: '/docs/category/supplementary-services',
},
{
label: 'Administration',
to: '/docs/documentation/administration',
},
{
label: 'For Developers',
to: '/docs/category/for-developers',
},
],
},
{