robustifying arrays and foreignkeys

This commit is contained in:
2023-02-01 18:54:53 +01:00
parent 43ad5c3048
commit 12285b2473
5 changed files with 72 additions and 31 deletions

View File

@@ -32,22 +32,22 @@ class ProvisionTemplate(CrudDocument):
fulltext_search = ['name', 'title', 'body'] fulltext_search = ['name', 'title', 'body']
class ProvisionReference(BaseModel): class ProvisionTemplateReference(BaseModel):
provision_template_id: str = Field( provision_template_id: str = Field(
foreignKey={ foreignKey={
"reference": { "reference": {
"resource": "template/provision", "resource": "template/provision",
"schema": "ProvisionTemplate", "schema": "ProvisionTemplate",
"displayedFields": ['title', 'body']
}, },
}, }
props={"test": "test"}
) )
class ContractTemplate(CrudDocument): class ContractTemplate(CrudDocument):
name: str name: str
parties: List[PartyTemplate] = [] parties: List[PartyTemplate] = []
provisions: List[ProvisionReference] = Field( provisions: List[ProvisionTemplateReference] = Field(
default=[], default=[],
props={"items-per-row": "1"} props={"items-per-row": "1"}
) )

View File

@@ -1,7 +1,7 @@
from pydantic import BaseModel from pydantic import BaseModel
from typing import List from typing import List
from .models import ContractTemplate, ProvisionTemplate, PartyTemplate, ProvisionReference from .models import ContractTemplate, ProvisionTemplate, PartyTemplate, ProvisionTemplateReference
from ..core.schemas import Writer from ..core.schemas import Writer
from ..core.models import text_area from ..core.models import text_area
@@ -17,7 +17,7 @@ class ContractTemplateCreate(Writer):
class ContractTemplateUpdate(BaseModel): class ContractTemplateUpdate(BaseModel):
name: str name: str
parties: List[PartyTemplate] = [] parties: List[PartyTemplate] = []
provisions: List[ProvisionReference] = [] provisions: List[ProvisionTemplateReference] = []
class ProvisionTemplateRead(ProvisionTemplate): class ProvisionTemplateRead(ProvisionTemplate):

View File

@@ -91,7 +91,7 @@ export class CrudService extends ApiService {
} }
public get(resource: string, id: string) { public get(resource: string, id: string) {
return this.http.get<{}>( return this.http.get<any>(
`${this.api_root}/${resource.toLowerCase()}/${id}` `${this.api_root}/${resource.toLowerCase()}/${id}`
); );
} }

View File

@@ -43,8 +43,7 @@ export class ArrayTypeComponent extends FieldArrayType implements OnInit {
throw new Error("to value must be comprised between 0 and n - 1"); throw new Error("to value must be comprised between 0 and n - 1");
} }
value_list.splice(to, 0, value_list.splice(from, 1)[0]); value_list.splice(to, 0, value_list.splice(from, 1)[0]);
this.formControl.setValue(value_list); this.formControl.patchValue(value_list);
this.field.fieldGroup!.splice(to, 0, this.field.fieldGroup!.splice(from, 1)[0]);
} }
} }

View File

