Adjustements everywhere
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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] = ""
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
<form cForm [formGroup]="form" (ngSubmit)="onSubmit(model)">
|
||||
<span class="col col-form-label" *ngIf="loading$ | async">Loading...</span>
|
||||
<formly-form [form]="form" [fields]="fields" [model]="model"></formly-form>
|
||||
<button cButton color="primary">
|
||||
<button class="btn btn-success btn-lg" type="submit" [disabled]="!form.valid">
|
||||
{{ this.isCreateForm() ? "Create" : "Update" }}
|
||||
</button>
|
||||
<button cButton *ngIf="!this.isCreateForm()" (click)="onDelete()" color="danger">
|
||||
<button class="btn btn-danger btn-lg float-end" type="button" *ngIf="!this.isCreateForm()" (click)="onDelete()">
|
||||
Delete
|
||||
</button>
|
||||
</form>
|
||||
|
||||
@@ -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<string> = new EventEmitter();
|
||||
@Output() resourceDeleted: EventEmitter<string> = 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("")
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -20,12 +20,14 @@ export class CrudFormlyJsonschemaService extends FormlyJsonschema {
|
||||
}
|
||||
|
||||
getCreateFields(resourceName: string): Observable<FormlyFieldConfig> {
|
||||
resourceName = resourceName.charAt(0).toUpperCase() + resourceName.slice(1);
|
||||
return this.jsonSchemasService.getCreateResource(resourceName).pipe(
|
||||
map((schemas: any) => this.toFieldConfig(schemas)),
|
||||
)
|
||||
}
|
||||
|
||||
getUpdateFields(resourceName: string): Observable<FormlyFieldConfig> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,11 +14,14 @@ import { FieldArrayType } from '@ngx-formly/core';
|
||||
<div class="alert alert-danger" role="alert" *ngIf="showError && formControl.errors">
|
||||
<formly-validation-message [field]="field"></formly-validation-message>
|
||||
</div>
|
||||
|
||||
<div *ngFor="let field of field.fieldGroup; let i = index" class="row align-items-start">
|
||||
<formly-field class="col" [field]="field"></formly-field>
|
||||
<div *ngIf="field.props!['removable'] !== false" class="col-2 text-right">
|
||||
<button class="btn btn-danger" type="button" (click)="remove(i)">-</button>
|
||||
<div class="row">
|
||||
<div *ngFor="let field of field.fieldGroup; let i = index" class="card col-sm-6">
|
||||
<div class="card-body">
|
||||
<formly-field class="col" [field]="field"></formly-field>
|
||||
<div *ngIf="field.props!['removable'] !== false" class="col-2 text-right">
|
||||
<button class="btn btn-danger" type="button" (click)="remove(i)">-</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -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" />
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary cil-plus" type="button">Add</button>
|
||||
<button class="btn btn-success" type="button" (click)="add(foreignModal)"><span class="cil-plus btn-icon mr-2"></span> Add</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group" *ngIf="this.hasValue()">
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
value="{{this.foreignModel.label}}"
|
||||
value="{{this.foreignLabel}}"
|
||||
disabled=""
|
||||
readonly="readonly"
|
||||
/>
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary cil-plus" type="button">See</button>
|
||||
<button class="btn btn-info" type="button" (click)="see(foreignModal)"><span class="cil-zoom btn-icon"></span>See</button>
|
||||
</div>
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary cil-plus" type="button">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>
|
||||
<ng-template #foreignModal let-modal>
|
||||
<div class="modal-header">
|
||||
<button type="button" class="btn-close" aria-label="Close"
|
||||
(click)="modal.dismiss('Cross click')"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<crud-card *ngIf="this.hasValue()" [resource]="this.foreignResource" [resource_id]="this.foreignModel._id" [is_modal]="true" (resourceDeleted)="onResourceDeleted($event)"></crud-card>
|
||||
<crud-card *ngIf="! this.hasValue()" [resource]="this.foreignResource" [is_modal]="true" (resourceCreated)="onResourceCreated($event)"></crud-card>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
</div>
|
||||
</ng-template>
|
||||
`,
|
||||
})
|
||||
export class ForeignkeyTypeComponent extends FieldType<FieldTypeConfig> implements AfterContentInit
|
||||
export class ForeignkeyTypeComponent extends FieldType<FieldTypeConfig> 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<FieldTypeConfig> 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<string, readonly string[]> = (text$: Observable<string>) => {
|
||||
return text$.pipe(
|
||||
debounceTime(200),
|
||||
@@ -101,11 +118,40 @@ export class ForeignkeyTypeComponent extends FieldType<FieldTypeConfig> 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);
|
||||
}
|
||||
}
|
||||
|
||||
10
front/app/src/common/crud/types/hidden.type.ts
Normal file
10
front/app/src/common/crud/types/hidden.type.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { FieldType, FieldTypeConfig } from "@ngx-formly/core";
|
||||
|
||||
@Component({
|
||||
selector: 'app-form-hidden-type',
|
||||
template: `
|
||||
<input type="hidden" [formControl]="formControl" class="form-control" [formlyAttributes]="field"/>
|
||||
`,
|
||||
})
|
||||
export class HiddenTypeComponent extends FieldType<FieldTypeConfig> {}
|
||||
@@ -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: `
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<label *ngIf="props.label" class="form-label">{{ props.label }}</label>
|
||||
<p *ngIf="props.description">{{ props.description }}</p>
|
||||
<div class="alert alert-danger" role="alert" *ngIf="showError && formControl.errors">
|
||||
<formly-validation-message [field]="field"></formly-validation-message>
|
||||
<formly-validation-message [field]="field"></formly-validation-message>
|
||||
</div>
|
||||
<formly-field *ngFor="let f of field.fieldGroup" [field]="f"></formly-field>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
})
|
||||
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;
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { FieldType } from '@ngx-formly/core';
|
||||
selector: 'formly-object-type',
|
||||
template: `
|
||||
<div class="mb-3">
|
||||
<legend *ngIf="props.label">{{ props.label }}</legend>
|
||||
<label *ngIf="props.label">{{ props.label }}</label>
|
||||
<p *ngIf="props.description">{{ props.description }}</p>
|
||||
<div class="alert alert-danger" role="alert" *ngIf="showError && formControl.errors">
|
||||
<formly-validation-message [field]="field"></formly-validation-message>
|
||||
|
||||
Reference in New Issue
Block a user