Adding Date and working on fereign keys
This commit is contained in:
@@ -24,8 +24,13 @@ class Individual(BaseModel):
|
||||
|
||||
|
||||
class Employee(BaseModel):
|
||||
entity_id: str
|
||||
role: str
|
||||
entity_id: str = Field(foreignKey={
|
||||
"reference": {
|
||||
"resource": "entity",
|
||||
"fields": "_id"
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
class Corporation(BaseModel):
|
||||
@@ -46,6 +51,7 @@ class Entity(Document):
|
||||
|
||||
class Settings:
|
||||
bson_encoders = {
|
||||
date: lambda dt: datetime(year=dt.year, month=dt.month, day=dt.day, hour=0, minute=0, second=0) \
|
||||
if not hasattr(dt, 'hour') else dt
|
||||
date: lambda dt: dt if hasattr(dt, 'hour')
|
||||
else datetime(year=dt.year, month=dt.month, day=dt.day,
|
||||
hour=0, minute=0, second=0)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
import { FormlyFieldConfig } from '@ngx-formly/core'
|
||||
import { FormlyJsonschema } from '@ngx-formly/core/json-schema';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
|
||||
import { CrudService } from '../crud.service'
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
import { JsonschemasService } from "../jsonschemas.service";
|
||||
import {CrudFormlyJsonschemaService} from "../crud-formly-jsonschema.service";
|
||||
|
||||
export interface Model {
|
||||
email: string;
|
||||
@@ -33,27 +32,27 @@ export class CardComponent implements OnInit {
|
||||
}
|
||||
|
||||
constructor(private crudService: CrudService,
|
||||
private jsonSchemasService: JsonschemasService,
|
||||
private formlyJsonschema: FormlyJsonschema,
|
||||
private formlyJsonschema: CrudFormlyJsonschemaService,
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this._loading$.next(true);
|
||||
let fields$;
|
||||
if (this.isCreateForm()) {
|
||||
this.jsonSchemasService.getCreateResource(this.resource!).subscribe((schemas: any) => {
|
||||
this.fields = [this.formlyJsonschema.toFieldConfig(schemas)];
|
||||
})
|
||||
fields$ = this.formlyJsonschema.getCreateFields(this.resource!);
|
||||
} 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.model = model
|
||||
this._loading$.next(false);
|
||||
});
|
||||
fields$ = this.formlyJsonschema.getUpdateFields(this.resource!);
|
||||
}
|
||||
|
||||
fields$.subscribe((fields: any) => {
|
||||
this.fields = [fields]
|
||||
});
|
||||
}
|
||||
|
||||
onSubmit(model: any) {
|
||||
|
||||
34
front/app/src/common/crud/crud-formly-jsonschema.service.ts
Normal file
34
front/app/src/common/crud/crud-formly-jsonschema.service.ts
Normal 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),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -12,10 +12,13 @@ import { ListComponent } from './list/list.component';
|
||||
import { ArrayTypeComponent } from "./types/array.type";
|
||||
import { ObjectTypeComponent } from "./types/object.type";
|
||||
import { DatetimeTypeComponent } from "./types/datetime.type";
|
||||
import { DateTypeComponent } from "./types/date.type";
|
||||
import { ApiService, CrudService } from "./crud.service";
|
||||
import { CrudFormlyJsonschemaService } from "./crud-formly-jsonschema.service";
|
||||
import { NgbModule} from "@ng-bootstrap/ng-bootstrap";
|
||||
import { JsonschemasService } from "./jsonschemas.service";
|
||||
import { MultiSchemaTypeComponent } from "./types/multischema.type";
|
||||
import { ForeignkeyTypeComponent } from "./types/foreignkey.type";
|
||||
|
||||
|
||||
@NgModule({
|
||||
@@ -24,10 +27,12 @@ import { MultiSchemaTypeComponent } from "./types/multischema.type";
|
||||
ListComponent,
|
||||
ObjectTypeComponent,
|
||||
DatetimeTypeComponent,
|
||||
DateTypeComponent,
|
||||
ArrayTypeComponent,
|
||||
MultiSchemaTypeComponent
|
||||
MultiSchemaTypeComponent,
|
||||
ForeignkeyTypeComponent,
|
||||
],
|
||||
providers: [ JsonschemasService, ApiService, CrudService ],
|
||||
providers: [ JsonschemasService, ApiService, CrudService, CrudFormlyJsonschemaService ],
|
||||
imports: [
|
||||
CommonModule,
|
||||
HttpClientModule,
|
||||
@@ -39,8 +44,10 @@ import { MultiSchemaTypeComponent } from "./types/multischema.type";
|
||||
types: [
|
||||
{ name: 'object', component: ObjectTypeComponent },
|
||||
{ name: 'datetime', component: DatetimeTypeComponent },
|
||||
{ name: 'date', component: DateTypeComponent },
|
||||
{ name: 'array', component: ArrayTypeComponent },
|
||||
{ name: 'multischema', component: MultiSchemaTypeComponent },
|
||||
{ name: 'foreign-key', component: ForeignkeyTypeComponent },
|
||||
]
|
||||
}),
|
||||
FormlyBootstrapModule
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable, Inject } from '@angular/core';
|
||||
import { Schema } from "./jsonschemas.service";
|
||||
import {catchError} from "rxjs/operators";
|
||||
import {from} from "rxjs";
|
||||
|
||||
|
||||
@Injectable()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {ApiService} from "./crud.service";
|
||||
import {Observable} from "rxjs";
|
||||
import {Injectable} from "@angular/core";
|
||||
import { Observable } from "rxjs";
|
||||
import { Injectable } from "@angular/core";
|
||||
import { ApiService } from "./crud.service";
|
||||
|
||||
|
||||
@Injectable({
|
||||
@@ -9,7 +9,9 @@ import {Injectable} from "@angular/core";
|
||||
export class JsonschemasService {
|
||||
private rawSchemas: any | null = null;
|
||||
|
||||
constructor(private apiService: ApiService) {}
|
||||
constructor(
|
||||
private apiService: ApiService
|
||||
) {}
|
||||
|
||||
getSchemas(): Observable<Schema> {
|
||||
return new Observable<Schema>((observer) => {
|
||||
@@ -44,6 +46,10 @@ export class JsonschemasService {
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
72
front/app/src/common/crud/types/date.type.ts
Normal file
72
front/app/src/common/crud/types/date.type.ts
Normal 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')
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -6,14 +6,14 @@ import { FieldType, FieldTypeConfig } from '@ngx-formly/core';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-form-datepicker-type',
|
||||
selector: 'app-form-datetimepicker-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="text"
|
||||
<input type="hidden"
|
||||
[formControl]="formControl"
|
||||
[formlyAttributes]="field"
|
||||
[class.is-invalid]="showError"
|
||||
|
||||
142
front/app/src/common/crud/types/foreignkey.type.ts
Normal file
142
front/app/src/common/crud/types/foreignkey.type.ts
Normal 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),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user