@@ -1,12 +1,12 @@
import {AfterContentInit, Component, OnInit} from '@angular/core'; import { Component, OnInit } from '@angular/core';
import {Observable, OperatorFunction, switchMapTo, of, from, exhaustAll, mergeAll, concatAll} from 'rxjs'; import { Observable, OperatorFunction, concatAll } from 'rxjs';
import { catchError } from 'rxjs/operators'; import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators';
import { debounceTime, distinctUntilChanged, map, tap, merge } from 'rxjs/operators'; import { FieldType, FieldTypeConfig, FormlyFieldConfig } from '@ngx-formly/core';
import { FieldType, FieldTypeConfig} from '@ngx-formly/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { ModalDismissReasons, NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { CrudService, Filters } from "../crud.service";
import {CrudService, Filters, SortBy} from "../crud.service"; import { CrudFormlyJsonschemaService } from "../crud-formly-jsonschema.service";
import {formatDate} from "@angular/common"; import { FormGroup } from "@angular/forms";
@Component({ @Component({
selector: 'formly-foreignkey-type', selector: 'formly-foreignkey-type',
@@ -48,6 +48,7 @@ import {formatDate} from "@angular/common";
<button class="btn btn-danger" type="button" (click)="remove()"><span class="cil-x btn-icon mr-2"></span>Remove</button> <button class="btn btn-danger" type="button" (click)="remove()"><span class="cil-x btn-icon mr-2"></span>Remove</button>
</div> </div>
</div> </div>
<formly-form *ngIf="this.hasValue() && this.displayedFields" [form]="this.foreignForm" [fields]="this.foreignFields" [model]="this.foreignModel"></formly-form>
</div> </div>
<ng-template #foreignModal let-modal> <ng-template #foreignModal let-modal>
<div class="modal-header"> <div class="modal-header">
@@ -76,19 +77,23 @@ import {formatDate} from "@angular/common";
}) })
export class ForeignkeyTypeComponent extends FieldType<FieldTypeConfig> implements OnInit export class ForeignkeyTypeComponent extends FieldType<FieldTypeConfig> implements OnInit
{ {
public foreignForm = new FormGroup({});
public foreignFields: FormlyFieldConfig[] = [];
public foreignModel: any = {} public foreignModel: any = {}
public foreignLabel: string = "" public foreignLabel: string = ""
public foreignResource : string = ""; public foreignResource : string = "";
public foreignSchema : string = ""; public foreignSchema : string = "";
public displayedFields = [];
public errorMsg: string = ""; public errorMsg: string = "";
public displayModal = false;
constructor(private crudService: CrudService, private modalService: NgbModal) { constructor(private crudService: CrudService,
private formlyJsonschema: CrudFormlyJsonschemaService,
private modalService: NgbModal
) {
super(); super();
} }
typeaheadLoading: boolean = false; typeaheadLoading: boolean = false;
typeaheadNoResults: boolean = true;
dataSource: Observable<any> = new Observable(); dataSource: Observable<any> = new Observable();
formatter = (foreignModel: any) => foreignModel.label; formatter = (foreignModel: any) => foreignModel.label;
@@ -99,15 +104,33 @@ export class ForeignkeyTypeComponent extends FieldType<FieldTypeConfig> implemen
this.foreignResource = this.field.foreignKey.reference.resource; this.foreignResource = this.field.foreignKey.reference.resource;
// @ts-ignore // @ts-ignore
this.foreignSchema = this.field.foreignKey.reference.schema; this.foreignSchema = this.field.foreignKey.reference.schema;
// @ts-ignore
this.displayedFields = this.field.foreignKey.reference.displayedFields;
this.formControl.valueChanges.pipe(
map( v => {
if (!v) {
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()
}
})
).subscribe();
if (this.hasValue()) { if (this.hasValue()) {
this.getResource(this.formControl.value) this.getResource(this.formControl.value).pipe(
map( v => { this.setModel(v); return v; }),
map( v => this.formControl.patchValue(v._id))
).subscribe()
} }
} }
getResource(id: string) { getResource(id: string) {
this.crudService.get(this.foreignResource, id).subscribe((value: any) => { return this.crudService.get(this.foreignResource, id);
this.setValue(value);
});
} }
search: OperatorFunction<string, readonly string[]> = (text$: Observable<string>) => { search: OperatorFunction<string, readonly string[]> = (text$: Observable<string>) => {
@@ -132,17 +155,18 @@ export class ForeignkeyTypeComponent extends FieldType<FieldTypeConfig> implemen
} }
selectedItem(event: any) { selectedItem(event: any) {
this.setValue(event.item); this.setModel(event.item);
this.formControl.setValue(event.item._id);
} }
setValue(model: any) { setModel(model: any) {
this.formControl.setValue(model._id)
this.foreignModel = model; this.foreignModel = model;
this.foreignLabel = model.label; this.foreignLabel = model.label;
this.loadDisplayedFields();
} }
hasValue() { hasValue() {
return this.formControl.value !== undefined && this.formControl.value !== null; return this.formControl.value !== undefined && this.formControl.value !== null && this.formControl.value !== "";
} }
add(modal: any) { add(modal: any) {
@@ -164,8 +188,26 @@ export class ForeignkeyTypeComponent extends FieldType<FieldTypeConfig> implemen
} }
remove() { remove() {
this.foreignModel = {}; this.formControl.setValue("");
this.foreignLabel = ""; }
this.formControl.setValue(undefined);
loadDisplayedFields() {
if (this.displayedFields) {
this.formlyJsonschema.getUpdateFields(this.foreignSchema).subscribe( (form) =>
{
for (let i in form.fieldGroup) {
// @ts-ignore
let f = form["fieldGroup"]![i]
// @ts-ignore
if (this.displayedFields.indexOf(f.key) == -1) {
// @ts-ignore
delete form["fieldGroup"]![i]
}
}
delete form.props
delete form.templateOptions
this.foreignFields = [form];
});
}
} }
} }