Coupled paraterized dictionary

This commit is contained in:
2023-02-06 17:44:03 +01:00
parent d12e35cc10
commit 920bb39ca1
8 changed files with 188 additions and 18 deletions

View File

@@ -19,6 +19,7 @@ export class CardComponent implements OnInit {
@Input() is_modal: Boolean = false;
@Output() resourceCreated: EventEmitter<string> = new EventEmitter();
@Output() resourceUpdated: EventEmitter<string> = new EventEmitter();
@Output() resourceDeleted: EventEmitter<string> = new EventEmitter();
@@ -81,6 +82,7 @@ export class CardComponent implements OnInit {
this.crudService.update(this.resource!, model).subscribe((model: any) => {
this.model = model;
this._modelLoading$.next(false);
this.resourceUpdated.emit(model._id)
});
}
}

View File

@@ -45,6 +45,8 @@ export class CrudFormlyJsonschemaOptions implements FormlyJsonschemaOptions {
field.type = "date";
} else if (schema.hasOwnProperty('enum') && schema.enum.length == 1 && schema.enum[0] == schema.default ) {
field.type = "hidden";
} else if (schema.type == "array" && schema.format == "dictionary") {
field.type = "dictionary";
}
if (schema.hasOwnProperty('props')) {

View File

@@ -20,6 +20,8 @@ import { JsonschemasService } from "./jsonschemas.service";
import { MultiSchemaTypeComponent } from "./types/multischema.type";
import { ForeignkeyTypeComponent } from "./types/foreignkey.type";
import {HiddenTypeComponent} from "./types/hidden.type";
import {DictionaryTypeComponent} from "./types/dictionary.type";
import {DictionaryService} from "./types/dictionary.service";
@NgModule({
@@ -33,8 +35,15 @@ import {HiddenTypeComponent} from "./types/hidden.type";
MultiSchemaTypeComponent,
ForeignkeyTypeComponent,
HiddenTypeComponent,
DictionaryTypeComponent
],
providers: [
JsonschemasService,
ApiService,
CrudService,
CrudFormlyJsonschemaService,
DictionaryService
],
providers: [ JsonschemasService, ApiService, CrudService, CrudFormlyJsonschemaService ],
imports: [
CommonModule,
HttpClientModule,
@@ -51,6 +60,7 @@ import {HiddenTypeComponent} from "./types/hidden.type";
{ name: 'multischema', component: MultiSchemaTypeComponent },
{ name: 'foreign-key', component: ForeignkeyTypeComponent },
{ name: 'hidden', component: HiddenTypeComponent },
{ name: 'dictionary', component: DictionaryTypeComponent },
]
}),
FormlyBootstrapModule

View File

@@ -0,0 +1,23 @@
import { Injectable } from '@angular/core';
import {Observable, Subject} from "rxjs";
@Injectable()
export class DictionaryService {
fieldsParameters: {[field_id: string]: string[]} = {}
parameters: string[] = []
parameters$: Subject<string[]> = new Subject<string[]>()
updateParameters(field_id: string, newParameters: string[]) {
this.fieldsParameters[field_id] = newParameters;
this.parameters = [].concat();
for (const field of Object.values(this.fieldsParameters)) {
this.parameters = this.parameters.concat(field);
}
this.parameters = this.parameters.filter(
(item,index) => this.parameters.indexOf(item) === index
);
this.parameters$.next(this.parameters)
}
}

View File

@@ -0,0 +1,97 @@
import { Component, OnInit } from '@angular/core';
import {FieldType, FieldTypeConfig, FormlyFieldConfig, FormlyFormOptions} from '@ngx-formly/core';
import {FormControl, FormGroup, FormArray} from "@angular/forms";
import {DictionaryService} from "./dictionary.service";
import {JSONSchema7} from "json-schema";
import {FormlyJsonschema} from "@ngx-formly/core/json-schema";
@Component({
selector: 'formly-dictionary-type',
template: `
<div class="mb-3">
<ngb-accordion #acc="ngbAccordion" activeIds="ngb-panel-0">
<ngb-panel>
<ng-template ngbPanelTitle>
<label *ngIf="props.label && props['hideLabel'] !== true" [attr.for]="id"
class="form-label">{{ props.label }}
<span *ngIf="props.required && props['hideRequiredMarker'] !== true" aria-hidden="true">*</span>
</label>
</ng-template>
<ng-template ngbPanelContent>
<div class="alert alert-danger" role="alert" *ngIf="showError && formControl.errors">
<formly-validation-message [field]="field"></formly-validation-message>
</div>
<formly-form [model]="parameterModel" [fields]="parameterFields" [form]="parameterForm"></formly-form>
</ng-template>
</ngb-panel>
</ngb-accordion>
</div>
`,
})
export class DictionaryTypeComponent extends FieldType<FieldTypeConfig> implements OnInit
{
public errorMsg: string = "";
parameterForm: FormGroup = new FormGroup({});
parameterList: string[] = [];
parameterModel: {[field_id: string]: string} = {};
parameterFields: FormlyFieldConfig[] = [];
constructor(protected service: DictionaryService,
private formlyJsonschema: FormlyJsonschema) {
super();
}
ngOnInit() {
for (const entry of this.formControl.value) {
this.parameterModel[entry.key] = entry.value;
}
this.service.parameters$.subscribe((parameters) => {
this.parameterList = parameters;
for (const pname of parameters) {
if (Object.keys(this.parameterModel).indexOf(pname) == -1) {
this.parameterModel[pname] = "";
}
}
this.parameterFields = [this.formlyJsonschema.toFieldConfig(
this.getFormSchema(parameters)
)];
this.parameterForm.setValue(this.parameterModel, {emitEvent: false});
});
this.parameterForm.valueChanges.subscribe((values) => {
this.parameterModel = values;
const formValue: { key :string, value: string }[] = []
for (const [key, value] of Object.entries(this.parameterModel)) {
formValue.push({key, value});
}
this.formControl.setValue(formValue)
})
}
getFormSchema(properties: string[]) {
const schema: JSONSchema7 = {
type: "object",
properties: {
},
};
let required: string[] = []
for (const pname of properties) {
schema.properties![pname] = {
type: "string",
title: pname
}
if (this.field.props.required) {
required.push(pname)
}
}
schema.required = required
return schema
}
}

