Handling subfileds as colunm in list

This commit is contained in:
2023-02-08 03:27:28 +01:00
parent c5910ef22e
commit 4ee649a814
3 changed files with 120 additions and 40 deletions

View File

@@ -1,6 +1,7 @@
import { Observable } from "rxjs"; import { Observable } from "rxjs";
import { Injectable } from "@angular/core"; import { Injectable } from "@angular/core";
import { ApiService } from "./crud.service"; import { ApiService } from "./crud.service";
import {JSONSchema7} from "json-schema";
@Injectable({ @Injectable({
@@ -42,7 +43,7 @@ export class JsonschemasService {
for (let i in prop.oneOf) { for (let i in prop.oneOf) {
this.resolveReference(resource, prop.oneOf[i]); 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); this.resolveReference(resource, prop.items);
} }
} }
@@ -61,6 +62,10 @@ export class JsonschemasService {
} }
} }
getReferencedSchema() {
}
getCreateResource(resourceName: string): Observable<Schema> { getCreateResource(resourceName: string): Observable<Schema> {
return new Observable<Schema>((observer) => { return new Observable<Schema>((observer) => {
this.getSchemas().subscribe(() => { this.getSchemas().subscribe(() => {
@@ -91,10 +96,18 @@ export class JsonschemasService {
}) })
} }
private is_object(prop: any) {
return prop.hasOwnProperty('properties')
}
private is_reference(prop: any) { private is_reference(prop: any) {
return prop.hasOwnProperty('$ref'); return prop.hasOwnProperty('$ref');
} }
private is_array(prop: any) {
return prop.hasOwnProperty('items');
}
private is_union(prop: any) { private is_union(prop: any) {
return prop.hasOwnProperty('oneOf'); return prop.hasOwnProperty('oneOf');
} }
@@ -102,6 +115,67 @@ export class JsonschemasService {
private get_reference_name(prop: any) { private get_reference_name(prop: any) {
return prop['$ref'].substring(prop['$ref'].lastIndexOf('/')+1); 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 { export interface Schema {

View File

@@ -26,7 +26,7 @@
<tbody> <tbody>
<tr *ngFor="let row of listData$ | async" (click)="onSelect(row._id)"> <tr *ngFor="let row of listData$ | async" (click)="onSelect(row._id)">
<td *ngFor="let col of this.displayedColumns"> <td *ngFor="let col of this.displayedColumns">
<ngb-highlight [result]="row[col]" [term]="searchTerm"></ngb-highlight> <ngb-highlight [result]="getColumnValue(row,col)" [term]="searchTerm"></ngb-highlight>
</td> </td>
</tr> </tr>
</tbody> </tbody>

View File

@@ -1,39 +1,46 @@
import { Component, ViewChildren, QueryList, Input, OnInit } from '@angular/core'; import { Component, ViewChildren, QueryList, Input, OnInit } from '@angular/core';
import { BehaviorSubject } from "rxjs"; import { BehaviorSubject } from "rxjs";
import {JSONSchema7} from "json-schema";
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import {CrudService, Filters, SortBy} from "../crud.service"; import {CrudService, Filters, SortBy} from "../crud.service";
import { NgbdSortableHeader, SortColumn, SortDirection } from './sortable.directive'; import { NgbdSortableHeader, SortColumn, SortDirection } from './sortable.directive';
import { JsonschemasService } from "../jsonschemas.service"; import { JsonschemasService } from "../jsonschemas.service";
interface SearchResult {
data: any[];
total: number;
}
interface State { interface State {
page: number; page: number;
pageSize: number; pageSize: number;
searchTerm: string; searchTerm: string;
sortColumn: SortColumn; sortColumn: SortColumn;
sortDirection: SortDirection; sortDirection: SortDirection;
} }
@Component({ @Component({
selector: 'crud-list', selector: 'crud-list',
templateUrl: './list.component.html', templateUrl: './list.component.html',
styleUrls: ['./list.component.css'], styleUrls: ['./list.component.css'],
}) })
export class ListComponent implements OnInit { export class ListComponent implements OnInit {
@Input() resource: string = ""; @Input() resource: string = "";
@Input() columns: string[] = []; @Input() columns: string[] = [];
@Input() schema: string | undefined; @Input() schema: string | undefined;
public displayedColumns: string[] = []; @ViewChildren(NgbdSortableHeader) headers: QueryList<NgbdSortableHeader> = new QueryList<NgbdSortableHeader>();
loading: boolean = false; public displayedColumns: string[] = [];
@ViewChildren(NgbdSortableHeader) headers: QueryList<NgbdSortableHeader> = new QueryList<NgbdSortableHeader>(); private _loading$ = new BehaviorSubject<boolean>(true);
//private _search$ = new Subject<void>();
private _listData$ = new BehaviorSubject<any[]>([]);
private _total$ = new BehaviorSubject<number>(0);
private _state: State = {
page: 1,
pageSize: 15,
searchTerm: '',
sortColumn: '_id',
sortDirection: 'asc',
};
constructor(private service: CrudService, constructor(private service: CrudService,
private jsonSchemasService: JsonschemasService, private jsonSchemasService: JsonschemasService,
@@ -42,36 +49,35 @@ export class ListComponent implements OnInit {
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.jsonSchemasService.getUpdateResource(this.schema!).subscribe((schemas: any) => { this.jsonSchemasService.getUpdateResource(this.schema!).subscribe((schema: any) => {
if (this.columns.length == 0) { this.getColumnDefinition(schema)
for (let param_name in schemas.properties) { })
this._search();
}
getColumnDefinition(schema: JSONSchema7) {
if (this.columns.length == 0) {
for (let param_name in schema.properties) {
if (param_name != "_id") { if (param_name != "_id") {
this.displayedColumns.push(param_name); this.displayedColumns.push(param_name);
} }
} }
} else { } else {
for (let column of this.columns) { for (let column of this.columns) {
if (column in schemas.properties) { if (this.jsonSchemasService.path_exists(schema, column)) {
this.displayedColumns.push(column); this.displayedColumns.push(column);
} }
} }
} }
})
this._search();
} }
private _loading$ = new BehaviorSubject<boolean>(true); getColumnValue(row: any, col: string) {
//private _search$ = new Subject<void>(); let parent = row;
private _listData$ = new BehaviorSubject<any[]>([]); for (const key of col.split('.')) {
private _total$ = new BehaviorSubject<number>(0); parent = parent[key];
}
private _state: State = { return parent;
page: 1, }
pageSize: 15,
searchTerm: '',
sortColumn: '_id',
sortDirection: 'asc',
};
private _search() { private _search() {
this._loading$.next(true); this._loading$.next(true);
@@ -104,7 +110,7 @@ export class ListComponent implements OnInit {
} }
onCreate() { onCreate() {
this.router.navigate([`../new`], {relativeTo: this.route}); this.router.navigate([`../new`], {relativeTo: this.route});
} }
get listData$() { get listData$() {