From 4ee649a81456feaf679c8fccc1d895548148f5b2 Mon Sep 17 00:00:00 2001 From: ewandor Date: Wed, 8 Feb 2023 03:27:28 +0100 Subject: [PATCH] Handling subfileds as colunm in list --- .../src/common/crud/jsonschemas.service.ts | 76 ++++++++++++++++- .../src/common/crud/list/list.component.html | 2 +- .../src/common/crud/list/list.component.ts | 82 ++++++++++--------- 3 files changed, 120 insertions(+), 40 deletions(-) diff --git a/front/app/src/common/crud/jsonschemas.service.ts b/front/app/src/common/crud/jsonschemas.service.ts index 8e77742d..ba763ffb 100644 --- a/front/app/src/common/crud/jsonschemas.service.ts +++ b/front/app/src/common/crud/jsonschemas.service.ts @@ -1,6 +1,7 @@ import { Observable } from "rxjs"; import { Injectable } from "@angular/core"; import { ApiService } from "./crud.service"; +import {JSONSchema7} from "json-schema"; @Injectable({ @@ -42,7 +43,7 @@ export class JsonschemasService { for (let i in prop.oneOf) { this.resolveReference(resource, prop.oneOf[i]); } - } else if (prop.hasOwnProperty('items') && this.is_reference(prop.items)) { + } else if (this.is_array(prop) && this.is_reference(prop.items)) { this.resolveReference(resource, prop.items); } } @@ -61,6 +62,10 @@ export class JsonschemasService { } } + getReferencedSchema() { + + } + getCreateResource(resourceName: string): Observable { return new Observable((observer) => { this.getSchemas().subscribe(() => { @@ -91,10 +96,18 @@ export class JsonschemasService { }) } + private is_object(prop: any) { + return prop.hasOwnProperty('properties') + } + private is_reference(prop: any) { return prop.hasOwnProperty('$ref'); } + private is_array(prop: any) { + return prop.hasOwnProperty('items'); + } + private is_union(prop: any) { return prop.hasOwnProperty('oneOf'); } @@ -102,6 +115,67 @@ export class JsonschemasService { private get_reference_name(prop: any) { return prop['$ref'].substring(prop['$ref'].lastIndexOf('/')+1); } + + has_descendant(resource: JSONSchema7, property_name: string): boolean { + if (this.is_array(resource)) { + return property_name == 'items'; + } else if (this.is_object(resource)) { + return property_name in resource.properties!; + } else if (this.is_reference(resource)) { + let subresourceName = this.get_reference_name(resource); + return this.has_descendant(this.buildResource(subresourceName), property_name); + } else if (this.is_union(resource)) { + for (const ref of resource.oneOf!) { + // @ts-ignore + if (this.has_descendant(ref, property_name)) { + return true; + } + return false; + } + } + throw new Error("Jsonschema format not implemented in property finder"); + return false; + } + + get_descendant(resource: JSONSchema7, property_name: string): JSONSchema7 { + if (this.is_array(resource) && property_name == 'items') { + // @ts-ignore + return resource.items; + } else if (this.is_object(resource) && property_name in resource.properties!) { + // @ts-ignore + return resource.properties[property_name]; + } else if (this.is_reference(resource)) { + let subresourceName = this.get_reference_name(resource); + let subresource = this.buildResource(subresourceName); + return this.get_descendant(subresource, property_name); + } else if (this.is_union(resource)) { + for (const ref of resource.oneOf!) { + // @ts-ignore + if (this.has_property(ref, property_name)) { + // @ts-ignore + return this.get_descendant(ref, property_name); + } + } + } + throw new Error("property not found or Jsonschema format not implemented"); + } + + path_exists(resource: JSONSchema7, path: string): boolean{ + const pointFirstPosition = path.indexOf('.') + if (pointFirstPosition == -1) { + return this.has_descendant(resource, path); + } + + + return this.has_descendant(resource, path.substring(0, pointFirstPosition)) + && this.path_exists( + this.get_descendant( + resource, + path.substring(0, pointFirstPosition) + ), + path.substring(pointFirstPosition + 1) + ); + } } export interface Schema { diff --git a/front/app/src/common/crud/list/list.component.html b/front/app/src/common/crud/list/list.component.html index 865ccace..24530fef 100644 --- a/front/app/src/common/crud/list/list.component.html +++ b/front/app/src/common/crud/list/list.component.html @@ -26,7 +26,7 @@ - + diff --git a/front/app/src/common/crud/list/list.component.ts b/front/app/src/common/crud/list/list.component.ts index e772cd1b..b77fbab9 100644 --- a/front/app/src/common/crud/list/list.component.ts +++ b/front/app/src/common/crud/list/list.component.ts @@ -1,39 +1,46 @@ import { Component, ViewChildren, QueryList, Input, OnInit } from '@angular/core'; import { BehaviorSubject } from "rxjs"; +import {JSONSchema7} from "json-schema"; import { ActivatedRoute, Router } from '@angular/router'; import {CrudService, Filters, SortBy} from "../crud.service"; import { NgbdSortableHeader, SortColumn, SortDirection } from './sortable.directive'; import { JsonschemasService } from "../jsonschemas.service"; -interface SearchResult { - data: any[]; - total: number; -} - interface State { - page: number; - pageSize: number; - searchTerm: string; - sortColumn: SortColumn; - sortDirection: SortDirection; + page: number; + pageSize: number; + searchTerm: string; + sortColumn: SortColumn; + sortDirection: SortDirection; } @Component({ - selector: 'crud-list', - templateUrl: './list.component.html', - styleUrls: ['./list.component.css'], + selector: 'crud-list', + templateUrl: './list.component.html', + styleUrls: ['./list.component.css'], }) export class ListComponent implements OnInit { - @Input() resource: string = ""; - @Input() columns: string[] = []; - @Input() schema: string | undefined; + @Input() resource: string = ""; + @Input() columns: string[] = []; + @Input() schema: string | undefined; - public displayedColumns: string[] = []; + @ViewChildren(NgbdSortableHeader) headers: QueryList = new QueryList(); - loading: boolean = false; + public displayedColumns: string[] = []; - @ViewChildren(NgbdSortableHeader) headers: QueryList = new QueryList(); + private _loading$ = new BehaviorSubject(true); + //private _search$ = new Subject(); + private _listData$ = new BehaviorSubject([]); + private _total$ = new BehaviorSubject(0); + + private _state: State = { + page: 1, + pageSize: 15, + searchTerm: '', + sortColumn: '_id', + sortDirection: 'asc', + }; constructor(private service: CrudService, private jsonSchemasService: JsonschemasService, @@ -42,36 +49,35 @@ export class ListComponent implements OnInit { ) { } ngOnInit(): void { - this.jsonSchemasService.getUpdateResource(this.schema!).subscribe((schemas: any) => { - if (this.columns.length == 0) { - for (let param_name in schemas.properties) { + this.jsonSchemasService.getUpdateResource(this.schema!).subscribe((schema: any) => { + this.getColumnDefinition(schema) + }) + this._search(); + } + + getColumnDefinition(schema: JSONSchema7) { + if (this.columns.length == 0) { + for (let param_name in schema.properties) { if (param_name != "_id") { this.displayedColumns.push(param_name); } } } else { for (let column of this.columns) { - if (column in schemas.properties) { + if (this.jsonSchemasService.path_exists(schema, column)) { this.displayedColumns.push(column); } } } - }) - this._search(); } - private _loading$ = new BehaviorSubject(true); - //private _search$ = new Subject(); - private _listData$ = new BehaviorSubject([]); - private _total$ = new BehaviorSubject(0); - - private _state: State = { - page: 1, - pageSize: 15, - searchTerm: '', - sortColumn: '_id', - sortDirection: 'asc', - }; + getColumnValue(row: any, col: string) { + let parent = row; + for (const key of col.split('.')) { + parent = parent[key]; + } + return parent; + } private _search() { this._loading$.next(true); @@ -104,7 +110,7 @@ export class ListComponent implements OnInit { } onCreate() { - this.router.navigate([`../new`], {relativeTo: this.route}); + this.router.navigate([`../new`], {relativeTo: this.route}); } get listData$() {