From 9b31dd2a617c11f9953c316fb69bf665d7c5850e Mon Sep 17 00:00:00 2001 From: FishExplosion <1arteha1@gmail.com> Date: Tue, 24 Dec 2019 19:39:50 +0100 Subject: [PATCH] v0.1.6-alpha.3 - added @Textarea() for string-fields. - @UseForSearch() improvements. - fixes --- package.json | 12 ++++++---- src/ExtendedRecord.ts | 35 +---------------------------- src/Property.ts | 41 +++++++++++++++++++++++++++++++--- src/Resource.ts | 8 +++---- src/decorators/Textarea.ts | 14 ++++++++++++ src/symbols/TEXTAREA_SYMBOL.ts | 1 + src/utils/convertFilter.ts | 12 +++++++--- src/utils/getTitle.ts | 3 +++ tsconfig.json | 3 ++- 9 files changed, 80 insertions(+), 49 deletions(-) create mode 100644 src/decorators/Textarea.ts create mode 100644 src/symbols/TEXTAREA_SYMBOL.ts diff --git a/package.json b/package.json index 97cba019..7e92b387 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "admin-bro-typeorm", - "version": "0.1.6-alpha.2", + "version": "0.1.6-alpha.3", "description": "TypeORM adapter for AdminBro", "keywords": [ "typeorm", @@ -27,8 +27,8 @@ "author": "Artem Zabolotnyi <1arteha1@gmail.com>", "license": "MIT", "peerDependencies": { - "reflect-metadata": ">=0.1.13", - "admin-bro": ">=1.4.0", + "admin-bro": ">=1.6.0-beta.5", + "admin-bro-expressjs": ">=0.4.0", "typeorm": ">=0.2.1" }, "optionalDependencies": {}, @@ -36,7 +36,8 @@ "@types/chai": "^4.2.4", "@types/mocha": "^5.2.7", "@types/node": "12.0.10", - "admin-bro": ">=1.4.0", + "admin-bro": "^1.6.0-beta.5", + "admin-bro-expressjs": "^0.4.0", "chai": "^4.2.0", "class-validator": "^0.11.0", "mocha": "^6.2.2", @@ -46,5 +47,8 @@ "tslint": "^5.20.0", "typeorm": "^0.2.1", "typescript": "^3.6.3" + }, + "dependencies": { + "reflect-metadata": "^0.1.13" } } diff --git a/src/ExtendedRecord.ts b/src/ExtendedRecord.ts index a88a9b5c..463d98e6 100644 --- a/src/ExtendedRecord.ts +++ b/src/ExtendedRecord.ts @@ -35,40 +35,7 @@ export class ExtendedRecord extends BaseRecord obj.title = this.title(); // sorry but, .toJSON() doesn't take title from .title() if(this._instance) { - // I Also patched "dots" to normal JSON. Because now we can edit json field like a string: - /* - { - "params": { - "id": 93, - "name": "4", - "carrierId": 1, - "countryId": 5, - "zeros": 3, - "zipCodes.0": 9, - "zipCodes.1": 12, - "zipCodes.2": 19, - "zipCodes.3": 22, - "zipCodes.4": 24, - "zipCodes.5.0": 33000, - "zipCodes.5.1": 34999, - "zipCodes.6.0": 39000, - "zipCodes.6.1": 40999, - "zipCodes.7": 42, - "zipCodes.8": 44, - "zipCodes.9": 47, - "zipCodes.10": 49, - "exceptions": [], - "carrier.id": 1, - "carrier.name": "leman", - "carrier.oilRate": 1.336, - "carrier.category": "all", - "carrier.hasSpecialHandling": true, - "country.id": 5, - "country.name": "SPAIN" - }, - ... - } - * */ + // patched strange objects ({"key.deepKey": 123}) to normal JSON. obj.params = {}; for (const n in this._instance) { diff --git a/src/Property.ts b/src/Property.ts index 85e04fa2..d5d950ba 100644 --- a/src/Property.ts +++ b/src/Property.ts @@ -1,18 +1,25 @@ +import "reflect-metadata"; import { ColumnMetadata } from "typeorm/metadata/ColumnMetadata"; import { DATA_TYPES } from "./utils/data-types"; - import { BaseProperty, PropertyType } from "admin-bro"; +import {Resource} from "./Resource"; +import {TEXTAREA_SYMBOL} from "./symbols/TEXTAREA_SYMBOL"; +import { SEARCH_FIELD_SYMBOL } from "./symbols/SEARCH_FIELD_SYMBOL"; export class Property extends BaseProperty { public column: ColumnMetadata; + public resource: Resource; + public columnPosition: number; - constructor(column: ColumnMetadata) + constructor(column: ColumnMetadata, resource: Resource, columnPosition: number) { // for reference fields take database name (with ...Id) const path = column.referencedColumn ? column.databaseName : column.propertyPath; super({ path }); this.column = column; + this.resource = resource; + this.columnPosition = columnPosition; } public name() @@ -20,6 +27,21 @@ export class Property extends BaseProperty return this.column.propertyName; } + isTitle(): boolean + { + const name = this.name(); + const key = Reflect.getMetadata(SEARCH_FIELD_SYMBOL, this.resource.model); + if(key != undefined) + return key == this.name(); + else + { + const firstProp = this.resource.properties()[0]; + if(firstProp) + return firstProp.name() == name; + return false; + } + } + public isEditable() { return !this.isId() @@ -41,6 +63,10 @@ export class Property extends BaseProperty return null; } + public position() { + return this.columnPosition || 0; + } + public availableValues() { const values = this.column.enum; @@ -51,6 +77,7 @@ export class Property extends BaseProperty public type(): PropertyType { + let type: PropertyType | null = null; if (typeof this.column.type == "function") { @@ -70,6 +97,14 @@ export class Property extends BaseProperty if (!type) console.warn(`Unhandled type: ${this.column.type}`); - return type || "string"; + type = type || "string"; + + if(type == "string" && Reflect.getMetadata(TEXTAREA_SYMBOL, this.resource.model, this.name())) + return "textarea"; + // TODO: Uncomment this in future. + /*if(Reflect.getMetadata(TEXTAREA_SYMBOL, this.resource.model, this.name())) + return "textarea";*/ + + return type; } } \ No newline at end of file diff --git a/src/Resource.ts b/src/Resource.ts index 3ff933c1..c1b0232d 100644 --- a/src/Resource.ts +++ b/src/Resource.ts @@ -11,7 +11,7 @@ import { SEARCH_FIELD_SYMBOL } from "./symbols/SEARCH_FIELD_SYMBOL"; export class Resource extends BaseResource { public static validate: any; - private model: typeof BaseEntity; + public model: typeof BaseEntity; private propsObject: Record = {}; constructor(model: typeof BaseEntity) @@ -46,7 +46,7 @@ export class Resource extends BaseResource { // Reverse properties as temporary fix of columns direction. // TODO: remove .reverse() when "admin-bro" will be fixed. - return Object.values(this.propsObject).reverse(); + return Object.values(this.propsObject); } public property(path: string): Property | null @@ -200,9 +200,9 @@ export class Resource extends BaseResource private prepareProps() { const columns = this.model.getRepository().metadata.columns; - for (const col of columns) + for (let i = 0; i < columns.length; i++) { - const property = new Property(col); + const property = new Property(columns[i], this, i); this.propsObject[property.path()] = property; } } diff --git a/src/decorators/Textarea.ts b/src/decorators/Textarea.ts new file mode 100644 index 00000000..3764e7d9 --- /dev/null +++ b/src/decorators/Textarea.ts @@ -0,0 +1,14 @@ +import "reflect-metadata"; +import { TEXTAREA_SYMBOL } from "../symbols/TEXTAREA_SYMBOL"; +import { BaseEntity } from "typeorm"; + +export function Textarea(name?: string) +{ + return function (target: BaseEntity, propertyKey: string | undefined): void + { + if (propertyKey == undefined) + throw new TypeError(); + + Reflect.defineMetadata(TEXTAREA_SYMBOL, true, target.constructor, name || propertyKey); + }; +} \ No newline at end of file diff --git a/src/symbols/TEXTAREA_SYMBOL.ts b/src/symbols/TEXTAREA_SYMBOL.ts new file mode 100644 index 00000000..9a842b0f --- /dev/null +++ b/src/symbols/TEXTAREA_SYMBOL.ts @@ -0,0 +1 @@ +export const TEXTAREA_SYMBOL = Symbol("textarea"); \ No newline at end of file diff --git a/src/utils/convertFilter.ts b/src/utils/convertFilter.ts index e09e997b..f1aaf2f9 100644 --- a/src/utils/convertFilter.ts +++ b/src/utils/convertFilter.ts @@ -1,4 +1,4 @@ -import { BaseEntity, FindConditions, Between, MoreThanOrEqual, LessThanOrEqual } from "typeorm"; +import { BaseEntity, FindConditions, Between, MoreThanOrEqual, LessThanOrEqual, Like } from "typeorm"; import { Filter } from "admin-bro"; function safeParseJSON(json: string) @@ -24,7 +24,13 @@ export function convertFilter(filter?: Filter): FindConditions for (const n in filters) { const one = filters[n]; - if(["boolean", "number", "float", "mixed"].includes(one.property.type())) + if(["number", "float", "reference"].includes(one.property.type())) + { + const val = Number(one.value); + if(!isNaN(val)) + where[n] = val; + } + else if(["boolean", "mixed"].includes(one.property.type())) where[n] = safeParseJSON(one.value); else if(["date", "datetime"].includes(one.property.type())) { @@ -36,7 +42,7 @@ export function convertFilter(filter?: Filter): FindConditions where[n] = LessThanOrEqual(new Date(one.value.to)); } else - where[n] = one.value; + where[n] = Like(`%${one.value}%`); } return where; } diff --git a/src/utils/getTitle.ts b/src/utils/getTitle.ts index fb765409..50432eaa 100644 --- a/src/utils/getTitle.ts +++ b/src/utils/getTitle.ts @@ -11,6 +11,9 @@ export async function getTitle(instance: BaseEntity | null | undefined): Promise const prop = instance[meta]; if(prop instanceof Function) return `${await (prop.bind(instance))()}`; + else if(prop instanceof Promise) + return `${await prop}`; + return `${prop}`; } else { diff --git a/tsconfig.json b/tsconfig.json index 37014c70..3ae721b2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,12 +3,13 @@ "module": "commonjs", "target": "es6", "lib": [ + "dom", "es2018" ], "sourceMap": true, "noImplicitAny": false, "strictNullChecks": true, - "esModuleInterop": false, + "esModuleInterop": true, "declaration": true, "declarationDir": "./lib", "outDir": "./lib",