diff --git a/back/app/entity/models.py b/back/app/entity/models.py index 63cbc33d..900bf97e 100644 --- a/back/app/entity/models.py +++ b/back/app/entity/models.py @@ -15,10 +15,10 @@ class EntityType(BaseModel): class Individual(EntityType): type: Literal['individual'] = 'individual' - firstname: Indexed(str, index_type=TEXT) - middlenames: List[Indexed(str)] = Field(default=[]) + firstname: Indexed(str) + middlename: Indexed(str) = "" lastname: Indexed(str) - surnames: List[Indexed(str)] = Field(default=[]) + surnames: List[Indexed(str)] = [] day_of_birth: date @@ -29,15 +29,8 @@ class Individual(EntityType): return '{} {}'.format(self.firstname, self.lastname) - @staticmethod - def get_label(data) -> str: - if len(data['surname']) > 0: - return '{} "{}" {}'.format(data['firstname'], data['surnames'][0], data['lastname']) - return '{} {}'.format(data['firstname'], data['lastname']) - - -class Employee(EntityType): +class Employee(BaseModel): role: Indexed(str) entity_id: str = Field(foreignKey={ "reference": { @@ -55,7 +48,7 @@ class Corporation(EntityType): employees: List[Employee] = Field(default=[]) -class Institution(BaseModel): +class Institution(EntityType): type: Literal['institution'] = 'institution' title: Indexed(str) activity: Indexed(str) @@ -70,6 +63,8 @@ class Entity(Document): @validator("label", always=True) def generate_label(cls, v, values, **kwargs): + if 'entity_data' not in values: + return v return values['entity_data'].label created_at: datetime = Field(default=datetime.utcnow(), nullable=False) diff --git a/back/app/entity/schemas.py b/back/app/entity/schemas.py index 50def168..6ff96e5d 100644 --- a/back/app/entity/schemas.py +++ b/back/app/entity/schemas.py @@ -1,7 +1,7 @@ from typing import Optional from pydantic import BaseModel, Field -from .models import Entity, EntityType, Individual, Corporation +from .models import Entity, Institution, Individual, Corporation from ..core.schemas import Writer @@ -10,10 +10,10 @@ class EntityRead(Entity): class EntityCreate(Writer): - entity_data: Individual | Corporation = Field(..., discriminator='type') + entity_data: Individual | Corporation | Institution = Field(..., discriminator='type') address: Optional[str] = "" class EntityUpdate(BaseModel): - entity_data: Individual | Corporation = Field(..., discriminator='type') + entity_data: Individual | Corporation | Institution = Field(..., discriminator='type') address: Optional[str] = "" diff --git a/back/migration.py b/back/migration.py index 90d5c638..067f95e1 100644 --- a/back/migration.py +++ b/back/migration.py @@ -19,7 +19,7 @@ async def handle_migration(args): content = json.load(f) for r in content: obj = m(**r) - obj.save() + await obj.save() elif args.action == "export-fixtures": for m in models: diff --git a/front/app/src/common/crud/card/card.component.html b/front/app/src/common/crud/card/card.component.html index 2f4c0a3d..c8139fd8 100644 --- a/front/app/src/common/crud/card/card.component.html +++ b/front/app/src/common/crud/card/card.component.html @@ -2,10 +2,10 @@
Loading... - -
diff --git a/front/app/src/common/crud/card/card.component.ts b/front/app/src/common/crud/card/card.component.ts index 1f67e64e..5262a69b 100644 --- a/front/app/src/common/crud/card/card.component.ts +++ b/front/app/src/common/crud/card/card.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { FormlyFieldConfig } from '@ngx-formly/core' import { ActivatedRoute, Router } from '@angular/router'; @@ -19,6 +19,12 @@ export interface Model { export class CardComponent implements OnInit { @Input() resource: string | undefined; @Input() resource_id: string | null = null; + @Input() is_modal: Boolean = false; + + @Output() resourceCreated: EventEmitter = new EventEmitter(); + @Output() resourceDeleted: EventEmitter = new EventEmitter(); + + form = new FormGroup({}); model = {}; fields: FormlyFieldConfig[] = []; @@ -60,7 +66,11 @@ export class CardComponent implements OnInit { if (this.isCreateForm()) { this.crudService.create(this.resource!, model).subscribe((response: any) => { this._loading$.next(false); - this.router.navigate([`../${response.id}`], {relativeTo: this.route}); + if (! this.is_modal) { + this.router.navigate([`../${response.id}`], {relativeTo: this.route}); + } else { + this.resourceCreated.emit(response.id) + } }); } else { this.crudService.update(this.resource!, model).subscribe((model: any) => { @@ -74,7 +84,11 @@ export class CardComponent implements OnInit { this._loading$.next(true); this.crudService.delete(this.resource!, this.model).subscribe((model: any) => { this._loading$.next(false); - this.router.navigate(['../'], {relativeTo: this.route}); + if (! this.is_modal) { + this.router.navigate(['../'], {relativeTo: this.route}); + } else { + this.resourceDeleted.emit("") + } }); } diff --git a/front/app/src/common/crud/crud-formly-jsonschema.service.ts b/front/app/src/common/crud/crud-formly-jsonschema.service.ts index 4ae29808..7b542d59 100644 --- a/front/app/src/common/crud/crud-formly-jsonschema.service.ts +++ b/front/app/src/common/crud/crud-formly-jsonschema.service.ts @@ -20,12 +20,14 @@ export class CrudFormlyJsonschemaService extends FormlyJsonschema { } getCreateFields(resourceName: string): Observable { + resourceName = resourceName.charAt(0).toUpperCase() + resourceName.slice(1); return this.jsonSchemasService.getCreateResource(resourceName).pipe( map((schemas: any) => this.toFieldConfig(schemas)), ) } getUpdateFields(resourceName: string): Observable { + resourceName = resourceName.charAt(0).toUpperCase() + resourceName.slice(1); return this.jsonSchemasService.getUpdateResource(resourceName).pipe( map((schemas: any) => this.toFieldConfig(schemas)), ) @@ -35,8 +37,16 @@ export class CrudFormlyJsonschemaService extends FormlyJsonschema { export class CrudFormlyJsonschemaOptions implements FormlyJsonschemaOptions { map = (field: any, schema: any) => { if (schema.hasOwnProperty('foreignKey')) { + field.type = "foreign-key"; field.foreignKey = schema['foreignKey']; + } else if (schema.format === 'date-time') { + field.type = "datetime"; + } else if (schema.format === 'date') { + field.type = "date"; + } else if (schema.hasOwnProperty('enum') && schema.enum.length == 1 && schema.enum[0] == schema.default ) { + field.type = "hidden"; } + return field; } } diff --git a/front/app/src/common/crud/crud.module.ts b/front/app/src/common/crud/crud.module.ts index aa34385f..946cfdcc 100644 --- a/front/app/src/common/crud/crud.module.ts +++ b/front/app/src/common/crud/crud.module.ts @@ -19,6 +19,7 @@ import { NgbModule} from "@ng-bootstrap/ng-bootstrap"; import { JsonschemasService } from "./jsonschemas.service"; import { MultiSchemaTypeComponent } from "./types/multischema.type"; import { ForeignkeyTypeComponent } from "./types/foreignkey.type"; +import {HiddenTypeComponent} from "./types/hidden.type"; @NgModule({ @@ -31,6 +32,7 @@ import { ForeignkeyTypeComponent } from "./types/foreignkey.type"; ArrayTypeComponent, MultiSchemaTypeComponent, ForeignkeyTypeComponent, + HiddenTypeComponent, ], providers: [ JsonschemasService, ApiService, CrudService, CrudFormlyJsonschemaService ], imports: [ @@ -48,6 +50,7 @@ import { ForeignkeyTypeComponent } from "./types/foreignkey.type"; { name: 'array', component: ArrayTypeComponent }, { name: 'multischema', component: MultiSchemaTypeComponent }, { name: 'foreign-key', component: ForeignkeyTypeComponent }, + { name: 'hidden', component: HiddenTypeComponent }, ] }), FormlyBootstrapModule diff --git a/front/app/src/common/crud/jsonschemas.service.ts b/front/app/src/common/crud/jsonschemas.service.ts index 8aaec9a0..dcac005a 100644 --- a/front/app/src/common/crud/jsonschemas.service.ts +++ b/front/app/src/common/crud/jsonschemas.service.ts @@ -44,12 +44,6 @@ export class JsonschemasService { } } else if (prop.hasOwnProperty('items') && this.is_reference(prop.items)) { this.resolveReference(resource, prop.items); - } else if (prop.format === 'date-time') { - prop.type = "datetime"; - } else if (prop.format === 'date') { - prop.type = "date"; - } else if (prop.hasOwnProperty('foreignKey')) { - prop.type = "foreign-key"; } } diff --git a/front/app/src/common/crud/types/array.type.ts b/front/app/src/common/crud/types/array.type.ts index 5b10ac60..7634b705 100644 --- a/front/app/src/common/crud/types/array.type.ts +++ b/front/app/src/common/crud/types/array.type.ts @@ -14,11 +14,14 @@ import { FieldArrayType } from '@ngx-formly/core'; - -
- -
- +
+
+
+ +
+ +
+
diff --git a/front/app/src/common/crud/types/foreignkey.type.ts b/front/app/src/common/crud/types/foreignkey.type.ts index 46088a8a..756e33c4 100644 --- a/front/app/src/common/crud/types/foreignkey.type.ts +++ b/front/app/src/common/crud/types/foreignkey.type.ts @@ -1,8 +1,10 @@ + import {AfterContentInit, Component, OnInit} from '@angular/core'; import {Observable, OperatorFunction, switchMapTo, of, from, exhaustAll, mergeAll, concatAll} from 'rxjs'; import { catchError } from 'rxjs/operators'; import { debounceTime, distinctUntilChanged, map, tap, merge } from 'rxjs/operators'; import { FieldType, FieldTypeConfig} from '@ngx-formly/core'; +import { ModalDismissReasons, NgbModal } from '@ng-bootstrap/ng-bootstrap'; import {CrudService, Filters, SortBy} from "../crud.service"; import {formatDate} from "@angular/common"; @@ -29,35 +31,47 @@ import {formatDate} from "@angular/common"; [resultFormatter]="formatter" [editable]="false" />
- +
- +
- +
+ + + + + `, }) -export class ForeignkeyTypeComponent extends FieldType implements AfterContentInit +export class ForeignkeyTypeComponent extends FieldType implements OnInit { public foreignModel: any = {} public foreignLabel: string = "" - public foreignId: string = "" public foreignResource : string = ""; public errorMsg: string = ""; + public displayModal = false; - constructor(private crudService: CrudService) { + constructor(private crudService: CrudService, private modalService: NgbModal) { super(); } @@ -68,17 +82,20 @@ export class ForeignkeyTypeComponent extends FieldType implemen formatter = (foreignModel: any) => foreignModel.label; - ngAfterContentInit() { + ngOnInit() { // @ts-ignore this.foreignResource = this.field.foreignKey.reference.resource; if (this.hasValue()) { - this.crudService.get(this.foreignResource, this.formControl.value).subscribe((value: any) => { - this.foreignModel = value; - this.foreignLabel = this.foreignModel.label; - }); + this.getResource(this.formControl.value) } } + getResource(id: string) { + this.crudService.get(this.foreignResource, id).subscribe((value: any) => { + this.setValue(value); + }); + } + search: OperatorFunction = (text$: Observable) => { return text$.pipe( debounceTime(200), @@ -101,11 +118,40 @@ export class ForeignkeyTypeComponent extends FieldType implemen } selectedItem(event: any) { - this.formControl.setValue(event.item._id) - this.foreignLabel = event.item.label; + this.setValue(event.item); + } + + setValue(model: any) { + this.formControl.setValue(model._id) + this.foreignModel = model; + this.foreignLabel = model.label; } hasValue() { return this.formControl.value !== undefined; } + + add(modal: any) { + this.modalService.open(modal); + } + + onResourceCreated(resource_id: string) { + this.modalService.dismissAll(); + this.getResource(resource_id); + } + + see(modal: any) { + this.modalService.open(modal); + } + + onResourceDeleted(resource_id: string) { + this.modalService.dismissAll(); + this.remove(); + } + + remove() { + this.foreignModel = {}; + this.foreignLabel = ""; + this.formControl.setValue(undefined); + } } diff --git a/front/app/src/common/crud/types/hidden.type.ts b/front/app/src/common/crud/types/hidden.type.ts new file mode 100644 index 00000000..752d27a3 --- /dev/null +++ b/front/app/src/common/crud/types/hidden.type.ts @@ -0,0 +1,10 @@ +import { Component } from "@angular/core"; +import { FieldType, FieldTypeConfig } from "@ngx-formly/core"; + +@Component({ + selector: 'app-form-hidden-type', + template: ` + + `, +}) +export class HiddenTypeComponent extends FieldType {} diff --git a/front/app/src/common/crud/types/multischema.type.ts b/front/app/src/common/crud/types/multischema.type.ts index 7dcae663..a92ea3e3 100644 --- a/front/app/src/common/crud/types/multischema.type.ts +++ b/front/app/src/common/crud/types/multischema.type.ts @@ -1,20 +1,16 @@ -import {Component, OnInit} from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { FieldType } from '@ngx-formly/core'; -import {Observable} from "rxjs"; + @Component({ selector: 'formly-multi-schema-type', template: ` -
-

{{ props.description }}

-
-
`, }) export class MultiSchemaTypeComponent extends FieldType implements OnInit { @@ -24,11 +20,6 @@ export class MultiSchemaTypeComponent extends FieldType implements OnInit { option.label = f.fieldGroup![1].fieldGroup![option.value].props!.label; f.fieldGroup![1].fieldGroup![option.value].props!.label = ""; }); - - f.fieldGroup![1].fieldGroup!.forEach(function (field) { - //field.fieldGroup![0].hide = true; - }); - } } diff --git a/front/app/src/common/crud/types/object.type.ts b/front/app/src/common/crud/types/object.type.ts index f8089a85..578faab4 100644 --- a/front/app/src/common/crud/types/object.type.ts +++ b/front/app/src/common/crud/types/object.type.ts @@ -5,7 +5,7 @@ import { FieldType } from '@ngx-formly/core'; selector: 'formly-object-type', template: `
- {{ props.label }} +

{{ props.description }}