connect-admin/src/app/pages/content-providers/criteria/criteria.component.ts

239 lines
8.2 KiB
TypeScript

import {
AfterViewInit,
ChangeDetectorRef,
Component,
Input,
OnChanges,
OnDestroy,
OnInit,
SimpleChanges
} from '@angular/core';
import {EnvProperties} from '../../../openaireLibrary/utils/properties/env-properties';
import {Constraint, Criteria, SelectionCriteria} from '../../../openaireLibrary/utils/entities/contentProvider';
import {AbstractControl, UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms';
import {properties} from "../../../../environments/environment";
import {MatSlideToggleChange} from "@angular/material/slide-toggle";
import {HelperFunctions} from "../../../openaireLibrary/utils/HelperFunctions.class";
import {CriteriaUtils} from "../criteria-utils";
import {NotificationHandler} from "../../../openaireLibrary/utils/notification-handler";
import {OpenaireEntities} from "../../../openaireLibrary/utils/properties/searchFields";
import {ISVocabulariesService} from "../../../openaireLibrary/utils/staticAutoComplete/ISVocabularies.service";
import {Subscription} from "rxjs";
@Component({
selector: 'criteria',
templateUrl: 'criteria.component.html',
styleUrls: ['criteria.component.less']
})
export class CriteriaComponent implements OnInit, OnChanges, AfterViewInit, OnDestroy {
@Input()
public entityType: string = 'filter';
@Input()
public entityTypePlural: string = 'filters';
@Input()
public selectionCriteria: SelectionCriteria;
@Input()
public height: number = 0;
public criteriaHeight: number = 0;
public selectionCriteriaForm: UntypedFormGroup;
public properties: EnvProperties = properties;
public criteriaUtils: CriteriaUtils = new CriteriaUtils();
public fos: string[] = [];
public sdg: string[] = [];
public loading = true;
public openaireEntities = OpenaireEntities;
private subscriptions: any[] = [];
constructor(private cdr: ChangeDetectorRef, private vocabulariesService: ISVocabulariesService,
private fb: UntypedFormBuilder) {
}
ngOnInit() {
this.loading = false;
this.subscriptions.push(this.vocabulariesService.getVocabularyByType('fos', null, properties).subscribe((fos: any[]) => {
this.fos = fos.map(element => element.id);
}));
this.subscriptions.push(this.vocabulariesService.getVocabularyByType('sdg', null, properties).subscribe((sdg: any[]) => {
this.sdg = sdg.map(element => element.id);
}));
}
ngOnChanges(changes: SimpleChanges) {
if(changes.selectionCriteria){
this.reset();
}
this.calculateMaxHeight();
}
ngAfterViewInit() {
this.calculateMaxHeight();
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscription) {
subscription.unsubscribe();
}
});
}
calculateMaxHeight() {
if(this.height) {
if(this.height > 0) {
/* Element height - margins(20 + 20) - button height(42) */
this.criteriaHeight = this.height - 40 - 42;
this.cdr.detectChanges();
}
}
}
reset() {
this.selectionCriteriaForm = this.fb.group({
criteria: this.fb.array([])
});
if (this.selectionCriteria?.criteria) {
this.selectionCriteria.criteria.forEach(criterion => {
let constraintArray: UntypedFormArray = this.fb.array([]);
criterion.constraint.forEach(constraint => {
constraintArray.push(this.fb.group({
field: this.fb.control(constraint.field, Validators.required),
verb: this.fb.control(this.removeSuffix(constraint.verb), Validators.required),
value: this.fb.control(constraint.value, Validators.required),
verb_suffix: this.fb.control(this.getSuffix(constraint.verb))
}));
});
this.criteria.push(this.fb.group({
constraint: constraintArray
}));
});
}
}
get disabled() {
return this.loading || !this.dirty || this.selectionCriteriaForm.invalid;
}
public get criteria(): UntypedFormArray {
return this.selectionCriteriaForm.get('criteria') as UntypedFormArray;
}
public getConstraint(i: number): UntypedFormArray {
return this.criteria.at(i).get('constraint') as UntypedFormArray;
}
public addCriteria() {
let constraintArray: UntypedFormArray = this.fb.array([
this.fb.group({
field: this.fb.control('', Validators.required),
verb: this.fb.control('contains', Validators.required),
value: this.fb.control('', Validators.required),
verb_suffix: this.fb.control('_caseinsensitive')
})
]);
this.criteria.push(this.fb.group({constraint: constraintArray}));
this.cdr.detectChanges();
document.getElementById('criterion-' + (this.criteria.length - 1).toString()).scrollIntoView({behavior: 'smooth'});
}
public addConstraint(i: number) {
let constraintArray: UntypedFormArray = this.criteria.at(i).get('constraint') as UntypedFormArray;
constraintArray.push(this.fb.group({
field: this.fb.control('', Validators.required),
verb: this.fb.control('contains', Validators.required),
value: this.fb.control('', Validators.required),
verb_suffix: this.fb.control('_caseinsensitive')
}));
this.cdr.detectChanges();
}
public removeConstraint(i: number, j: number) {
let constraintArray: UntypedFormArray = this.criteria.at(i).get('constraint') as UntypedFormArray;
constraintArray.removeAt(j);
if (constraintArray.length === 0) {
this.criteria.removeAt(i);
}
this.cdr.detectChanges();
}
get criteriaArray(): Criteria[] {
return (this.selectionCriteria?.criteria) ? this.selectionCriteria?.criteria : [];
}
get dirty() {
if (!this.selectionCriteria && !this.criteria) {
return false;
} else if (this.criteria.length !== this.criteriaArray.length) {
return true;
} else {
return this.criteriaArray.filter((criterion, i) => {
if (criterion.constraint.length !== this.getConstraint(i).length) {
return true;
} else {
let temp = this.getConstraint(i).value;
return criterion.constraint.filter((constraint, j) => {
return constraint.field !== temp[j].field || constraint.verb !== (temp[j].verb + temp[j].verb_suffix) || constraint.value !== temp[j].value;
}).length > 0;
}
}).length > 0;
}
}
save(callback: (selectionCriteria) => void = null) {
if (this.selectionCriteriaForm.valid) {
this.loading = true;
callback(this.parseForm(this.selectionCriteriaForm.value));
}
}
handeError(message, error = null) {
console.error(error);
NotificationHandler.rise(message, 'danger');
}
caseSensitive(event: MatSlideToggleChange, constraint: AbstractControl) {
if (event.checked) {
constraint.get('verb_suffix').setValue('');
} else {
constraint.get('verb_suffix').setValue('_caseinsensitive');
}
}
removeSuffix(verb: string) {
return verb.replace('_caseinsensitive', '');
}
getSuffix(verb: string) {
if (verb.includes('_caseinsensitive')) {
return '_caseinsensitive';
} else {
return '';
}
}
parseForm(formValue): SelectionCriteria {
let value = HelperFunctions.copy(formValue);
let selectionCriteria: SelectionCriteria = new SelectionCriteria();
selectionCriteria.criteria = [];
value.criteria.forEach(criterion => {
let criteria = new Criteria();
criteria.constraint = [];
criterion.constraint.forEach(constraint => {
criteria.constraint.push(new Constraint(constraint.verb + constraint.verb_suffix, constraint.field, constraint.value));
});
selectionCriteria.criteria.push(criteria);
})
return selectionCriteria;
}
resetFieldWhenValueChange(constraint){
// if field not numeric, but verb is numeric clear the verb
if(this.criteriaUtils.numericFields.indexOf(constraint.get('field').value) == -1 && this.criteriaUtils.verbs.indexOf(constraint.get('verb').value)){
constraint.get('verb').setValue(this.criteriaUtils.verbs[0].value);
}
if(this.criteriaUtils.numericFields.indexOf(constraint.get('field').value) != -1 && this.criteriaUtils.numericFields.indexOf(constraint.get('verb').value)){
constraint.get('verb').setValue(this.criteriaUtils.verbsForNumbers[0].value);
}
}
}