From 15f101eb9f80fdc2d794532e9e45c0f90d195c74 Mon Sep 17 00:00:00 2001 From: ewandor Date: Wed, 18 Jan 2023 16:04:01 +0100 Subject: [PATCH] Fully resource agnostic jsonschemas interpreter --- .../src/common/crud/card/card.component.ts | 52 ++++++------ front/app/src/common/crud/crud.module.ts | 3 +- front/app/src/common/crud/crud.service.ts | 5 +- .../src/common/crud/jsonschemas.service.ts | 85 +++++++++++++++++++ 4 files changed, 114 insertions(+), 31 deletions(-) create mode 100644 front/app/src/common/crud/jsonschemas.service.ts diff --git a/front/app/src/common/crud/card/card.component.ts b/front/app/src/common/crud/card/card.component.ts index 40bd5c50..3e63483d 100644 --- a/front/app/src/common/crud/card/card.component.ts +++ b/front/app/src/common/crud/card/card.component.ts @@ -6,6 +6,7 @@ import { Router } from '@angular/router'; import { CrudService } from '../crud.service' import {BehaviorSubject} from "rxjs"; +import {JsonschemasService} from "../jsonschemas.service"; export interface Model { email: string; @@ -32,45 +33,44 @@ export class CardComponent implements OnInit { } constructor(private crudService: CrudService, + private jsonSchemasService: JsonschemasService, private formlyJsonschema: FormlyJsonschema, private router: Router ) { } - ngOnInit(): void { - this._loading$.next(true); - this.crudService.getSchema().subscribe((jsonSchemas: any) => { - this.schemas = jsonSchemas.components.schemas.EntityCreate - this.schemas.components = { - schemas: { - EntityType: jsonSchemas.components.schemas.EntityType + ngOnInit(): void { + this._loading$.next(true); + if (this.isCreateForm()) { + this.jsonSchemasService.getCreateResource(this.resource).subscribe((schemas: any) => { + this.fields = [this.formlyJsonschema.toFieldConfig(schemas)]; + }) + } else { + this.jsonSchemasService.getUpdateResource(this.resource).subscribe((schemas: any) => { + this.fields = [this.formlyJsonschema.toFieldConfig(schemas)]; + }) + this.crudService.get(this.resource_id!).subscribe((model: any) => { + this.model = model + this._loading$.next(false); + }); } - }; - - this.fields = [this.formlyJsonschema.toFieldConfig(this.schemas)]; - }); - - if (this.resource_id !== null) { - this.crudService.get(this.resource_id!).subscribe((model: any) => { - this.model = model - }); - - this._loading$.next(false); } - } onSubmit(model: any) { this._loading$.next(true); - if (this.resource_id !== null) { - this.crudService.update(model).subscribe((model: any) => { - this.model = model; - this._loading$.next(false); - }); - } else { + if (this.isCreateForm()) { this.crudService.create(model).subscribe((response: any) => { this._loading$.next(false); this.router.navigateByUrl('/entities/' + response.id); }); + } else { + this.crudService.update(model).subscribe((model: any) => { + this.model = model; + this._loading$.next(false); + }); } - console.log(model); + } + + isCreateForm() { + return this.resource_id === null; } } diff --git a/front/app/src/common/crud/crud.module.ts b/front/app/src/common/crud/crud.module.ts index d49a032c..3e915dc7 100644 --- a/front/app/src/common/crud/crud.module.ts +++ b/front/app/src/common/crud/crud.module.ts @@ -14,6 +14,7 @@ import { ListComponent } from './list/list.component'; import { ObjectTypeComponent } from "./object.type"; import { CrudService } from "./crud.service"; import {NgbModule} from "@ng-bootstrap/ng-bootstrap"; +import {JsonschemasService} from "./jsonschemas.service"; @NgModule({ @@ -22,7 +23,7 @@ import {NgbModule} from "@ng-bootstrap/ng-bootstrap"; ListComponent, ObjectTypeComponent ], - providers: [ CrudService ], + providers: [ CrudService, JsonschemasService ], imports: [ CommonModule, HttpClientModule, diff --git a/front/app/src/common/crud/crud.service.ts b/front/app/src/common/crud/crud.service.ts index 3fd5f60e..a970cfbf 100644 --- a/front/app/src/common/crud/crud.service.ts +++ b/front/app/src/common/crud/crud.service.ts @@ -1,11 +1,8 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; +import { Schema } from "./jsonschemas.service"; -export interface Schema { - components: { }; -} - @Injectable() export class CrudService { diff --git a/front/app/src/common/crud/jsonschemas.service.ts b/front/app/src/common/crud/jsonschemas.service.ts new file mode 100644 index 00000000..c8c4093a --- /dev/null +++ b/front/app/src/common/crud/jsonschemas.service.ts @@ -0,0 +1,85 @@ +import {CrudService} from "./crud.service"; +import {Observable} from "rxjs"; +import {Injectable} from "@angular/core"; + + +@Injectable({ + providedIn: 'root', +}) +export class JsonschemasService { + private rawSchemas: any | null = null; + + constructor(private crudService: CrudService) {} + + getSchemas(): Observable { + return new Observable((observer) => { + if (this.rawSchemas === null) { + this.crudService.getSchema().subscribe((jsonSchemas: any) => { + this.rawSchemas = jsonSchemas; + observer.next(this.rawSchemas) + }); + } else { + observer.next(this.rawSchemas) + } + }); + } + + buildResource(resourceName: string) { + let resource; + + resource = { ... this.rawSchemas.components.schemas[resourceName]}; + resource.components = { schemas: {} }; + for (let prop_name in resource.properties) { + let prop = resource.properties[prop_name]; + + if (this.is_reference(prop)) { + let subresourceName = this.get_reference_name(prop); + resource.components.schemas[subresourceName] = this.buildResource(subresourceName); + } + } + + return resource; + } + + getCreateResource(resourceName: string): Observable { + return new Observable((observer) => { + this.getSchemas().subscribe(() => { + observer.next(this.buildResource(resourceName + 'Create')) + }) + }) + } + + getUpdateResource(resourceName: string): Observable { + return new Observable((observer) => { + this.getSchemas().subscribe(() => { + let resource = this.buildResource(resourceName + 'Read'); + let updateResource = this.rawSchemas.components.schemas[resourceName + 'Update'] + + for (let prop_name in resource.properties) { + if (! updateResource.properties.hasOwnProperty(prop_name)) { + if (this.is_reference(resource.properties[prop_name])) { + let subresourceName = this.get_reference_name(resource.properties[prop_name]); + resource.components.schemas[subresourceName].readOnly = true; + } else { + resource.properties[prop_name].readOnly = true; + } + } + } + + observer.next(resource); + }) + }) + } + + private is_reference(prop: any) { + return prop.hasOwnProperty('$ref'); + } + + private get_reference_name(prop: any) { + return prop['$ref'].substring(prop['$ref'].lastIndexOf('/')+1); + } +} + +export interface Schema { + components: { }; +}