View File

@@ -7,6 +7,7 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { CrudService, Filters } from "../crud.service";
import { CrudFormlyJsonschemaService } from "../crud-formly-jsonschema.service";
import { FormGroup } from "@angular/forms";
import {DictionaryService} from "./dictionary.service";
@Component({
selector: 'formly-foreignkey-type',
@@ -61,13 +62,14 @@ import { FormGroup } from "@angular/forms";
[resource_id]="this.foreignModel._id"
[schema]="this.foreignSchema"
[is_modal]="true"
(resourceDeleted)="onResourceDeleted($event)">
(resourceDeleted)="onResourceDeleted($event)"
(resourceUpdated)="onResourceModified($event)">
</crud-card>
<crud-card *ngIf="! this.hasValue()"
[resource]="this.foreignResource"
[schema]="this.foreignSchema"
[is_modal]="true"
(resourceCreated)="onResourceCreated($event)">
(resourceCreated)="onResourceModified($event)">
</crud-card>
</div>
<div class="modal-footer">
@@ -88,7 +90,8 @@ export class ForeignkeyTypeComponent extends FieldType<FieldTypeConfig> implemen
constructor(private crudService: CrudService,
private formlyJsonschema: CrudFormlyJsonschemaService,
private modalService: NgbModal
private modalService: NgbModal,
protected service: DictionaryService
) {
super();
}
@@ -114,18 +117,12 @@ export class ForeignkeyTypeComponent extends FieldType<FieldTypeConfig> implemen
this.foreignModel = {};
this.foreignLabel = "";
} else if (v != this.foreignModel._id) {
this.getResource(v).pipe(
map(v => { this.setModel(v); return v; }),
map( v => this.formControl.patchValue(v._id))
).subscribe()
this.loadModel(v);
}
})
).subscribe();
if (this.hasValue()) {
this.getResource(this.formControl.value).pipe(
map( v => { this.setModel(v); return v; }),
map( v => this.formControl.patchValue(v._id))
).subscribe()
this.loadModel(this.formControl.value);
}
}
@@ -133,6 +130,13 @@ export class ForeignkeyTypeComponent extends FieldType<FieldTypeConfig> implemen
return this.crudService.get(this.foreignResource, id);
}
loadModel(id:string) {
this.getResource(id).pipe(
map(v => { this.setModel(v); return v; }),
map( v => this.formControl.patchValue(v._id))
).subscribe()
}
search: OperatorFunction<string, readonly string[]> = (text$: Observable<string>) => {
return text$.pipe(
debounceTime(200),
@@ -163,6 +167,7 @@ export class ForeignkeyTypeComponent extends FieldType<FieldTypeConfig> implemen
this.foreignModel = model;
this.foreignLabel = model.label;
this.loadDisplayedFields();
this.service.updateParameters(this.field.id!, this.getParameters())
}
hasValue() {
@@ -173,9 +178,9 @@ export class ForeignkeyTypeComponent extends FieldType<FieldTypeConfig> implemen
this.modalService.open(modal, { size: 'xl' });
}
onResourceCreated(resource_id: string) {
onResourceModified(resource_id: string) {
this.modalService.dismissAll();
this.getResource(resource_id);
this.loadModel(resource_id);
}
see(modal: any) {
@@ -213,4 +218,26 @@ export class ForeignkeyTypeComponent extends FieldType<FieldTypeConfig> implemen
});
}
}
getParameters() {
return this.extractParameters(this.foreignModel);
}
extractParameters(obj: any) {
let result: string[] = [];
for (const [k, v] of Object.entries(obj)) {
if (typeof(obj[k]) == "string") {
const matches = obj[k].match(/%[^\s.]+%/g);
if (matches) {
result = result.concat(matches.map((p: string | any[]) => p.slice(1,-1)) || []);
}
result = result.concat();
} else if (typeof(obj[k]) == "object") {
result = result.concat(this.extractParameters(obj[k]));
}
}
return result
}
}