Adding Date and working on fereign keys

This commit is contained in:
2023-01-22 04:39:11 +01:00
parent 70d5a6e752
commit 7dd684e514
9 changed files with 289 additions and 21 deletions

View File

@@ -24,8 +24,13 @@ class Individual(BaseModel):
class Employee(BaseModel): class Employee(BaseModel):
entity_id: str
role: str role: str
entity_id: str = Field(foreignKey={
"reference": {
"resource": "entity",
"fields": "_id"
}
})
class Corporation(BaseModel): class Corporation(BaseModel):
@@ -46,6 +51,7 @@ class Entity(Document):
class Settings: class Settings:
bson_encoders = { bson_encoders = {
date: lambda dt: datetime(year=dt.year, month=dt.month, day=dt.day, hour=0, minute=0, second=0) \ date: lambda dt: dt if hasattr(dt, 'hour')
if not hasattr(dt, 'hour') else dt else datetime(year=dt.year, month=dt.month, day=dt.day,
hour=0, minute=0, second=0)
} }

View File

@@ -1,12 +1,11 @@
import { Component, Input, OnInit } from '@angular/core'; import { Component, Input, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms'; import { FormGroup } from '@angular/forms';
import { FormlyFieldConfig } from '@ngx-formly/core' import { FormlyFieldConfig } from '@ngx-formly/core'
import { FormlyJsonschema } from '@ngx-formly/core/json-schema';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { CrudService } from '../crud.service' import { CrudService } from '../crud.service'
import { BehaviorSubject } from "rxjs"; import { BehaviorSubject } from "rxjs";
import { JsonschemasService } from "../jsonschemas.service"; import {CrudFormlyJsonschemaService} from "../crud-formly-jsonschema.service";
export interface Model { export interface Model {
email: string; email: string;
@@ -33,27 +32,27 @@ export class CardComponent implements OnInit {
} }
constructor(private crudService: CrudService, constructor(private crudService: CrudService,
private jsonSchemasService: JsonschemasService, private formlyJsonschema: CrudFormlyJsonschemaService,
private formlyJsonschema: FormlyJsonschema,
private router: Router, private router: Router,
private route: ActivatedRoute, private route: ActivatedRoute,
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this._loading$.next(true); this._loading$.next(true);
let fields$;
if (this.isCreateForm()) { if (this.isCreateForm()) {
this.jsonSchemasService.getCreateResource(this.resource!).subscribe((schemas: any) => { fields$ = this.formlyJsonschema.getCreateFields(this.resource!);
this.fields = [this.formlyJsonschema.toFieldConfig(schemas)];
})
} else { } else {
this.jsonSchemasService.getUpdateResource(this.resource!).subscribe((schemas: any) => {
this.fields = [this.formlyJsonschema.toFieldConfig(schemas)];
})
this.crudService.get(this.resource!, this.resource_id!).subscribe((model: any) => { this.crudService.get(this.resource!, this.resource_id!).subscribe((model: any) => {
this.model = model this.model = model
this._loading$.next(false); this._loading$.next(false);
}); });
fields$ = this.formlyJsonschema.getUpdateFields(this.resource!);
} }
fields$.subscribe((fields: any) => {
this.fields = [fields]
});
} }
onSubmit(model: any) { onSubmit(model: any) {

View File

@@ -0,0 +1,34 @@
import { FormlyJsonschema } from "@ngx-formly/core/json-schema";
import { FormlyJsonschemaOptions } from "@ngx-formly/core/json-schema/formly-json-schema.service";
import { FormlyFieldConfig } from "@ngx-formly/core";
import { JSONSchema7 } from 'json-schema';
import {JsonschemasService } from "./jsonschemas.service";
import {Observable, map, tap} from "rxjs";
import {Injectable} from "@angular/core";
@Injectable({
providedIn: 'root',
})
export class CrudFormlyJsonschemaService extends FormlyJsonschema {
constructor(private jsonSchemasService: JsonschemasService) {
super();
}
override toFieldConfig(schema: JSONSchema7, options?: FormlyJsonschemaOptions): FormlyFieldConfig {
return super.toFieldConfig(schema, options);
}
getCreateFields(resourceName: string): Observable<FormlyFieldConfig> {
return this.jsonSchemasService.getCreateResource(resourceName).pipe(
map((schemas: any) => this.toFieldConfig(schemas)),
tap(console.log),
)
}
getUpdateFields(resourceName: string): Observable<FormlyFieldConfig> {
return this.jsonSchemasService.getUpdateResource(resourceName).pipe(
map((schemas: any) => this.toFieldConfig(schemas)),
tap(console.log),
)
}
}

View File

@@ -12,10 +12,13 @@ import { ListComponent } from './list/list.component';
import { ArrayTypeComponent } from "./types/array.type"; import { ArrayTypeComponent } from "./types/array.type";
import { ObjectTypeComponent } from "./types/object.type"; import { ObjectTypeComponent } from "./types/object.type";
import { DatetimeTypeComponent } from "./types/datetime.type"; import { DatetimeTypeComponent } from "./types/datetime.type";
import { DateTypeComponent } from "./types/date.type";
import { ApiService, CrudService } from "./crud.service"; import { ApiService, CrudService } from "./crud.service";
import { CrudFormlyJsonschemaService } from "./crud-formly-jsonschema.service";
import { NgbModule} from "@ng-bootstrap/ng-bootstrap"; import { NgbModule} from "@ng-bootstrap/ng-bootstrap";
import { JsonschemasService } from "./jsonschemas.service"; import { JsonschemasService } from "./jsonschemas.service";
import { MultiSchemaTypeComponent } from "./types/multischema.type"; import { MultiSchemaTypeComponent } from "./types/multischema.type";
import { ForeignkeyTypeComponent } from "./types/foreignkey.type";
@NgModule({ @NgModule({
@@ -24,10 +27,12 @@ import { MultiSchemaTypeComponent } from "./types/multischema.type";
ListComponent, ListComponent,
ObjectTypeComponent, ObjectTypeComponent,
DatetimeTypeComponent, DatetimeTypeComponent,
DateTypeComponent,
ArrayTypeComponent, ArrayTypeComponent,
MultiSchemaTypeComponent MultiSchemaTypeComponent,
ForeignkeyTypeComponent,
], ],
providers: [ JsonschemasService, ApiService, CrudService ], providers: [ JsonschemasService, ApiService, CrudService, CrudFormlyJsonschemaService ],
imports: [ imports: [
CommonModule, CommonModule,
HttpClientModule, HttpClientModule,
@@ -39,8 +44,10 @@ import { MultiSchemaTypeComponent } from "./types/multischema.type";
types: [ types: [
{ name: 'object', component: ObjectTypeComponent }, { name: 'object', component: ObjectTypeComponent },
{ name: 'datetime', component: DatetimeTypeComponent }, { name: 'datetime', component: DatetimeTypeComponent },
{ name: 'date', component: DateTypeComponent },
{ name: 'array', component: ArrayTypeComponent }, { name: 'array', component: ArrayTypeComponent },
{ name: 'multischema', component: MultiSchemaTypeComponent }, { name: 'multischema', component: MultiSchemaTypeComponent },
{ name: 'foreign-key', component: ForeignkeyTypeComponent },
] ]
}), }),
FormlyBootstrapModule FormlyBootstrapModule

View File

@@ -1,6 +1,8 @@
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Injectable, Inject } from '@angular/core'; import { Injectable, Inject } from '@angular/core';
import { Schema } from "./jsonschemas.service"; import { Schema } from "./jsonschemas.service";
import {catchError} from "rxjs/operators";
import {from} from "rxjs";
@Injectable() @Injectable()

View File

@@ -1,6 +1,6 @@
import {ApiService} from "./crud.service"; import { Observable } from "rxjs";
import {Observable} from "rxjs"; import { Injectable } from "@angular/core";
import {Injectable} from "@angular/core"; import { ApiService } from "./crud.service";
@Injectable({ @Injectable({
@@ -9,7 +9,9 @@ import {Injectable} from "@angular/core";
export class JsonschemasService { export class JsonschemasService {
private rawSchemas: any | null = null; private rawSchemas: any | null = null;
constructor(private apiService: ApiService) {} constructor(
private apiService: ApiService
) {}
getSchemas(): Observable<Schema> { getSchemas(): Observable<Schema> {
return new Observable<Schema>((observer) => { return new Observable<Schema>((observer) => {
@@ -44,6 +46,10 @@ export class JsonschemasService {
this.resolveReference(resource, prop.items); this.resolveReference(resource, prop.items);
} else if (prop.format === 'date-time') { } else if (prop.format === 'date-time') {
prop.type = "datetime"; prop.type = "datetime";
} else if (prop.format === 'date') {
prop.type = "date";
} else if (prop.hasOwnProperty('foreignKey')) {
prop.type = "foreign-key";
} }
} }

View File

@@ -0,0 +1,72 @@
import { Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import { formatDate } from "@angular/common";
import { NgbDateStruct, NgbTimeStruct } from '@ng-bootstrap/ng-bootstrap';
import { FieldType, FieldTypeConfig } from '@ngx-formly/core';
@Component({
selector: 'app-form-datepicker-type',
template: `
<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>
<div class="input-group" *ngIf="! this.field.props.readonly">
<input type="hidden"
[formControl]="formControl"
[formlyAttributes]="field"
[class.is-invalid]="showError"
/>
<input
class="form-control"
placeholder="yyyy-mm-dd"
name="dp"
[(ngModel)]="date"
(ngModelChange)="changeDatetime($event)"
ngbDatepicker
#d="ngbDatepicker"
/>
<button class="btn btn-outline-secondary bi bi-calendar3" (click)="d.toggle()" type="button"></button>
</div>
<div class="input-group" *ngIf="this.field.props.readonly">
<input class="form-control" value="{{ this.datetime.toLocaleString() }}" disabled=""/>
</div>
`,
})
export class DateTypeComponent extends FieldType<FieldTypeConfig> implements OnInit
{
public time : NgbTimeStruct = { hour: 12, minute: 0, second: 0 }
public date : NgbDateStruct = { year: 2023, month: 1, day: 9 }
public datetime : Date = new Date()
constructor() {
super();
}
ngOnInit() {
this.formControl.valueChanges.subscribe(value => {
this.datetime = new Date(value)
this.date = this.getDateStruct(this.datetime);
})
}
getDateStruct(d: Date) {
return {
year: d.getFullYear(),
month: d.getMonth() + 1,
day: d.getDate(),
}
}
changeDatetime(event: any) {
this.datetime.setFullYear(this.date.year)
this.datetime.setMonth(this.date.month - 1)
this.datetime.setDate(this.date.day)
this.formControl.setValue(
formatDate(this.datetime, 'YYYY-MM-dd', 'EN_US', 'CET')
)
}
}

View File

@@ -6,14 +6,14 @@ import { FieldType, FieldTypeConfig } from '@ngx-formly/core';
@Component({ @Component({
selector: 'app-form-datepicker-type', selector: 'app-form-datetimepicker-type',
template: ` template: `
<label *ngIf="props.label && props['hideLabel'] !== true" [attr.for]="id" <label *ngIf="props.label && props['hideLabel'] !== true" [attr.for]="id"
class="form-label">{{ props.label }} class="form-label">{{ props.label }}
<span *ngIf="props.required && props['hideRequiredMarker'] !== true" aria-hidden="true">*</span> <span *ngIf="props.required && props['hideRequiredMarker'] !== true" aria-hidden="true">*</span>
</label> </label>
<div class="input-group" *ngIf="! this.field.props.readonly"> <div class="input-group" *ngIf="! this.field.props.readonly">
<input type="text" <input type="hidden"
[formControl]="formControl" [formControl]="formControl"
[formlyAttributes]="field" [formlyAttributes]="field"
[class.is-invalid]="showError" [class.is-invalid]="showError"

View File

@@ -0,0 +1,142 @@
import {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 {CrudService} from "../crud.service";
const states = [
'Alabama',
'Alaska',
'American Samoa',
'Arizona',
'Arkansas',
'California',
'Colorado',
'Connecticut',
'Delaware',
'District Of Columbia',
'Federated States Of Micronesia',
'Florida',
'Georgia',
'Guam',
'Hawaii',
'Idaho',
'Illinois',
'Indiana',
'Iowa',
'Kansas',
'Kentucky',
'Louisiana',
'Maine',
'Marshall Islands',
'Maryland',
'Massachusetts',
'Michigan',
'Minnesota',
'Mississippi',
'Missouri',
'Montana',
'Nebraska',
'Nevada',
'New Hampshire',
'New Jersey',
'New Mexico',
'New York',
'North Carolina',
'North Dakota',
'Northern Mariana Islands',
'Ohio',
'Oklahoma',
'Oregon',
'Palau',
'Pennsylvania',
'Puerto Rico',
'Rhode Island',
'South Carolina',
'South Dakota',
'Tennessee',
'Texas',
'Utah',
'Vermont',
'Virgin Islands',
'Virginia',
'Washington',
'West Virginia',
'Wisconsin',
'Wyoming',
];
@Component({
selector: 'formly-array-type',
template: `
<div class="mb-3">
<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>
<div class="alert alert-danger" role="alert" *ngIf="showError && formControl.errors">
<formly-validation-message [field]="field"></formly-validation-message>
</div>
<input
class="form-control"
name="autocomplete"
[(ngModel)]="foreignId"
/>
<div class="input-group">
<input type="text"
class="form-control"
placeholder="Type the first letters..."
[(ngModel)]="foreignId"
[ngbTypeahead]="search" >
<div class="input-group-append">
<button class="btn btn-outline-secondary cil-plus" type="button">Button</button>
</div>
</div>
</div>
`,
})
export class ForeignkeyTypeComponent extends FieldType<FieldTypeConfig> implements OnInit
{
public foreignId: string = ""
public foreignResource : string = "";
public errorMsg: string = "";
constructor(private crudService: CrudService) {
super();
}
asyncSelected: string = "toto";
typeaheadLoading: boolean = false;
typeaheadNoResults: boolean = true;
dataSource: Observable<any> = new Observable();
ngOnInit() {
this.foreignResource = this.field.key!.toString().split('_')[0];
this.dataSource = new Observable((observer: any) => {
observer.next(this.asyncSelected);
})
}
// fired every time search string is changed
search: OperatorFunction<string, readonly string[]> = (text$: Observable<string>) => {
return text$.pipe(
debounceTime(200),
distinctUntilChanged(),
map((term) => this.getList(term)),
concatAll(),
)
}
getList(term: string) : Observable<readonly string[]> {
return this.crudService.getList(this.foreignResource, 0, 10, '_id', 'asc')
.pipe(
map((result: any) => result["items"]),
tap(console.log),
);
}
}