Merge branch 'AdminTemplateRedesign' into WizardDescriptionRefactor
|
@ -64,12 +64,31 @@ export class AppComponent implements OnInit, AfterViewInit {
|
||||||
ngAfterViewInit(): void {
|
ngAfterViewInit(): void {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.sideNavSubscription = this.sidenavService.status().subscribe(isopen=>{
|
this.sideNavSubscription = this.sidenavService.status().subscribe(isopen=>{
|
||||||
|
const hamburger = document.getElementById('hamburger');
|
||||||
if(isopen){
|
if(isopen){
|
||||||
//update value of hamburfer
|
//update value of hamburfer
|
||||||
document.getElementById('hamburger').classList.add('change');
|
if(!hamburger){//try later
|
||||||
|
setTimeout(() => {
|
||||||
|
const hamburger = document.getElementById('hamburger');
|
||||||
|
if(hamburger){
|
||||||
|
hamburger.classList.add('change');
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
}else{
|
||||||
|
hamburger.classList.add('change');
|
||||||
|
}
|
||||||
this.sidenav.open()
|
this.sidenav.open()
|
||||||
}else{
|
}else{//closed
|
||||||
document.getElementById('hamburger').classList.remove('change');
|
if(!hamburger){//try later
|
||||||
|
setTimeout(() => {
|
||||||
|
const hamburger = document.getElementById('hamburger');
|
||||||
|
if(hamburger){
|
||||||
|
hamburger.classList.remove('change');
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
}else{
|
||||||
|
hamburger.classList.remove('change');
|
||||||
|
}
|
||||||
this.sidenav.close();
|
this.sidenav.close();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -388,7 +388,10 @@ export class GuidedTourComponent implements AfterViewInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
const scrollAdjustment = this.currentTourStep.scrollAdjustment ? this.currentTourStep.scrollAdjustment : 0;
|
const scrollAdjustment = this.currentTourStep.scrollAdjustment ? this.currentTourStep.scrollAdjustment : 0;
|
||||||
const tourStepHeight = typeof this.tourStep.nativeElement.getBoundingClientRect === 'function' ? this.tourStep.nativeElement.getBoundingClientRect().height : 0;
|
let tourStepHeight = 0;
|
||||||
|
if (this.tourStep != null && this.tourStep.nativeElement != null && typeof this.tourStep.nativeElement.getBoundingClientRect === 'function') {
|
||||||
|
tourStepHeight = this.tourStep.nativeElement.getBoundingClientRect().height;
|
||||||
|
}
|
||||||
const elementHeight = this.selectedElementRect.height + scrollAdjustment + tourStepHeight;
|
const elementHeight = this.selectedElementRect.height + scrollAdjustment + tourStepHeight;
|
||||||
|
|
||||||
if ((this.windowRef.nativeWindow.innerHeight - this.topOfPageAdjustment) < elementHeight) {
|
if ((this.windowRef.nativeWindow.innerHeight - this.topOfPageAdjustment) < elementHeight) {
|
||||||
|
|
|
@ -67,12 +67,12 @@
|
||||||
</div>
|
</div>
|
||||||
</div> -->
|
</div> -->
|
||||||
<mat-form-field appearance="none" class="numbering-label" [ngStyle]="calculateLabelWidth(numbering)">
|
<mat-form-field appearance="none" class="numbering-label" [ngStyle]="calculateLabelWidth(numbering)">
|
||||||
<input matInput type="text" [value]="numbering" disabled>
|
<input [ngClass]="{'text-danger':form.get('title').invalid &&form.get('title').touched}" matInput type="text" [value]="numbering" disabled>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<!-- [appearance]="titleControl.focused? 'legacy':'none'" floatLabel="never" -->
|
<!-- [appearance]="titleControl.focused? 'legacy':'none'" floatLabel="never" -->
|
||||||
<mat-form-field class="col field-title" [appearance]="'none'">
|
<mat-form-field class="col field-title" [appearance]="'none'" floatLabel="never">
|
||||||
<input matInput type="text" placeholder="Title" #titleControl="matInput"
|
<input matInput type="text" placeholder="Title" #titleControl="matInput"
|
||||||
[formControl]="this.form.get('title')">
|
[formControl]="this.form.get('title')" required>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -145,6 +145,7 @@
|
||||||
[form]="form.get('fields').get(''+i)" [showOrdinal]="false"
|
[form]="form.get('fields').get(''+i)" [showOrdinal]="false"
|
||||||
[indexPath]="indexPath + 'f' + i" [viewOnly]="viewOnly"
|
[indexPath]="indexPath + 'f' + i" [viewOnly]="viewOnly"
|
||||||
[expandView]="hasFocus"
|
[expandView]="hasFocus"
|
||||||
|
[canBeDeleted]="form.get('fields')['controls'].length !=1"
|
||||||
(delete)="deleteField(i)">
|
(delete)="deleteField(i)">
|
||||||
</app-dataset-profile-editor-field-component>
|
</app-dataset-profile-editor-field-component>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -32,6 +32,7 @@ import { CurrencyDataEditorModel } from '../../../admin/field-data/currency-data
|
||||||
import { ValidationDataEditorModel } from '../../../admin/field-data/validation-data-editor-models';
|
import { ValidationDataEditorModel } from '../../../admin/field-data/validation-data-editor-models';
|
||||||
import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service';
|
import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service';
|
||||||
import { OrganizationsDataEditorModel } from '../../../admin/field-data/organizations-data-editor-models';
|
import { OrganizationsDataEditorModel } from '../../../admin/field-data/organizations-data-editor-models';
|
||||||
|
import { EditorCustomValidators } from '../../custom-validators/editor-custom-validators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-dataset-profile-editor-composite-field-component',
|
selector: 'app-dataset-profile-editor-composite-field-component',
|
||||||
|
@ -59,6 +60,7 @@ export class DatasetProfileEditorCompositeFieldComponent implements OnInit, OnCh
|
||||||
viewStyleEnum = DatasetProfileFieldViewStyle;
|
viewStyleEnum = DatasetProfileFieldViewStyle;
|
||||||
|
|
||||||
viewTypeEnum = ViewStyleType;
|
viewTypeEnum = ViewStyleType;
|
||||||
|
private myCustomValidators:EditorCustomValidators = new EditorCustomValidators();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
|
@ -358,15 +360,15 @@ export class DatasetProfileEditorCompositeFieldComponent implements OnInit, OnCh
|
||||||
fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.ComboBox)
|
fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.ComboBox)
|
||||||
fieldForm.addControl('data', new WordListFieldDataEditorModel().buildForm());
|
fieldForm.addControl('data', new WordListFieldDataEditorModel().buildForm());
|
||||||
|
|
||||||
this.form.get('data').setValidators(this._atLeastOneElementListValidator('options'));
|
fieldForm.get('data').setValidators(this.myCustomValidators.atLeastOneElementListValidator('options'));
|
||||||
this.form.get('data').updateValueAndValidity();
|
fieldForm.get('data').updateValueAndValidity();
|
||||||
break;
|
break;
|
||||||
case this.viewTypeEnum.Other:
|
case this.viewTypeEnum.Other:
|
||||||
fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.ComboBox)
|
fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.ComboBox)
|
||||||
fieldForm.addControl('data', new AutoCompleteFieldDataEditorModel().buildForm()); //TODO SEE
|
fieldForm.addControl('data', new AutoCompleteFieldDataEditorModel().buildForm()); //TODO SEE
|
||||||
|
|
||||||
fieldForm.get('data').setValidators(this._atLeastOneElementListValidator('autoCompleteSingleDataList'));
|
fieldForm.get('data').setValidators(this.myCustomValidators.atLeastOneElementListValidator('autoCompleteSingleDataList'));
|
||||||
|
fieldForm.get('data').updateValueAndValidity();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case this.viewTypeEnum.InternalDmpEntities:
|
case this.viewTypeEnum.InternalDmpEntities:
|
||||||
|
@ -380,6 +382,9 @@ export class DatasetProfileEditorCompositeFieldComponent implements OnInit, OnCh
|
||||||
case this.viewTypeEnum.RadioBox:
|
case this.viewTypeEnum.RadioBox:
|
||||||
fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.RadioBox)
|
fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.RadioBox)
|
||||||
fieldForm.addControl('data', new RadioBoxFieldDataEditorModel().buildForm());
|
fieldForm.addControl('data', new RadioBoxFieldDataEditorModel().buildForm());
|
||||||
|
fieldForm.get('data').setValidators(this.myCustomValidators.atLeastOneElementListValidator('options'));
|
||||||
|
fieldForm.get('data').updateValueAndValidity();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case this.viewTypeEnum.TextArea:
|
case this.viewTypeEnum.TextArea:
|
||||||
fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.TextArea)
|
fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.TextArea)
|
||||||
|
@ -416,7 +421,7 @@ export class DatasetProfileEditorCompositeFieldComponent implements OnInit, OnCh
|
||||||
break;
|
break;
|
||||||
case this.viewTypeEnum.Organizations:
|
case this.viewTypeEnum.Organizations:
|
||||||
fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Organizations)
|
fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Organizations)
|
||||||
this.form.addControl('data', new OrganizationsDataEditorModel().buildForm());
|
fieldForm.addControl('data', new OrganizationsDataEditorModel().buildForm());
|
||||||
// this.form.addControl('data', new OrganizationsDataEditorModel().buildForm())
|
// this.form.addControl('data', new OrganizationsDataEditorModel().buildForm())
|
||||||
// fieldForm.addControl('data', new DatasetsAutoCompleteFieldDataEditorModel().buildForm()); //TODO
|
// fieldForm.addControl('data', new DatasetsAutoCompleteFieldDataEditorModel().buildForm()); //TODO
|
||||||
break;
|
break;
|
||||||
|
@ -436,7 +441,9 @@ export class DatasetProfileEditorCompositeFieldComponent implements OnInit, OnCh
|
||||||
|
|
||||||
(<FormArray>this.form.get('fields')).push(fieldForm);
|
(<FormArray>this.form.get('fields')).push(fieldForm);
|
||||||
|
|
||||||
// fieldForm.updateValueAndValidity();
|
fieldForm.get('viewStyle').get('renderStyle').updateValueAndValidity();
|
||||||
|
fieldForm.get('data').updateValueAndValidity();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,17 +495,17 @@ export class DatasetProfileEditorCompositeFieldComponent implements OnInit, OnCh
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
private _atLeastOneElementListValidator(arrayToCheck): ValidatorFn{
|
// private _atLeastOneElementListValidator(arrayToCheck): ValidatorFn{
|
||||||
return (control: AbstractControl): ValidationErrors | null=>{
|
// return (control: AbstractControl): ValidationErrors | null=>{
|
||||||
|
|
||||||
const fa = control.get(arrayToCheck) as FormArray;
|
// const fa = control.get(arrayToCheck) as FormArray;
|
||||||
|
|
||||||
if(fa.length === 0){
|
// if(fa.length === 0){
|
||||||
return {emptyArray: true};
|
// return {emptyArray: true};
|
||||||
}
|
// }
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
calculateLabelWidth(numbering: string){
|
calculateLabelWidth(numbering: string){
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<li class="list-inline-item" *ngIf="!viewOnly && viewType">
|
<li class="list-inline-item" *ngIf="!viewOnly && viewType">
|
||||||
<mat-icon style="cursor: pointer;" (click)="addNewRule()" [matTooltip]="'DATASET-PROFILE-EDITOR.ACTIONS.FIELD.ADD-VISIBILITY-RULE' | translate">visibility</mat-icon>
|
<mat-icon style="cursor: pointer;" (click)="addNewRule()" [matTooltip]="'DATASET-PROFILE-EDITOR.ACTIONS.FIELD.ADD-VISIBILITY-RULE' | translate">visibility</mat-icon>
|
||||||
</li>
|
</li>
|
||||||
<li class="list-inline-item" *ngIf="!viewOnly && viewType">
|
<li class="list-inline-item" *ngIf="!viewOnly && viewType && canBeDeleted">
|
||||||
<mat-icon style="cursor: pointer;" (click)="onDelete()" [matTooltip]="'DATASET-PROFILE-EDITOR.ACTIONS.FIELD.DELETE-INPUT' | translate">delete</mat-icon>
|
<mat-icon style="cursor: pointer;" (click)="onDelete()" [matTooltip]="'DATASET-PROFILE-EDITOR.ACTIONS.FIELD.DELETE-INPUT' | translate">delete</mat-icon>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ export class DatasetProfileEditorFieldComponent extends BaseComponent implements
|
||||||
|
|
||||||
|
|
||||||
@Input() expandView: boolean = true;
|
@Input() expandView: boolean = true;
|
||||||
|
@Input() canBeDeleted:boolean = true;
|
||||||
|
|
||||||
@Output() delete = new EventEmitter<void>();
|
@Output() delete = new EventEmitter<void>();
|
||||||
|
|
||||||
|
@ -425,7 +425,7 @@ export class DatasetProfileEditorFieldComponent extends BaseComponent implements
|
||||||
this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.ComboBox)
|
this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.ComboBox)
|
||||||
this.form.addControl('data', new WordListFieldDataEditorModel().buildForm());
|
this.form.addControl('data', new WordListFieldDataEditorModel().buildForm());
|
||||||
|
|
||||||
this.form.get('data').setValidators(this.myCustomValidators._atLeastOneElementListValidator('options'));
|
this.form.get('data').setValidators(this.myCustomValidators.atLeastOneElementListValidator('options'));
|
||||||
this.form.get('data').updateValueAndValidity();
|
this.form.get('data').updateValueAndValidity();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -433,7 +433,7 @@ export class DatasetProfileEditorFieldComponent extends BaseComponent implements
|
||||||
this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.ComboBox)
|
this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.ComboBox)
|
||||||
this.form.addControl('data', new AutoCompleteFieldDataEditorModel().buildForm()); //TODO SEE
|
this.form.addControl('data', new AutoCompleteFieldDataEditorModel().buildForm()); //TODO SEE
|
||||||
|
|
||||||
this.form.get('data').setValidators(this.myCustomValidators._atLeastOneElementListValidator('autoCompleteSingleDataList'));
|
this.form.get('data').setValidators(this.myCustomValidators.atLeastOneElementListValidator('autoCompleteSingleDataList'));
|
||||||
this.form.get('data').updateValueAndValidity();
|
this.form.get('data').updateValueAndValidity();
|
||||||
|
|
||||||
|
|
||||||
|
@ -450,7 +450,7 @@ export class DatasetProfileEditorFieldComponent extends BaseComponent implements
|
||||||
this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.RadioBox)
|
this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.RadioBox)
|
||||||
this.form.addControl('data', new RadioBoxFieldDataEditorModel().buildForm());
|
this.form.addControl('data', new RadioBoxFieldDataEditorModel().buildForm());
|
||||||
|
|
||||||
this.form.get('data').setValidators(this.myCustomValidators._atLeastOneElementListValidator('options'));
|
this.form.get('data').setValidators(this.myCustomValidators.atLeastOneElementListValidator('options'));
|
||||||
this.form.get('data').updateValueAndValidity();
|
this.form.get('data').updateValueAndValidity();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -504,6 +504,10 @@ export class DatasetProfileEditorFieldComponent extends BaseComponent implements
|
||||||
this.form.addControl('data', new ValidationDataEditorModel().buildForm());
|
this.form.addControl('data', new ValidationDataEditorModel().buildForm());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.form.get('data').updateValueAndValidity();
|
||||||
|
this.form.get('viewStyle').get('renderStyle').updateValueAndValidity();
|
||||||
|
this.form.updateValueAndValidity();
|
||||||
setTimeout(() => { //TODO
|
setTimeout(() => { //TODO
|
||||||
this.showPreview = true;
|
this.showPreview = true;
|
||||||
});
|
});
|
||||||
|
|
|
@ -130,6 +130,8 @@ export class DatasetProfileEditorSectionFieldSetComponent extends BaseComponent
|
||||||
if(el){
|
if(el){
|
||||||
el.scrollIntoView({behavior: "smooth"});
|
el.scrollIntoView({behavior: "smooth"});
|
||||||
}
|
}
|
||||||
|
}else{//scroll on top
|
||||||
|
window.scrollTo({top:0, behavior:'smooth'});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
<div class="hint col-12">{{'DATASET-PROFILE-EDITOR.STEPS.SECTION-INFO.SECTION-NAME-HINT' | translate}}</div>
|
<div class="hint col-12">{{'DATASET-PROFILE-EDITOR.STEPS.SECTION-INFO.SECTION-NAME-HINT' | translate}}</div>
|
||||||
<mat-form-field class="col-12">
|
<mat-form-field class="col-12">
|
||||||
<input matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.TITLE' | translate}}"
|
<input matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.TITLE' | translate}}"
|
||||||
formControlName="title">
|
formControlName="title" required>
|
||||||
|
<mat-error >{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<!-- <mat-form-field class="col-md-3">
|
<!-- <mat-form-field class="col-md-3">
|
||||||
<mat-select placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.PAGE' | translate}}" formControlName="page"
|
<mat-select placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.PAGE' | translate}}" formControlName="page"
|
||||||
|
@ -30,7 +31,8 @@
|
||||||
<div class="hint col-12">{{'DATASET-PROFILE-EDITOR.STEPS.SECTION-INFO.SECTION-DESCRIPTION-HINT' | translate}}</div>
|
<div class="hint col-12">{{'DATASET-PROFILE-EDITOR.STEPS.SECTION-INFO.SECTION-DESCRIPTION-HINT' | translate}}</div>
|
||||||
<mat-form-field class="col-12">
|
<mat-form-field class="col-12">
|
||||||
<input matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.DESCRIPTION' | translate}}"
|
<input matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.DESCRIPTION' | translate}}"
|
||||||
formControlName="description">
|
formControlName="description" required>
|
||||||
|
<mat-error >{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,16 +4,64 @@ import { AbstractControl, FormArray, ValidationErrors, ValidatorFn } from "@angu
|
||||||
|
|
||||||
export class EditorCustomValidators{
|
export class EditorCustomValidators{
|
||||||
|
|
||||||
public _atLeastOneElementListValidator(arrayToCheck): ValidatorFn{
|
public atLeastOneElementListValidator(arrayToCheck): ValidatorFn{
|
||||||
return (control: AbstractControl): ValidationErrors | null=>{
|
return (control: AbstractControl): ValidationErrors | null=>{
|
||||||
|
|
||||||
const fa = control.get(arrayToCheck) as FormArray;
|
const fa = control.get(arrayToCheck) as FormArray;
|
||||||
|
|
||||||
if(fa.length === 0){
|
if(fa.length === 0){
|
||||||
return {emptyArray: true};
|
return {[EditorCustomValidatorsEnum.emptyArray]: true};
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public pagesHaveAtLeastOneSection(pagesArrayName:string,sectionsArrayName:string ): ValidatorFn{
|
||||||
|
|
||||||
|
return (control: AbstractControl): ValidationErrors | null=>{
|
||||||
|
|
||||||
|
const pages = control.get(pagesArrayName) as FormArray;
|
||||||
|
const sections = control.get(sectionsArrayName) as FormArray;
|
||||||
|
|
||||||
|
|
||||||
|
const pageIdsArray = pages.controls.map(page=>page.get('id').value);
|
||||||
|
const sectionsPageIds = sections.controls.map(section=> section.get('page').value);
|
||||||
|
|
||||||
|
let invalidMessage = null;
|
||||||
|
|
||||||
|
pageIdsArray.forEach(pageId=>{
|
||||||
|
if(!sectionsPageIds.includes(pageId)){
|
||||||
|
invalidMessage = {[EditorCustomValidatorsEnum.atLeastOneSectionInPage]:true};
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return invalidMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sectionHasAtLeastOneChildOf(fieldsetsArrayName, sectionsArrayName): ValidatorFn{
|
||||||
|
|
||||||
|
return (control: AbstractControl): ValidationErrors | null=>{
|
||||||
|
|
||||||
|
const fieldsets = control.get(fieldsetsArrayName) as FormArray;
|
||||||
|
const sections = control.get(sectionsArrayName) as FormArray;
|
||||||
|
|
||||||
|
|
||||||
|
if((fieldsets && fieldsets.length) || (sections && sections.length)){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {[EditorCustomValidatorsEnum.sectionMustHaveOneChild] : true};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export enum EditorCustomValidatorsEnum{
|
||||||
|
sectionMustHaveOneChild = "sectionMustHaveOneChild",
|
||||||
|
atLeastOneSectionInPage = 'atLeastOneSectionInPage',
|
||||||
|
emptyArray="emptyArray"
|
||||||
|
}
|
|
@ -40,7 +40,7 @@
|
||||||
<span (click)="stepper.selectedIndex=idx"
|
<span (click)="stepper.selectedIndex=idx"
|
||||||
class="stepper-title-label"
|
class="stepper-title-label"
|
||||||
[ngClass]="{'stepper-title-label-locked': !isStepUnlocked(idx),'stepper-title-label-completed':idx < stepper.selectedIndex} ">
|
[ngClass]="{'stepper-title-label-locked': !isStepUnlocked(idx),'stepper-title-label-completed':idx < stepper.selectedIndex} ">
|
||||||
<ng-container *ngIf="isStepCompleted(idx) else numberLabel">
|
<ng-container *ngIf="(step.completed &&(idx!=steps.length-1)) else numberLabel">
|
||||||
<mat-icon style="font-size:0.7em; height: 0px;">done</mat-icon>
|
<mat-icon style="font-size:0.7em; height: 0px;">done</mat-icon>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-template #numberLabel>
|
<ng-template #numberLabel>
|
||||||
|
@ -119,7 +119,8 @@
|
||||||
|
|
||||||
<mat-horizontal-stepper [linear]="true" #stepper class="stepper" (selectionChange)="onMatStepperSelectionChange($event)" style="padding-left: 8px; padding-right: 15px;">
|
<mat-horizontal-stepper [linear]="true" #stepper class="stepper" (selectionChange)="onMatStepperSelectionChange($event)" style="padding-left: 8px; padding-right: 15px;">
|
||||||
|
|
||||||
<mat-step [label]="'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.TITLE' | translate" [stepControl]="basicInfo">
|
<!-- IMPORTANT TO BE !INVALID (WHEN THE TEMPLATE IS FINALIZED THE CONTORLS ARE DISABLED) -->
|
||||||
|
<mat-step [label]="'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.TITLE' | translate" [completed]="(!form.get('label').invalid && !form.get('description').invalid && !form.get('language').invalid)" >
|
||||||
<!-- <ng-template matStepLabel>{{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.TITLE' | translate}}
|
<!-- <ng-template matStepLabel>{{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.TITLE' | translate}}
|
||||||
</ng-template> -->
|
</ng-template> -->
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -127,7 +128,7 @@
|
||||||
<div class="heading">1.1 {{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-NAME'| translate}} *</div>
|
<div class="heading">1.1 {{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-NAME'| translate}} *</div>
|
||||||
<div class="hint">{{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-NAME-HINT'| translate}}</div>
|
<div class="hint">{{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-NAME-HINT'| translate}}</div>
|
||||||
<mat-form-field class="full-width basic-info-input">
|
<mat-form-field class="full-width basic-info-input">
|
||||||
<input matInput formControlName="label"
|
<input matInput [formControl]="form.get('label')"
|
||||||
placeholder="{{'DATASET-PROFILE-EDITOR.FIELDS.DATASET-TITLE' | translate}}" required>
|
placeholder="{{'DATASET-PROFILE-EDITOR.FIELDS.DATASET-TITLE' | translate}}" required>
|
||||||
<mat-error *ngIf="form.get('label').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' |
|
<mat-error *ngIf="form.get('label').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' |
|
||||||
translate}}
|
translate}}
|
||||||
|
@ -139,7 +140,7 @@
|
||||||
<!-- <div class="hint">{{'DMP-EDITOR.MAIN-INFO.HINT' | translate}}</div> -->
|
<!-- <div class="hint">{{'DMP-EDITOR.MAIN-INFO.HINT' | translate}}</div> -->
|
||||||
<div class="hint">{{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-DESCRIPTION-HINT'| translate}}</div>
|
<div class="hint">{{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-DESCRIPTION-HINT'| translate}}</div>
|
||||||
<mat-form-field class="full-width basic-info-input">
|
<mat-form-field class="full-width basic-info-input">
|
||||||
<textarea matInput formControlName="description" cdkTextareaAutosize cdkAutosizeMinRows="4" cdkAutosizeMaxRows="5"
|
<textarea matInput [formControl]="form.get('description')" cdkTextareaAutosize cdkAutosizeMinRows="4" cdkAutosizeMaxRows="5"
|
||||||
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-DESCRIPTION-PLACEHOLDER'| translate}}" required>
|
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-DESCRIPTION-PLACEHOLDER'| translate}}" required>
|
||||||
</textarea>
|
</textarea>
|
||||||
<mat-error *ngIf="form.get('description').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED'
|
<mat-error *ngIf="form.get('description').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED'
|
||||||
|
@ -153,7 +154,7 @@
|
||||||
<div class="heading">1.3 {{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-LANGUAGE'| translate}} *</div>
|
<div class="heading">1.3 {{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-LANGUAGE'| translate}} *</div>
|
||||||
<mat-form-field class="full-width basic-info-input">
|
<mat-form-field class="full-width basic-info-input">
|
||||||
<!-- <input matInput formControlName="description" placeholder="{{'DATASET-PROFILE-EDITOR.FIELDS.DATASET-DESCRIPTION' | translate}}" required> -->
|
<!-- <input matInput formControlName="description" placeholder="{{'DATASET-PROFILE-EDITOR.FIELDS.DATASET-DESCRIPTION' | translate}}" required> -->
|
||||||
<mat-select formControlName="language" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-SELECT-LANGUAGE'| translate}}">
|
<mat-select [formControl]="form.get('language')" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-SELECT-LANGUAGE'| translate}}">
|
||||||
<mat-option *ngFor="let lang of getLanguageInfos()" [value]="lang.code">
|
<mat-option *ngFor="let lang of getLanguageInfos()" [value]="lang.code">
|
||||||
{{ lang.name }}
|
{{ lang.name }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
@ -181,7 +182,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</mat-step> -->
|
</mat-step> -->
|
||||||
<mat-step [label]="'DATASET-PROFILE-EDITOR.STEPS.FORM.TITLE' | translate" [stepControl]="form">
|
<mat-step [label]="'DATASET-PROFILE-EDITOR.STEPS.FORM.TITLE' | translate" [completed]="form.valid">
|
||||||
<!-- <ng-template matStepLabel>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.TITLE' | translate}}</ng-template> -->
|
<!-- <ng-template matStepLabel>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.TITLE' | translate}}</ng-template> -->
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
||||||
|
@ -200,7 +201,8 @@
|
||||||
(removeEntry)="onRemoveEntry($event)"
|
(removeEntry)="onRemoveEntry($event)"
|
||||||
[itemSelected]="selectedTocEntry"
|
[itemSelected]="selectedTocEntry"
|
||||||
[viewOnly]="viewOnly"
|
[viewOnly]="viewOnly"
|
||||||
(dataNeedsRefresh)="onDataNeedsRefresh()">
|
(dataNeedsRefresh)="onDataNeedsRefresh()"
|
||||||
|
[colorizeInvalid]="colorizeInvalid">
|
||||||
</dataset-profile-table-of-contents>
|
</dataset-profile-table-of-contents>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -224,6 +226,7 @@
|
||||||
<div class="hint">{{'DATASET-PROFILE-EDITOR.STEPS.PAGE-INFO.PAGE-NAME-HINT' | translate}}</div>
|
<div class="hint">{{'DATASET-PROFILE-EDITOR.STEPS.PAGE-INFO.PAGE-NAME-HINT' | translate}}</div>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<input type="text" matInput formControlName="title">
|
<input type="text" matInput formControlName="title">
|
||||||
|
<mat-error >{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -402,7 +405,7 @@
|
||||||
<!-- SAVE BUTTON -->
|
<!-- SAVE BUTTON -->
|
||||||
<div class="col-6 d-flex" *ngIf="!viewOnly">
|
<div class="col-6 d-flex" *ngIf="!viewOnly">
|
||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<ng-container *ngIf="false">
|
<ng-container *ngIf="true">
|
||||||
<button mat-raised-button class="col-auto mr-2" color="primary" type="button col-auto"
|
<button mat-raised-button class="col-auto mr-2" color="primary" type="button col-auto"
|
||||||
(click)='checkFormValidation()'
|
(click)='checkFormValidation()'
|
||||||
[disabled]="form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.VALIDATE' | translate}}</button>
|
[disabled]="form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.VALIDATE' | translate}}</button>
|
||||||
|
@ -440,12 +443,20 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<!--
|
|
||||||
<div class="row">
|
<!-- <div class="row">
|
||||||
<button (click)="printForm()">
|
<button (click)="printForm()">
|
||||||
console form
|
console form
|
||||||
</button>
|
</button>
|
||||||
</div> -->
|
</div> -->
|
||||||
|
<!--
|
||||||
|
<div *ngIf="form">{{form.value | json}}</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<div class="row">
|
||||||
|
{{form.controls?.sections.value |json}}
|
||||||
|
</div> -->
|
||||||
|
|
||||||
<!-- {{form.value | json}} -->
|
<!-- {{form.value | json}} -->
|
||||||
<!-- <div class="row">
|
<!-- <div class="row">
|
||||||
|
|
|
@ -41,7 +41,7 @@ import { Rule } from '@app/core/model/dataset-profile-definition/rule';
|
||||||
import { DatasetProfileFieldViewStyle } from '@app/core/common/enum/dataset-profile-field-view-style';
|
import { DatasetProfileFieldViewStyle } from '@app/core/common/enum/dataset-profile-field-view-style';
|
||||||
import { invalid } from '@angular/compiler/src/render3/view/util';
|
import { invalid } from '@angular/compiler/src/render3/view/util';
|
||||||
import { SideNavService } from '@app/core/services/sidenav/side-nav.sevice';
|
import { SideNavService } from '@app/core/services/sidenav/side-nav.sevice';
|
||||||
import { EditorCustomValidators } from './custom-validators/editor-custom-validators';
|
import { EditorCustomValidators, EditorCustomValidatorsEnum } from './custom-validators/editor-custom-validators';
|
||||||
import { CustomErrorValidator } from '@common/forms/validation/custom-validator';
|
import { CustomErrorValidator } from '@common/forms/validation/custom-validator';
|
||||||
import { STEPPER_ANIMATIONS } from './animations/animations';
|
import { STEPPER_ANIMATIONS } from './animations/animations';
|
||||||
const skipDisable: any[] = require('../../../../../assets/resources/skipDisable.json');
|
const skipDisable: any[] = require('../../../../../assets/resources/skipDisable.json');
|
||||||
|
@ -72,6 +72,8 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
errorMessages: string[] = [];
|
errorMessages: string[] = [];
|
||||||
tocEntryEnumValues = ToCEntryType;
|
tocEntryEnumValues = ToCEntryType;
|
||||||
|
|
||||||
|
colorizeInvalid:boolean = false;
|
||||||
|
|
||||||
|
|
||||||
customEditorValidators = new EditorCustomValidators();
|
customEditorValidators = new EditorCustomValidators();
|
||||||
|
|
||||||
|
@ -187,7 +189,7 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
} else {
|
} else {
|
||||||
this.dataModel = new DatasetProfileEditorModel();
|
this.dataModel = new DatasetProfileEditorModel();
|
||||||
this.form = this.dataModel.buildForm();
|
this.form = this.dataModel.buildForm();
|
||||||
this.form.setValidators([this.customEditorValidators._atLeastOneElementListValidator('pages'), this.customEditorValidators._atLeastOneElementListValidator('sections')])
|
this.form.setValidators([this.customEditorValidators.atLeastOneElementListValidator('pages'), this.customEditorValidators.pagesHaveAtLeastOneSection('pages', 'sections')])
|
||||||
if (this.dataModel.status === DatasetProfileEnum.FINALIZED) {
|
if (this.dataModel.status === DatasetProfileEnum.FINALIZED) {
|
||||||
this.form.disable();
|
this.form.disable();
|
||||||
this.viewOnly = true;
|
this.viewOnly = true;
|
||||||
|
@ -207,10 +209,11 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
|
|
||||||
prepareForm() {
|
prepareForm() {
|
||||||
this.visibilityRulesService.buildVisibilityRules([],this.form);
|
this.visibilityRulesService.buildVisibilityRules([],this.form);
|
||||||
this.form.setValidators([this.customEditorValidators._atLeastOneElementListValidator('pages'), this.customEditorValidators._atLeastOneElementListValidator('pages')]);
|
this.form.setValidators([this.customEditorValidators.atLeastOneElementListValidator('pages'),this.customEditorValidators.pagesHaveAtLeastOneSection('pages', 'sections')]);
|
||||||
this.form.valueChanges
|
this.form.valueChanges
|
||||||
.pipe(takeUntil(this._destroyed))
|
.pipe(takeUntil(this._destroyed))
|
||||||
.subscribe(change => {
|
.subscribe(change => {
|
||||||
|
|
||||||
// this.datasetProfileService.preview(this.form.value)
|
// this.datasetProfileService.preview(this.form.value)
|
||||||
// .pipe(takeUntil(this._destroyed))
|
// .pipe(takeUntil(this._destroyed))
|
||||||
// .subscribe(dataset => {
|
// .subscribe(dataset => {
|
||||||
|
@ -230,8 +233,6 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
this.selectedTocEntry = tocentries[0];
|
this.selectedTocEntry = tocentries[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
//this.getPreview();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onIsMultiplicityEnabledChange(isMultiplicityEnabled: boolean) {
|
onIsMultiplicityEnabledChange(isMultiplicityEnabled: boolean) {
|
||||||
|
@ -241,11 +242,11 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addSection() {
|
// addSection() {
|
||||||
const section: SectionEditorModel = new SectionEditorModel();
|
// const section: SectionEditorModel = new SectionEditorModel();
|
||||||
this.dataModel.sections.push(section);
|
// this.dataModel.sections.push(section);
|
||||||
(<FormArray>this.form.get('sections')).push(section.buildForm());
|
// (<FormArray>this.form.get('sections')).push(section.buildForm());
|
||||||
}
|
// }
|
||||||
|
|
||||||
addPage() {
|
addPage() {
|
||||||
const page: PageEditorModel = new PageEditorModel(this.dataModel.pages.length);
|
const page: PageEditorModel = new PageEditorModel(this.dataModel.pages.length);
|
||||||
|
@ -376,6 +377,11 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateValidity(){
|
||||||
|
// this.form.updateValueAndValidity();
|
||||||
|
console.log('updagted');
|
||||||
|
}
|
||||||
|
|
||||||
getFilenameFromContentDispositionHeader(header: string): string {
|
getFilenameFromContentDispositionHeader(header: string): string {
|
||||||
const regex: RegExp = new RegExp(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/g);
|
const regex: RegExp = new RegExp(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/g);
|
||||||
|
|
||||||
|
@ -399,15 +405,19 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFormValidation() {
|
checkFormValidation() {
|
||||||
if (!this.form.valid) {
|
this.colorizeInvalid = true;
|
||||||
this.nestedIndex = -1;
|
this.printMyErrors(this.form);
|
||||||
this.form.markAllAsTouched();
|
|
||||||
this.printErrors(this.form);
|
|
||||||
this.showValidationErrorsDialog();
|
// if (!this.form.valid) {
|
||||||
this.nestedCount = [];
|
// this.nestedIndex = -1;
|
||||||
this.nestedIndex = 0;
|
// this.form.markAllAsTouched();
|
||||||
this.errorMessages = [];
|
// this.printErrors(this.form);
|
||||||
}
|
// this.showValidationErrorsDialog();
|
||||||
|
// this.nestedCount = [];
|
||||||
|
// this.nestedIndex = 0;
|
||||||
|
// this.errorMessages = [];
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
printErrors(rootform: FormGroup) {
|
printErrors(rootform: FormGroup) {
|
||||||
|
@ -740,7 +750,7 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
// this.dataModel.pages.push(page);
|
// this.dataModel.pages.push(page);
|
||||||
|
|
||||||
pagesArray.push(pageForm);
|
pagesArray.push(pageForm);
|
||||||
|
// this.form.updateValueAndValidity();
|
||||||
this.refreshToCEntries();
|
this.refreshToCEntries();
|
||||||
this.selectedTocEntry = this._findTocEntryById(pageForm.get('id').value, this.toCEntries);
|
this.selectedTocEntry = this._findTocEntryById(pageForm.get('id').value, this.toCEntries);
|
||||||
|
|
||||||
|
@ -757,6 +767,7 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
section.page = parent.id;
|
section.page = parent.id;
|
||||||
section.ordinal = sectionsArray.length;
|
section.ordinal = sectionsArray.length;
|
||||||
sectionsArray.push(section.buildForm());
|
sectionsArray.push(section.buildForm());
|
||||||
|
// this.form.updateValueAndValidity();
|
||||||
|
|
||||||
} else if( parent.type == ToCEntryType.Section) { //SUBSECTION OF SECTION
|
} else if( parent.type == ToCEntryType.Section) { //SUBSECTION OF SECTION
|
||||||
sectionsArray = parent.form.get('sections') as FormArray;
|
sectionsArray = parent.form.get('sections') as FormArray;
|
||||||
|
@ -774,6 +785,8 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
|
|
||||||
|
|
||||||
const sectionAdded = sectionsArray.at(sectionsArray.length -1) as FormGroup;
|
const sectionAdded = sectionsArray.at(sectionsArray.length -1) as FormGroup;
|
||||||
|
sectionAdded.setValidators(this.customEditorValidators.sectionHasAtLeastOneChildOf('fieldSets','sections'));
|
||||||
|
sectionAdded.updateValueAndValidity();
|
||||||
|
|
||||||
|
|
||||||
this.refreshToCEntries();
|
this.refreshToCEntries();
|
||||||
|
@ -817,7 +830,7 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this.refreshToCEntries();
|
this.form.updateValueAndValidity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -912,27 +925,29 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
pages.removeAt(pageIndex);
|
pages.removeAt(pageIndex);
|
||||||
//clean up sections of removed page
|
//clean up sections of removed page
|
||||||
|
|
||||||
const sections = (this.form.get('sections') as FormArray).controls;
|
const sections = (this.form.get('sections') as FormArray);
|
||||||
|
|
||||||
const updatedSections = new FormArray([]);
|
const sectionsIndexToBeRemoved = [];
|
||||||
|
|
||||||
for (let i = 0; i < sections.length; i++) {
|
sections.controls.forEach((section,idx)=>{
|
||||||
let section = sections[i];
|
if(section.get('page').value === tce.id){
|
||||||
|
sectionsIndexToBeRemoved.push(idx);
|
||||||
if (section.get('page').value != tce.id) {
|
|
||||||
updatedSections.push(section);
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
//replace sections value
|
|
||||||
this.form.controls.sections = updatedSections;
|
|
||||||
|
|
||||||
//update page orders
|
if(sectionsIndexToBeRemoved.length){
|
||||||
|
sectionsIndexToBeRemoved.reverse().forEach(index=>{
|
||||||
|
sections.removeAt(index);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//update page ordinals
|
||||||
for(let i=0; i<pages.length; i++){
|
for(let i=0; i<pages.length; i++){
|
||||||
pages.at(i).get('ordinal').patchValue(i);
|
pages.at(i).get('ordinal').patchValue(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
//update validity
|
//update validity
|
||||||
this.form.controls.sections.updateValueAndValidity();
|
// this.form.controls.sections.updateValueAndValidity();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1028,6 +1043,7 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
//in case selectedtocentrhy is child of the removed element
|
//in case selectedtocentrhy is child of the removed element
|
||||||
|
|
||||||
this.refreshToCEntries();
|
this.refreshToCEntries();
|
||||||
|
this.form.updateValueAndValidity();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1339,22 +1355,22 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
get basicInfo(){
|
// get basicInfo(){
|
||||||
|
|
||||||
const label = this.form.get('label');
|
// const label = this.form.get('label');
|
||||||
const description = this.form.get('description');
|
// const description = this.form.get('description');
|
||||||
const language = this.form.get('language');
|
// const language = this.form.get('language');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const fg = new FormGroup({
|
// const fg = new FormGroup({
|
||||||
label: label,
|
// label: label,
|
||||||
description: description,
|
// description: description,
|
||||||
language: language
|
// language: language
|
||||||
})
|
// })
|
||||||
|
|
||||||
return fg;
|
// return fg;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1421,14 +1437,12 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isStepCompleted(stepIndex: number){
|
isStepCompleted(stepIndex: number){ //TODO NA TO DOUME MIPOS DEN XREIAZETAI
|
||||||
|
|
||||||
let stepCompleted = false;
|
let stepCompleted = false;
|
||||||
this.steps.forEach((step,index)=>{
|
this.steps.forEach((step,index)=>{
|
||||||
if(stepIndex === index){
|
if(stepIndex === index){
|
||||||
if(step.stepControl){
|
stepCompleted = step.completed;
|
||||||
stepCompleted = step.stepControl.valid;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1437,13 +1451,17 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
|
|
||||||
isStepUnlocked(stepIndex: number): boolean{
|
isStepUnlocked(stepIndex: number): boolean{
|
||||||
if(stepIndex === 0) return true;
|
if(stepIndex === 0) return true;
|
||||||
|
if(stepIndex <0 ) return false;
|
||||||
//if previous step is valid then unlock
|
//if previous step is valid then unlock
|
||||||
let stepUnlocked: boolean = false;
|
let stepUnlocked: boolean = false;
|
||||||
|
|
||||||
|
if(!this.isStepUnlocked(stepIndex -1)) return false;
|
||||||
|
|
||||||
this.steps.forEach((step,index)=>{
|
this.steps.forEach((step,index)=>{
|
||||||
|
|
||||||
if(index+1 == stepIndex){//previous step
|
if(index+1 == stepIndex){//previous step
|
||||||
if(step.stepControl.valid){
|
|
||||||
|
if(step.completed){
|
||||||
stepUnlocked = true;
|
stepUnlocked = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1453,27 +1471,27 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
}
|
}
|
||||||
|
|
||||||
validateStep(step: CdkStep){
|
validateStep(step: CdkStep){
|
||||||
if(step.hasError){
|
// if(step.hasError){
|
||||||
this.printMyErrors(this.form);
|
// this.printMyErrors(this.form);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
getFormValidationErrors() {
|
// getFormValidationErrors() {
|
||||||
Object.keys(this.form.controls).forEach(key => {
|
// Object.keys(this.form.controls).forEach(key => {
|
||||||
|
|
||||||
const controlErrors: ValidationErrors = this.form.get(key).errors;
|
// const controlErrors: ValidationErrors = this.form.get(key).errors;
|
||||||
if (controlErrors != null) {
|
// if (controlErrors != null) {
|
||||||
Object.keys(controlErrors).forEach(keyError => {
|
// Object.keys(controlErrors).forEach(keyError => {
|
||||||
console.log('Key control: ' + key + ', keyError: ' + keyError + ', err value: ', controlErrors[keyError]);
|
// console.log('Key control: ' + key + ', keyError: ' + keyError + ', err value: ', controlErrors[keyError]);
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
if(this.form.invalid){
|
// if(this.form.invalid){
|
||||||
console.log('this form is invalid!');
|
// console.log('this form is invalid!');
|
||||||
console.log(this.form.errors);
|
// console.log(this.form.errors);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1481,11 +1499,26 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
const errmess: string[] = [];
|
const errmess: string[] = [];
|
||||||
|
|
||||||
Object.keys(errors).forEach(keyError => {
|
Object.keys(errors).forEach(keyError => {
|
||||||
if (typeof errors[keyError] === 'boolean') {
|
|
||||||
errmess.push(numbering + ' ' + key + ' is ' + keyError);
|
switch(keyError){
|
||||||
} else {
|
case EditorCustomValidatorsEnum.atLeastOneSectionInPage:
|
||||||
errmess.push(numbering + ' ' + key + ': ' + keyError + ': ' + JSON.stringify(errors[keyError]));
|
errmess.push('Each section must have at least one subsection');
|
||||||
|
break;
|
||||||
|
case EditorCustomValidatorsEnum.emptyArray:
|
||||||
|
errmess.push(numbering+" needs more information.")
|
||||||
|
break;
|
||||||
|
case EditorCustomValidatorsEnum.sectionMustHaveOneChild:
|
||||||
|
errmess.push(numbering+" must have either subsection or input sets.")
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (typeof errors[keyError] === 'boolean') {
|
||||||
|
errmess.push(numbering + ' ' + key + ' is ' + keyError);
|
||||||
|
} else {
|
||||||
|
errmess.push(numbering + ' ' + key + ': ' + keyError + ': ' + JSON.stringify(errors[keyError]));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return errmess;
|
return errmess;
|
||||||
|
@ -1495,59 +1528,67 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
printMyErrors(form: AbstractControl){
|
printMyErrors(form: AbstractControl){
|
||||||
// this._printToCentriesErrrors(this.toCEntries);
|
// this._printToCentriesErrrors(this.toCEntries);
|
||||||
const result = this._getErrors(form);
|
const result = this._getErrors(form);
|
||||||
// console.log('result', result);
|
|
||||||
|
|
||||||
|
|
||||||
|
// console.log('got errors ');
|
||||||
// console.log(result);
|
// console.log(result);
|
||||||
|
|
||||||
if(result){
|
if(result && form.invalid){
|
||||||
|
|
||||||
form.markAllAsTouched();
|
|
||||||
const errmess:string[] = [];
|
const errmess:string[] = [];
|
||||||
|
if(result.length){
|
||||||
|
form.markAllAsTouched();
|
||||||
|
|
||||||
let indexes:number[] = [];
|
let indexes:number[] = [];
|
||||||
///search in pages,sections and fieldsets for the id
|
///search in pages,sections and fieldsets for the id
|
||||||
result.forEach((err,i)=>{
|
result.forEach((err,i)=>{
|
||||||
const entry = this._findTocEntryById(err.id, this.toCEntries);
|
const entry = this._findTocEntryById(err.id, this.toCEntries);
|
||||||
if(entry){
|
if(entry){
|
||||||
|
|
||||||
// errmess.push(`Error on ${entry.numbering} ${entry.label} . ${err.key}`);
|
// errmess.push(`Error on ${entry.numbering} ${entry.label} . ${err.key}`);
|
||||||
errmess.push(...this._buildErrorMessage(err.errors, entry.numbering, err.key));
|
errmess.push(...this._buildErrorMessage(err.errors, entry.numbering, err.key));
|
||||||
indexes.push(i);
|
indexes.push(i);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
indexes.reverse().forEach(index=>{
|
indexes.reverse().forEach(index=>{
|
||||||
result.splice(index,1);
|
result.splice(index,1);
|
||||||
});
|
|
||||||
|
|
||||||
indexes = [];
|
|
||||||
//searching in fields
|
|
||||||
const fieldsets = this._getAllFieldSets(this.toCEntries);
|
|
||||||
result.forEach((err,i)=>{
|
|
||||||
fieldsets.filter(fs=>{
|
|
||||||
let fieldFound = false;
|
|
||||||
(fs.form.get('fields') as FormArray).controls.forEach(field=>{
|
|
||||||
if(field.get('id').value === err.id){
|
|
||||||
fieldFound = true;
|
|
||||||
indexes.push(i);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return fieldFound;
|
|
||||||
})
|
|
||||||
//printing fieldsets that the field missing
|
|
||||||
.forEach(fs=>{
|
|
||||||
// errmess.push(`Missing input in ${fs.numbering} ${fs.label} . ${err.key}`);
|
|
||||||
errmess.push(...this._buildErrorMessage(err.errors, fs.numbering, err.key));
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
indexes.reverse().forEach(index=>{
|
indexes = [];
|
||||||
result.splice(index,1);
|
//searching in fields
|
||||||
});
|
const fieldsets = this._getAllFieldSets(this.toCEntries);
|
||||||
|
result.forEach((err,i)=>{
|
||||||
|
fieldsets.filter(fs=>{
|
||||||
|
let fieldFound = false;
|
||||||
|
(fs.form.get('fields') as FormArray).controls.forEach(field=>{
|
||||||
|
if(field.get('id').value === err.id){
|
||||||
|
fieldFound = true;
|
||||||
|
indexes.push(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return fieldFound;
|
||||||
|
})
|
||||||
|
//printing fieldsets that the field missing
|
||||||
|
.forEach(fs=>{
|
||||||
|
// errmess.push(`Missing input in ${fs.numbering} ${fs.label} . ${err.key}`);
|
||||||
|
errmess.push(...this._buildErrorMessage(err.errors, fs.numbering, err.key));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
result.forEach(err=>{
|
indexes.reverse().forEach(index=>{
|
||||||
errmess.push(`Missing ${err.key}` );
|
result.splice(index,1);
|
||||||
})
|
});
|
||||||
|
|
||||||
|
result.forEach(err=>{
|
||||||
|
// console.log(err);
|
||||||
|
if(err.key){
|
||||||
|
errmess.push(`Missing ${err.key}` );
|
||||||
|
}else{
|
||||||
|
|
||||||
|
errmess.push('Make sure you provide a section and a subsection');
|
||||||
|
}
|
||||||
|
// errmess.push(...this._buildErrorMessage(err.errors,"", err.key) );
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// console.log(result);
|
// console.log(result);
|
||||||
|
|
||||||
|
@ -1627,11 +1668,7 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
|
|
||||||
private _getErrors(aControl: AbstractControl):InvalidControl[]{
|
private _getErrors(aControl: AbstractControl):InvalidControl[]{
|
||||||
|
|
||||||
// if(aControl instanceof FormGroup) console.log('is Formgroup');
|
|
||||||
// if(aControl instanceof FormControl)console.log( aControl.errors);
|
|
||||||
// if(aControl instanceof FormArray) console.log('isForm array');
|
|
||||||
|
|
||||||
// console
|
|
||||||
if(aControl.valid) return;
|
if(aControl.valid) return;
|
||||||
|
|
||||||
let controlType = 'control';
|
let controlType = 'control';
|
||||||
|
@ -1650,14 +1687,11 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
const keys = Object.keys(controls);
|
const keys = Object.keys(controls);
|
||||||
keys.forEach(key=>{
|
keys.forEach(key=>{
|
||||||
const control = controls[key];
|
const control = controls[key];
|
||||||
if(control.valid) return;
|
if(!control.invalid) return; //// !!!!! Important to be !invalid. (In case the template is finalized)
|
||||||
|
|
||||||
if(control instanceof FormControl){
|
if(control instanceof FormControl){
|
||||||
const ctrl = control as FormControl;
|
const ctrl = control as FormControl;
|
||||||
|
|
||||||
// console.log('Control ', key,' of Formgroup ', aControl.get('id'), ' has errors', ctrl.errors);
|
|
||||||
// console.log(aControl)
|
|
||||||
|
|
||||||
invalidControls.push({
|
invalidControls.push({
|
||||||
errors:ctrl.errors,
|
errors:ctrl.errors,
|
||||||
id: ctrl.get('id')? ctrl.get('id').value: null,
|
id: ctrl.get('id')? ctrl.get('id').value: null,
|
||||||
|
@ -1674,26 +1708,38 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
// invalidSubControls:[]//TODO TO CHECK
|
// invalidSubControls:[]//TODO TO CHECK
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
if(control.errors){
|
|
||||||
// invalidControls.push({
|
|
||||||
// id: aControl.get('id')? aControl.get('id').value: null,
|
|
||||||
// errors:aControl.errors,
|
|
||||||
// key: aControl.get('title')? aControl.get('title').value: 'unspecified',
|
|
||||||
// invalidSubControls:[]//TODO TO CHECK
|
|
||||||
// });
|
|
||||||
|
|
||||||
invalidControls.push({
|
|
||||||
errors:control.errors,
|
//THE ONE WE REMOVED
|
||||||
id: control.get('id')? control.get('id').value: null,
|
// if(control.errors){
|
||||||
invalidSubControls: [],
|
// // invalidControls.push({
|
||||||
key: key
|
// // id: aControl.get('id')? aControl.get('id').value: null,
|
||||||
});
|
// // errors:aControl.errors,
|
||||||
}
|
// // key: aControl.get('title')? aControl.get('title').value: 'unspecified',
|
||||||
|
// // invalidSubControls:[]//TODO TO CHECK
|
||||||
|
// // });
|
||||||
|
|
||||||
|
// invalidControls.push({
|
||||||
|
// errors:control.errors,
|
||||||
|
// id: control.get('id')? control.get('id').value: null,
|
||||||
|
// invalidSubControls: [],
|
||||||
|
// key: key
|
||||||
|
// });
|
||||||
|
// }
|
||||||
invalidControls.push(...this._getErrors(control)) ;
|
invalidControls.push(...this._getErrors(control)) ;
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**In case there is an error in a formgroup then the validator probably is custom */
|
||||||
|
if(aControl.errors){
|
||||||
|
invalidControls.push({
|
||||||
|
errors:aControl.errors,
|
||||||
|
id: aControl.get('id')? aControl.get('id').value: null,
|
||||||
|
invalidSubControls: [],
|
||||||
|
key: aControl.get('title')?aControl.get('title').value: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'fa':
|
case 'fa':
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
[ngStyle]="{'font-size' : (parentLink.type == tocEntryType.FieldSet? '.9rem':'1rem')}"
|
[ngStyle]="{'font-size' : (parentLink.type == tocEntryType.FieldSet? '.9rem':'1rem')}"
|
||||||
> -->
|
> -->
|
||||||
<span class="table-label-element" [ngClass]="{'table-label-element-active': itemSelected?.id == parentLink?.id}" (click)="itemClicked(parentLink)"
|
<span class="table-label-element" [ngClass]="{'table-label-element-active': itemSelected?.id == parentLink?.id, 'text-danger': colorError()}" (click)="itemClicked(parentLink)"
|
||||||
[ngStyle]="{'font-size' : (parentLink.type == tocEntryType.FieldSet? '.9rem':'1rem')}"
|
[ngStyle]="{'font-size' : (parentLink.type == tocEntryType.FieldSet? '.9rem':'1rem')}"
|
||||||
>
|
>
|
||||||
<!-- {{parentLink?.numbering}} {{parentLink?.label? parentLink?.label : 'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.UNTITLED' | translate}} -->
|
<!-- {{parentLink?.numbering}} {{parentLink?.label? parentLink?.label : 'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.UNTITLED' | translate}} -->
|
||||||
|
@ -33,10 +33,14 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto d-flex align-items-center" >
|
<div class="col-auto d-flex align-items-center" >
|
||||||
<span class="badge-ball"
|
|
||||||
*ngIf="!(!((parentLink?.subEntriesType == tocEntryType.FieldSet) && !selectedItemInLinks) || itemSelected?.id == parentLink.id ||isDragging)">
|
<ng-container *ngIf="!(!((parentLink?.subEntriesType == tocEntryType.FieldSet) && !selectedItemInLinks) || itemSelected?.id == parentLink.id ||isDragging)">
|
||||||
{{parentLink.subEntries?.length}}
|
<mat-icon class="text-danger" style="font-size: 1.4em;" *ngIf="!colorError() && parentLink?.form.invalid && colorizeInvalid && allFieldsAreTouched(parentLink?.form)">priority_high</mat-icon>
|
||||||
</span>
|
<span class="badge-ball"
|
||||||
|
>
|
||||||
|
{{parentLink.subEntries?.length}}
|
||||||
|
</span>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
|
||||||
<span style="cursor: pointer;" (click)="deleteEntry(parentLink)"
|
<span style="cursor: pointer;" (click)="deleteEntry(parentLink)"
|
||||||
|
@ -109,7 +113,8 @@
|
||||||
[overContainerId]="overContainerId"
|
[overContainerId]="overContainerId"
|
||||||
[isDragging]="isDragging"
|
[isDragging]="isDragging"
|
||||||
[draggingItemId]="draggingItemId"
|
[draggingItemId]="draggingItemId"
|
||||||
[parentRootId]="parentRootId">
|
[parentRootId]="parentRootId"
|
||||||
|
[colorizeInvalid]="colorizeInvalid">
|
||||||
</app-dataset-profile-table-of-contents-internal-section>
|
</app-dataset-profile-table-of-contents-internal-section>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { CdkDrag, CdkDragDrop, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';
|
import { CdkDrag, CdkDragDrop, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';
|
||||||
import { DOCUMENT } from '@angular/common';
|
import { DOCUMENT } from '@angular/common';
|
||||||
import { Component, EventEmitter, Inject, Input, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core';
|
import { Component, EventEmitter, Inject, Input, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core';
|
||||||
import { FormArray } from '@angular/forms';
|
import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms';
|
||||||
import { BaseComponent } from '@common/base/base.component';
|
import { BaseComponent } from '@common/base/base.component';
|
||||||
import { Foo, ToCEntry, ToCEntryType } from '../table-of-contents-entry';
|
import { Foo, ToCEntry, ToCEntryType } from '../table-of-contents-entry';
|
||||||
|
|
||||||
|
@ -31,6 +31,8 @@ export class DatasetProfileTableOfContentsInternalSection extends BaseComponent
|
||||||
@Input() draggingItemId: string;
|
@Input() draggingItemId: string;
|
||||||
@Input() parentRootId: string;
|
@Input() parentRootId: string;
|
||||||
|
|
||||||
|
@Input() colorizeInvalid:boolean = false;
|
||||||
|
|
||||||
@Input() viewOnly: boolean;
|
@Input() viewOnly: boolean;
|
||||||
// @Input() dropListGroup: Set<string> = new Set<string>();
|
// @Input() dropListGroup: Set<string> = new Set<string>();
|
||||||
@Input() dropListGroup: string[];
|
@Input() dropListGroup: string[];
|
||||||
|
@ -229,4 +231,78 @@ export class DatasetProfileTableOfContentsInternalSection extends BaseComponent
|
||||||
|
|
||||||
return tocEntryFound? tocEntryFound: null;
|
return tocEntryFound? tocEntryFound: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
colorError():boolean{
|
||||||
|
|
||||||
|
if(!this.colorizeInvalid) return false;
|
||||||
|
|
||||||
|
const form = this.parentLink.form;
|
||||||
|
if(!form || form.valid || !form.touched) return false;
|
||||||
|
|
||||||
|
const allFieldsAreTouched = this.allFieldsAreTouched(form);
|
||||||
|
|
||||||
|
//fieldset may have errros that are inside its controls and not in the fieldsetFormGroup
|
||||||
|
if(this.parentLink.type === this.tocEntryType.FieldSet && allFieldsAreTouched) return true;
|
||||||
|
|
||||||
|
if(form.errors && allFieldsAreTouched) return true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//checking form controls if have errors
|
||||||
|
let hasErrors = false;
|
||||||
|
|
||||||
|
if(allFieldsAreTouched){
|
||||||
|
if(form instanceof FormGroup){
|
||||||
|
const formGroup = form as FormGroup;
|
||||||
|
|
||||||
|
const controls = Object.keys(formGroup.controls);
|
||||||
|
|
||||||
|
controls.forEach(control=>{
|
||||||
|
if(formGroup.get(control).errors){
|
||||||
|
hasErrors = true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasErrors;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
allFieldsAreTouched(aControl:AbstractControl){//auto na testaroume
|
||||||
|
|
||||||
|
if(!aControl|| aControl.untouched) return false;
|
||||||
|
|
||||||
|
if(aControl instanceof FormControl){
|
||||||
|
return aControl.touched;
|
||||||
|
}else if(aControl instanceof FormGroup){
|
||||||
|
const controlKeys = Object.keys((aControl as FormGroup).controls);
|
||||||
|
let areAllTouched = true;
|
||||||
|
controlKeys.forEach(key=>{
|
||||||
|
if(!this.allFieldsAreTouched(aControl.get(key))){
|
||||||
|
areAllTouched = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// const areAllTouched = controlKeys.reduce((acc, key)=>acc && this._allFieldsAreTouched(aControl.get(key)), true);
|
||||||
|
return areAllTouched;
|
||||||
|
|
||||||
|
}else if(aControl instanceof FormArray){
|
||||||
|
const controls = (aControl as FormArray).controls;
|
||||||
|
// const areAllTouched = controls.reduce((acc, control)=>acc && this._allFieldsAreTouched(control), true);
|
||||||
|
let areAllTouched = true;
|
||||||
|
// controls.reduce((acc, control)=>acc && this._allFieldsAreTouched(control), true);
|
||||||
|
controls.forEach(control=>{
|
||||||
|
if(!this.allFieldsAreTouched(control)){
|
||||||
|
areAllTouched = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return areAllTouched;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -22,6 +22,7 @@
|
||||||
[draggingItemId]="draggingItemId"
|
[draggingItemId]="draggingItemId"
|
||||||
[parentRootId]="ROOT_ID"
|
[parentRootId]="ROOT_ID"
|
||||||
style="padding-right: 1em;"
|
style="padding-right: 1em;"
|
||||||
|
[colorizeInvalid]="colorizeInvalid"
|
||||||
></app-dataset-profile-table-of-contents-internal-section>
|
></app-dataset-profile-table-of-contents-internal-section>
|
||||||
|
|
||||||
<!-- <span *ngFor="let link of links; let i = index" (click)="toggle(link); goToStep(link);" class="docs-link mt-0">
|
<!-- <span *ngFor="let link of links; let i = index" (click)="toggle(link); goToStep(link);" class="docs-link mt-0">
|
||||||
|
|
|
@ -50,6 +50,7 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn
|
||||||
@Output() dataNeedsRefresh = new EventEmitter<void>();
|
@Output() dataNeedsRefresh = new EventEmitter<void>();
|
||||||
|
|
||||||
@Input() itemSelected: ToCEntry;
|
@Input() itemSelected: ToCEntry;
|
||||||
|
@Input() colorizeInvalid: boolean = false;
|
||||||
|
|
||||||
// @Input() set itemSelected(entry:ToCEntry){
|
// @Input() set itemSelected(entry:ToCEntry){
|
||||||
// this._itemSelected = entry;
|
// this._itemSelected = entry;
|
||||||
|
|
|
@ -76,11 +76,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::ng-deep .mat-form-field-wrapper {
|
:host ::ng-deep .mat-form-field-wrapper {
|
||||||
background-color: white !important;
|
background-color: white !important;
|
||||||
padding-bottom: 0 !important;
|
padding-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix {
|
:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix {
|
||||||
padding: 0.3rem 0rem 0.6rem 0rem !important;
|
padding: 0.3rem 0rem 0.6rem 0rem !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
padding: 0.4rem;
|
padding: 0.4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
::ng-deep .mat-form-field-wrapper {
|
:host ::ng-deep .mat-form-field-wrapper {
|
||||||
background-color: white !important;
|
background-color: white !important;
|
||||||
padding-bottom: 0 !important;
|
padding-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix {
|
:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix {
|
||||||
padding: 0.3rem 0rem 0.6rem 0rem !important;
|
padding: 0.3rem 0rem 0.6rem 0rem !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@
|
||||||
background-color: #2e74b649;
|
background-color: #2e74b649;
|
||||||
}
|
}
|
||||||
|
|
||||||
::ng-deep .mat-form-field-wrapper {
|
:host ::ng-deep .mat-form-field-wrapper {
|
||||||
background-color: white !important;
|
background-color: white !important;
|
||||||
padding-bottom: 0 !important;
|
padding-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
<div class="page-title">About</div>
|
<div class="page-title">About</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col pt-5 pb-3">
|
<div class="col pt-5 pb-3">
|
||||||
<div class="row title-4">How it works</div>
|
<div class="row title-4">What it is</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="pt-3">
|
<p class="pt-3">
|
||||||
ARGOS is the joint effort of OpenAIRE and EUDAT to deliver an open platform for Data Management Planning
|
ARGOS is the joint effort of OpenAIRE and EUDAT to deliver an open platform for Data Management Planning
|
||||||
|
@ -102,6 +102,322 @@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col pt-0 pb-3">
|
||||||
|
<div class="row title-4">How it works</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<p class="pt-3">
|
||||||
|
Research Data Management (RDM) is a vital part of Open Science that lies at the heart of European
|
||||||
|
research for it increases the quality of produced data and ensures integrity and preservation of
|
||||||
|
research outputs. RDM refers to activities undertaken throughout a research lifecycle, spanning from
|
||||||
|
data collection to data process and analysis. Open Access and FAIR principles govern data activities
|
||||||
|
today to foster data discovery, distribution and exploitation, thus accelerating scientific breakthroughs.
|
||||||
|
Coronavirus vaccine is the ultimate example of what can be achieved in a short amount of time when
|
||||||
|
data are openly shared across the global scientific community. RDM urges scientific practices to be
|
||||||
|
adjusted in ways that enable data understandability and re-usability from both humans and machines;
|
||||||
|
services and tools are realised or re-designed to support the shift towards Open and FAIR research outputs.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="pt-2">
|
||||||
|
Argos is a service for creating and publishing plans that describe data management activities,
|
||||||
|
commonly known as Data Management Plans (DMPs). The plans are produced as machine-actionable
|
||||||
|
outputs (ma-DMPs), in the form of rich text documents, following Open and FAIR practices and are
|
||||||
|
published in Zenodo. Argos supports RDM at the beginning of research for planning data activities to
|
||||||
|
be performed, as well as throughout and at the end of research for documenting the steps and
|
||||||
|
processes followed according to institutional or funder RDM requirements.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="col pt-5 pb-3">
|
||||||
|
<div class="row title-5">Dmp Lifecycle</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="pt-2">
|
||||||
|
Argos follows a full DMP publication lifecycle. Users create their DMPs and add descriptions for their
|
||||||
|
datasets. DMPs and Datasets are by default created in private mode and can be shared with
|
||||||
|
colleagues to facilitate the writing process. Datasets are added in DMPs per type and / or per scientific
|
||||||
|
discipline that they concern. That way information is well-organized and it is easier to distinguish
|
||||||
|
relevant information from a pool of data activities detailed in a single DMP record. Once created, DMPs
|
||||||
|
and their Datasets are in draft status and are treated as living documents in the Argos environment,
|
||||||
|
meaning that they can be versioned and updated at any time. When ready, users can validate and
|
||||||
|
finalize their DMPs, including corresponding Datasets, and change their visibility status from private to
|
||||||
|
open. Open DMPs in Argos are available and accessible to all from the Public Dashboards. To close the
|
||||||
|
DMP lifecycle, Argos integrates Zenodo, so users are able to publish their DMPs directly from its environment.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="col-12" style="margin-top: 121px; ">
|
||||||
|
|
||||||
|
<div style="position: relative;" id="lifecycle-img-container">
|
||||||
|
|
||||||
|
<img id="img-coloured" class="image-coloured img-sharp" src="../assets/img/lifecycle_full_color.png" alt="Dmp Lifecycle">
|
||||||
|
<img class="image-grey img-sharp" src="../assets/img/lifecycle_full_color.png" alt="Dmp Lifecycle">
|
||||||
|
<!-- <img class="preface-img" src="../assets/img/lifecycle_full_color.png" alt=""> -->
|
||||||
|
|
||||||
|
<!-- EDITORS-DRAFT -->
|
||||||
|
<div class="red-dot navigate-dot" data-navigate-to="multiple-navigation-1" data-clip-mode="clip-draft" style="top:24.7%; left: 23.5%; cursor: pointer;">
|
||||||
|
<div class="inner-red-dot"></div>
|
||||||
|
</div>
|
||||||
|
<!-- VALIDATED -->
|
||||||
|
<div class="red-dot navigate-dot" data-navigate-to="navigation-tab-2" data-clip-mode="clip-validated" style="top:19%; left: 56.5% ; cursor: pointer;">
|
||||||
|
<div class="inner-red-dot"></div>
|
||||||
|
</div>
|
||||||
|
<!-- FINALIZED -->
|
||||||
|
<div class="red-dot navigate-dot" data-navigate-to="navigation-tab-3" data-clip-mode="clip-finalized" style="top:39%; right: 19.7%; cursor: pointer;">
|
||||||
|
<div class="inner-red-dot"></div>
|
||||||
|
</div>
|
||||||
|
<!-- DMP -->
|
||||||
|
<div class="red-dot navigate-dot" data-navigate-to="navigation-tab-4" data-clip-mode="clip-dmp" style="top:67%; right: -0.3%; cursor: pointer;">
|
||||||
|
<div class="inner-red-dot"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-12" style="margin-top: 121px; ">
|
||||||
|
<div class="options-menu" id="options-menu">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-7">
|
||||||
|
<ul class="nav nav-tabs">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" data-toggle="tab" id="multiple-navigation-1" data-img-fragment href="#create_and_add">Create & Add</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" data-toggle="tab" id="navigation-tab-2" data-img-fragment="img-fragment-validated-is" href="#validate">Validate</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" data-toggle="tab" id="navigation-tab-3" data-img-fragment="img-fragment-finalized-is" href="#finalize">Finalize</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" data-toggle="tab" id="navigation-tab-4" data-img-fragment="img-fragment-dmp-out" href="#dmp">Ma-Dmp Outputs</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="tab-content">
|
||||||
|
<div role="tabpanel" class="tab-pane show active" id="create_and_add">
|
||||||
|
<div class="nav-tab-inner-text">
|
||||||
|
Argos consists of two main editors: the DMP editor and the Dataset editor.
|
||||||
|
Both editors integrate OpenAIRE and ESOC APIs to ease the writing process and
|
||||||
|
help create links with other outputs. Also, the editors incorporate a mechanism
|
||||||
|
to enable compliance with the <span style="color: #23BCBA;">RDA DMP Common Standard</span>.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- nested naviation -->
|
||||||
|
<ul class="nav nav-pills" style="padding-top: 2em;">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link sub-navigation-button active" data-toggle="tab" data-img-fragment="img-fragment-dmp-editor" href="#dmp_editor_pane">DMP Editor</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link sub-navigation-button" data-toggle="tab" data-img-fragment="img-fragment-dataset-editor" href="#dataset_editor_pane">Dataset Editor</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="tab-content">
|
||||||
|
<div role="tabpanel" class="tab-pane show active" id="dmp_editor_pane">
|
||||||
|
<div class="nav-tab-inner-text">
|
||||||
|
The DMP editor embeds the Dataset editor to provide a holistic view of a project's
|
||||||
|
scope, beneficiaries and data activities. Therefore, it guides users step-by-step
|
||||||
|
into adding appropriate administrative information, selecting templates that
|
||||||
|
correspond to research needs and requirements, and describing data activities.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div role="tabpanel" class="tab-pane fade" id="dataset_editor_pane">
|
||||||
|
<div class="nav-tab-inner-text">
|
||||||
|
The Dataset editor concers information that is solely for datasets, such as how Open
|
||||||
|
and FAIR principles have been applied to them throughout data management activities.
|
||||||
|
It is the place to select RDM templates and start answering data questions. Moreover,
|
||||||
|
the Dataset editor can be used independently at any time when new data are produced
|
||||||
|
throughout a project lifetime. That allows users to quickly describe their new data and
|
||||||
|
link them to existing DMPs in their dashboard.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div role="tabpanel" class="tab-pane fade" id="validate">
|
||||||
|
<div class="nav-tab-inner-text">
|
||||||
|
Information contained in DMPs should be validated before being published.
|
||||||
|
Validation at this stage checks for mandatory fields in the DMP and reports back
|
||||||
|
when necessary information has not been provided by the user. Once the user
|
||||||
|
add all necessary information, validation is successful.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div role="tabpanel" class="tab-pane fade" id="finalize">
|
||||||
|
<div class="nav-tab-inner-text">
|
||||||
|
DMPs finalization is the process of locking working drafts of DMPs and publishing
|
||||||
|
them, either just on the Argos platform or on Zenodo where they alse get DOI.
|
||||||
|
It is possible for datasets contained in DMPs to be finalized independently. That
|
||||||
|
is important especially for datasets that can not be shared openly, such as those
|
||||||
|
of sensitive content. Before publishing DMPs, sensitive datasets can be detached
|
||||||
|
from its core. That way data descriptions are equally protected form being openly
|
||||||
|
shared along with the DMP content.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div role="tabpanel" class="tab-pane fade" id="dmp">
|
||||||
|
<div class="nav-tab-inner-text">
|
||||||
|
Argos ma-DMP outputs carry rich information that exceeds metadata provided in
|
||||||
|
DMPs whey they are created and deposited as plain texts. Argos applies the RDA
|
||||||
|
DMP Common Standard to comply with global practices on the machine-actinability.
|
||||||
|
This is important for two reasons:
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row pt-2 nav-tab-inner-text">
|
||||||
|
<div class="col-auto" style="width:2.5em;color: #129D99;">I.</div>
|
||||||
|
<div class="col">It enables researchers to switch platforms at anytime and seamlessly work</div>
|
||||||
|
</div>
|
||||||
|
<div class="row nav-tab-inner-text pt-4">
|
||||||
|
<div class="col-auto " style="width:2.5em;color: #129D99;">II.</div>
|
||||||
|
<div class="col">Adds to the Scholarly Communication ecology and pushes for best practices
|
||||||
|
in neighbour areas to keep up pace, e.g. deposit in repositories and
|
||||||
|
classification of DMPs as data management plans and not as publications,</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Images -->
|
||||||
|
<div class="col">
|
||||||
|
<img src="../assets/img/3_dmp_editor.png" class="img-fragment-step opacity-1 img-sharp" id="img-fragment-dmp-editor" alt="DMP editor">
|
||||||
|
<img src="../assets/img/dmp_out.png" class="img-fragment-step img-sharp" id="img-fragment-dmp-out" alt="DMP outputs">
|
||||||
|
<img src="../assets/img/4_dataset_editor.png" class="img-fragment-step img-sharp" id="img-fragment-dataset-editor" alt="Dataset editor">
|
||||||
|
<img src="../assets/img/6_validated_is.png" class="img-fragment-step img-sharp" id="img-fragment-validated-is" alt="Validated DMP">
|
||||||
|
<img src="../assets/img/8_finalized_is.png" class="img-fragment-step img-sharp" id="img-fragment-finalized-is" alt="Finalized DMP">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-small" style="margin-top: 7em;">
|
||||||
|
|
||||||
|
<div class="col pt-5 pb-3" >
|
||||||
|
<div class="row title-5">Argos in the OpenAIRE ecosystem</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="pt-2">
|
||||||
|
Argos is hooked on the OpenAIRE ecosystem comprising a diverse set of services and tools for Open
|
||||||
|
Science and Scholarly Communication, from technical to educational and consultative in nature.
|
||||||
|
OpenAIRE services and tools are provided for immediate consumption by end-users, i.e. researchers,
|
||||||
|
research communities, research performing or funding organizations and policymakers. Moreover,
|
||||||
|
OpenAIRE services are exploitable by software engineers. Argos integrates other OpenAIRE services to
|
||||||
|
maximise efficiency of operations in Open and FAIR ecosystems and to make connections that add
|
||||||
|
value in Open Science at global scale. OpenAIRE services that Argos connects to are:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="container">
|
||||||
|
<div class="col" style="margin-top: 121px; position: relative;">
|
||||||
|
<img src="../assets/img/openaire_ecosystem.png" style="width: 100%; height: auto;" alt="">
|
||||||
|
|
||||||
|
<!-- apis -->
|
||||||
|
<div class="red-dot" style="top:8%; left: 22%"
|
||||||
|
data-toggle="tooltip" data-placement="bottom"
|
||||||
|
title='<h2>APIs</h2>
|
||||||
|
Utilises OpenAIRE pool of resources
|
||||||
|
and APIs to provide quick input to
|
||||||
|
users (e.g. CORDIS, Datacite, re3data,
|
||||||
|
ORCID, etc).'
|
||||||
|
><div class="inner-red-dot"></div>
|
||||||
|
</div>
|
||||||
|
<!-- zenodo -->
|
||||||
|
<div class="red-dot" style="top:10%; left: 54%"
|
||||||
|
data-toggle="tooltip" data-placement="bottom"
|
||||||
|
title='<h2>Zenodo</h2>
|
||||||
|
Closes the DMP lifecycle by offering a
|
||||||
|
DMP platform to expose DMP for
|
||||||
|
their immediate publication in an
|
||||||
|
open and FAIR manner (DMPs are
|
||||||
|
assigned DOIs, get licenses, follow
|
||||||
|
versioning mechanism etc).'
|
||||||
|
><div class="inner-red-dot"></div>
|
||||||
|
</div>
|
||||||
|
<!-- provide -->
|
||||||
|
<div class="red-dot" style="top:48.2%; left: 2.5%"
|
||||||
|
data-toggle="tooltip" data-placement="bottom"
|
||||||
|
title='<h2>Provide</h2>
|
||||||
|
Sends notifications to repository
|
||||||
|
managers of the OpenAIRE network
|
||||||
|
when datasets described in Argos
|
||||||
|
ma-DMPs are claimed to be
|
||||||
|
deposited in their repositories.'
|
||||||
|
><div class="inner-red-dot"></div>
|
||||||
|
</div>
|
||||||
|
<!-- monitor -->
|
||||||
|
<div class="red-dot" style="top:60.2%; right: 2.5%"
|
||||||
|
data-toggle="tooltip" data-placement="bottom"
|
||||||
|
title="<h2>Monitor</h2>
|
||||||
|
Collects contextualised information
|
||||||
|
about ma-DMPs to understand how
|
||||||
|
RDM and DMPs evolve in time and
|
||||||
|
support decision making of funders
|
||||||
|
and policymakers."
|
||||||
|
>
|
||||||
|
<div class="inner-red-dot"></div>
|
||||||
|
</div>
|
||||||
|
<!-- graph -->
|
||||||
|
<div class="red-dot" style="bottom:14.2%; left: 40.5%"
|
||||||
|
data-toggle="tooltip" data-placement="bottom"
|
||||||
|
title='<h2>Research Graph</h2>
|
||||||
|
Enriches the ma-DMP entity in the
|
||||||
|
OpenAIRE knowledge graph for open
|
||||||
|
scholarly communication information
|
||||||
|
and creates relationships with other
|
||||||
|
research outputs and links, adding in
|
||||||
|
the OpenAIRE LOD ecology.'
|
||||||
|
>
|
||||||
|
<div class="inner-red-dot"></div>
|
||||||
|
</div>
|
||||||
|
<!-- explore -->
|
||||||
|
<div class="red-dot" style="bottom:1%; left: 56%" data-toggle="tooltip" data-placement="bottom"
|
||||||
|
title='
|
||||||
|
<h2>Explore</h2>
|
||||||
|
Adds ma-DMPs in the OpenAIRE
|
||||||
|
search engine and makes them
|
||||||
|
findable under a dedicated resource
|
||||||
|
type category "data managment
|
||||||
|
plan".'>
|
||||||
|
<div class="inner-red-dot"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-small">
|
||||||
|
|
||||||
|
<p class="mt-3 pt-4" style="font-weight: bolder;" >Useful Resources</p>
|
||||||
|
<div class="resources-list">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-auto" style="padding-top: .5em;">
|
||||||
|
<div class="blue-dot"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col p-0">
|
||||||
|
Argos RDA output adoption:
|
||||||
|
<br>
|
||||||
|
<a href="https://www.rd-alliance.org/implementing-dmp-common-standard-argos-tool-madmps">
|
||||||
|
https://www.rd-alliance.org/implementing-dmp-common-standard-argos-tool-madmps
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row" >
|
||||||
|
<div class="col-auto" style="padding-top: .5em;">
|
||||||
|
<div class="blue-dot"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col p-0">
|
||||||
|
Webinar:
|
||||||
|
<br>
|
||||||
|
<a href="https://www.rd-alliance.org/implementing-dmp-common-standard-argos-tool-madmps">
|
||||||
|
https://www.rd-alliance.org/implementing-dmp-common-standard-argos-tool-madmps
|
||||||
|
</a>
|
||||||
|
(starts at 30:15)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<p class="pt-2">
|
<p class="pt-2">
|
||||||
More details on ARGOS as registered in the OpenAIRE services catalogue is available here:
|
More details on ARGOS as registered in the OpenAIRE services catalogue is available here:
|
||||||
<a href="http://catalogue.openaire.eu/service/openaire.argos"><u>http://catalogue.openaire.eu/service/openaire.argos</u></a>.
|
<a href="http://catalogue.openaire.eu/service/openaire.argos"><u>http://catalogue.openaire.eu/service/openaire.argos</u></a>.
|
||||||
|
@ -168,6 +484,8 @@
|
||||||
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
|
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
|
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
|
||||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
|
||||||
|
<!-- Js for this file -->
|
||||||
|
<script src="../js/how-it-works.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
After Width: | Height: | Size: 158 KiB |
After Width: | Height: | Size: 190 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 330 KiB |
After Width: | Height: | Size: 789 KiB |
|
@ -150,11 +150,15 @@ p a {
|
||||||
color: #212121;
|
color: #212121;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title-1, .title-2, .title-3, .title-4 {
|
.title-1, .title-2, .title-3, .title-4, .title-5 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-size: 2.37rem;
|
font-size: 2.37rem;
|
||||||
font-family: 'Roboto', sans-serif;
|
font-family: 'Roboto', sans-serif;
|
||||||
}
|
}
|
||||||
|
.title-5{
|
||||||
|
color: #129D99;
|
||||||
|
font: normal normal 300 27px/35px Roboto;
|
||||||
|
}
|
||||||
|
|
||||||
.page-title {
|
.page-title {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -379,3 +383,220 @@ hr {
|
||||||
.ext-link-icon {
|
.ext-link-icon {
|
||||||
margin-left: .2rem;
|
margin-left: .2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ABOUT HOW-IT-WORKDS PAGE REDESIGN */
|
||||||
|
|
||||||
|
.red-dot{
|
||||||
|
width: 27px;
|
||||||
|
height: 27px;
|
||||||
|
z-index: 20;
|
||||||
|
border: 3px solid #ee254091;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.inner-red-dot{
|
||||||
|
background-color: #EE2540;
|
||||||
|
width: 19px;
|
||||||
|
height: 19px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip >.tooltip-inner {
|
||||||
|
padding: 2em;
|
||||||
|
background-color: #FFF;
|
||||||
|
color: black;
|
||||||
|
box-shadow: 0px 3px 6px #0000001A;
|
||||||
|
text-align: start;
|
||||||
|
max-width: 25em;
|
||||||
|
}
|
||||||
|
.tooltip .show{
|
||||||
|
opacity: 1 !important;
|
||||||
|
}
|
||||||
|
.tooltip h2{
|
||||||
|
color: #23BCBA;
|
||||||
|
font-size: 1.3rem;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip.bs-tooltip-top .arrow:before {
|
||||||
|
border-top-color: #fff
|
||||||
|
}
|
||||||
|
.tooltip.bs-tooltip-right .arrow:before {
|
||||||
|
border-right-color: #fff;
|
||||||
|
}
|
||||||
|
.tooltip.bs-tooltip-left .arrow:before {
|
||||||
|
border-left-color: #fff;
|
||||||
|
}
|
||||||
|
.tooltip.bs-tooltip-bottom .arrow:before {
|
||||||
|
border-bottom-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip.show {
|
||||||
|
opacity: 1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-coloured {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
display: block;
|
||||||
|
z-index: 1;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0px;
|
||||||
|
clip-path: polygon(0% 0%);
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 200ms 50ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-grey {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
display: block;
|
||||||
|
z-index: 0;
|
||||||
|
filter: grayscale(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.clip-draft{
|
||||||
|
clip-path:polygon(41.84% 0.0%, 40.13% 46.41%, 40.90% 100%, 0.0% 100.0%, 0.0% 0.0%);
|
||||||
|
}
|
||||||
|
.clip-validated{
|
||||||
|
clip-path: polygon(41.84% 0%, 40.13% 46.41%, 40.9% 100%, 68.32% 100.0%, 68.32% 0%);
|
||||||
|
}
|
||||||
|
.clip-finalized{
|
||||||
|
clip-path: polygon(58.86% 0.0%, 58.74% 100.0%, 88.65% 100.0%, 88.65% 0.0%);
|
||||||
|
}
|
||||||
|
.clip-dmp{
|
||||||
|
clip-path: polygon(80.26% 0.0%, 80.13% 100.0%, 100.00% 100.0%, 100.0% 0.0%);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .preface-img{
|
||||||
|
width: 100%; height: auto; display: block; z-index: 2;
|
||||||
|
position: absolute;
|
||||||
|
top:0;
|
||||||
|
left: 0;
|
||||||
|
opacity: 1;
|
||||||
|
filter: grayscale(100%);
|
||||||
|
|
||||||
|
transition-property: opacity;
|
||||||
|
transition-duration: 300ms;
|
||||||
|
transition-delay: 50ms;
|
||||||
|
transition-timing-function: ease-in;
|
||||||
|
} */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.options-menu{
|
||||||
|
box-shadow: 0px 6px 15px #0000001A;
|
||||||
|
border-radius: 36px;
|
||||||
|
padding: 3.2em 4.1em !important;
|
||||||
|
min-height: 30em;
|
||||||
|
}
|
||||||
|
/* First level of tabs */
|
||||||
|
.options-menu .nav-tabs{
|
||||||
|
border-color: transparent !important;
|
||||||
|
color: #212121;
|
||||||
|
margin-bottom: 1.2em;
|
||||||
|
}
|
||||||
|
.options-menu .nav-tabs .nav-item .nav-link{
|
||||||
|
font-weight: normal;
|
||||||
|
border-radius: 0px !important;
|
||||||
|
padding: 0.2rem 0rem !important;
|
||||||
|
}
|
||||||
|
.options-menu .nav-tabs .nav-item:first-child .nav-link{
|
||||||
|
margin-left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.options-menu .nav-tabs .nav-link.active{
|
||||||
|
font-weight: bold;
|
||||||
|
border-left:0px!important;
|
||||||
|
border-top:0px !important;
|
||||||
|
border-right:0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.options-menu .nav-tabs .nav-link:hover:not(.active){
|
||||||
|
border-color: transparent !important;
|
||||||
|
}
|
||||||
|
.options-menu .nav-tabs .nav-link{
|
||||||
|
opacity: 0.5;
|
||||||
|
transition: opacity 200ms 50ms ease-out;
|
||||||
|
}
|
||||||
|
.options-menu .nav-tabs .nav-link:hover{
|
||||||
|
color: #212121;
|
||||||
|
}
|
||||||
|
.options-menu .nav-tabs .nav-link.active{
|
||||||
|
border-bottom: 3px solid black !important;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* nested tabs */
|
||||||
|
.options-menu .nav-pills{
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
.options-menu .nav-pills .nav-link{
|
||||||
|
padding: .3rem 1.3rem !important;
|
||||||
|
font-weight: normal;
|
||||||
|
border-radius: 40px;
|
||||||
|
border: 1px solid #1A1A1A;
|
||||||
|
color: #1A1A1A;
|
||||||
|
opacity: 0.5;
|
||||||
|
/* transition: opacity 200ms 50ms ease-out; */
|
||||||
|
}
|
||||||
|
.options-menu .nav-pills .nav-link.active{
|
||||||
|
background-color: #129D99;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #F9FBFC;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
.options-menu .nav-pills .nav-item:first-child .nav-link{
|
||||||
|
margin-left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-fragment-step{
|
||||||
|
width: auto;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height:23em;
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 200ms 50ms ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opacity-0{
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.opacity-1{
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab-inner-text{
|
||||||
|
text-align: left;
|
||||||
|
font-size: 0.9em;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
color: #1A1A1A;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
.resources-list{
|
||||||
|
margin-bottom: 9em;
|
||||||
|
}
|
||||||
|
/* .resources-list li::marker{
|
||||||
|
font-size: 1.5em;
|
||||||
|
color: #23BCBA;
|
||||||
|
} */
|
||||||
|
.blue-dot{
|
||||||
|
width: 0.7em;
|
||||||
|
height: 0.7em;
|
||||||
|
background-color: #23BCBA;
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
}
|
||||||
|
.img-sharp{
|
||||||
|
image-rendering: -webkit-optimize-contrast;
|
||||||
|
image-rendering: -moz-crisp-edges;
|
||||||
|
}
|
||||||
|
/* END OF ABOUT HOW-IT-WORKDS PAGE REDESIGN */
|
|
@ -0,0 +1,105 @@
|
||||||
|
|
||||||
|
jQuery(function(){
|
||||||
|
const $img_coloured = $('#img-coloured');
|
||||||
|
const $img_preface = $('.preface-img');
|
||||||
|
const $action_dots = $('[data-clip-mode]');
|
||||||
|
const $lifecycle_img_container = $('#lifecycle-img-container');
|
||||||
|
let current_mode = null;
|
||||||
|
|
||||||
|
const mutationObserver = new MutationObserver(function(mutations) {
|
||||||
|
mutations.forEach(mutation=>{
|
||||||
|
if(mutation.attributeName === 'class'){//class changed
|
||||||
|
const isActive = mutation.target.className.includes('active');
|
||||||
|
const target_image_id = mutation.target.attributes['data-img-fragment'].value;
|
||||||
|
|
||||||
|
if(target_image_id && target_image_id.length){
|
||||||
|
|
||||||
|
|
||||||
|
//dummy fix clean all opacities
|
||||||
|
$('.img-fragment-step').each(function(){
|
||||||
|
$(this).removeClass('opacity-1');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if(isActive){
|
||||||
|
$("#"+target_image_id).addClass('opacity-1');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(mutation.target.id == 'multiple-navigation-1' && isActive){ //search children
|
||||||
|
|
||||||
|
const $target_nav_links = $('.sub-navigation-button');
|
||||||
|
$target_nav_links.removeClass('active');
|
||||||
|
$target_nav_links.first().addClass('active');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
$('[data-toggle="tooltip"]').tooltip({html:true})
|
||||||
|
})
|
||||||
|
|
||||||
|
$action_dots.on('mouseenter', function(){
|
||||||
|
const mode = $(this).attr('data-clip-mode');
|
||||||
|
current_mode = mode;
|
||||||
|
|
||||||
|
$img_coloured.addClass(mode);
|
||||||
|
// $img_preface.addClass('opacity-0');
|
||||||
|
$img_coloured.addClass('opacity-1');
|
||||||
|
|
||||||
|
$action_dots.each(function(){
|
||||||
|
if($(this).attr('data-clip-mode') != mode){
|
||||||
|
$(this).addClass('d-none');
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
$action_dots.on('mouseleave', function(){
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$lifecycle_img_container.on('mouseleave', function(){
|
||||||
|
if(current_mode){
|
||||||
|
const mode = current_mode;
|
||||||
|
|
||||||
|
|
||||||
|
//give animation time to complete
|
||||||
|
setTimeout(() => {
|
||||||
|
$img_coloured.removeClass(mode);
|
||||||
|
$action_dots.each(function(){
|
||||||
|
$(this).removeClass('d-none');
|
||||||
|
});
|
||||||
|
}, 300);
|
||||||
|
$img_coloured.removeClass('opacity-1');
|
||||||
|
// $img_preface.removeClass('opacity-0');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
current_mode = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$("[data-img-fragment]").each(function(){
|
||||||
|
const nodeElement = $(this)[0];
|
||||||
|
|
||||||
|
mutationObserver.observe(nodeElement ,{attributes:true});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$('.navigate-dot').on('click', function(){
|
||||||
|
|
||||||
|
const navigate_to = $(this).attr('data-navigate-to');
|
||||||
|
|
||||||
|
if(navigate_to){
|
||||||
|
const $navigate_to = $('#'+navigate_to);
|
||||||
|
$navigate_to.click();
|
||||||
|
const offset = $('#options-menu').offset().top - 120;
|
||||||
|
window.scrollTo({top:offset, behavior:'smooth'})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|