import { dateFormat, isDate } from "sync-ql"; import { QueryRequest, NoData } from "../../services"; import { DataFilterOperation, DataFilterType, QuerySorting } from "../types/filter.type"; import { TableContext } from "../types/table.type"; export class Data { public static invertBoolean(value: DataFilterType | [DataFilterType, DataFilterType]): boolean { return Array.isArray(value) ? value.length > 0 && value[0] === true ? false : value.length > 0 && value[0] === false ? true : NoData : value === true ? false : value === false ? true : NoData } public static createQueryRequest(context: TableContext): QueryRequest { const isDateValue = (val: any, type: string) => { return val === null || val === undefined ? false : typeof val === 'boolean' ? false : typeof val === 'number' ? type === 'date' ? true : false : typeof val === 'string' ? val === 'true' || val === 'false' ? false : type === 'number' ? false : type === 'date' ? true : false : isDate(val) ? true : false } const column = context.columns.find(x => !!x.sort && x.sort !== 'disabled'); const select = context.columns.map(x => ({ name: x.name, as: x.as, schema: x.schema, table: x.table, type: !x.type || x.type === 'none' ? 'text' : x.type, })); const where = Object.keys(context.filters).map(k => { const column = context.columns.find(c => c.name === k); const type = !column || !column.type || column.type === 'none' ? 'text' : column.type; const toQuery = (value: DataFilterType | [DataFilterType, DataFilterType]): DataFilterType | [DataFilterType, DataFilterType] => { if (column && column.toQuery) { return column.toQuery(value); } return value; } const equalToBetween = context.filters[k].operation === 'equal' && isDateValue(context.filters[k].value, column.type) return column ? { column: { name: column.name, as: column.as, schema: column.schema, table: column.table, type, }, operation: equalToBetween ? 'between' : context.filters[k].operation, value: context.filters[k].operation === 'between' ? this.getFilterValue(toQuery(context.filters[k].value), 'between', column.type) : equalToBetween ? this.getFilterValue(toQuery(context.filters[k].value), 'between', column.type) : this.getFilterValue(toQuery(context.filters[k].value), context.filters[k].operation as DataFilterOperation, column.type)[0], } : null }); const orderBy: QuerySorting[] = column && column.sort && column.sort !== 'disabled' ? [{ column: { name: column.name, type: !column.type || column.type === 'none' ? 'text' : column.type, }, direction: column.sort }] : []; const query: QueryRequest = { 'SELECT': select, 'WHERE': where.filter( x => !!x && (!!x.value || x.value === false || x.value === 0) && (!Array.isArray(x.value) || (x.value.length > 0 && !!x.value[0])) ) as any, 'ORDER BY': orderBy, } as any return query; } public static createOptionsRequest(labelKey: string, searchKey: string, [text, currentValue]: [string, string]): QueryRequest { if (!labelKey) { throw `Label key can't be empty, null or undefined` } const labelColumn = { name: labelKey }; const searchColumn = { name: searchKey ?? labelKey }; const result: QueryRequest = { 'SELECT': labelColumn.name !== searchColumn.name ? [{ DISTINCT: { name: labelKey, type: 'text' } }, { name: searchKey, type: 'text' }] : [{ DISTINCT: { name: labelKey, type: 'text' } }], 'WHERE': !text && !!currentValue ? [{ column: searchColumn, operation: 'equal', value: currentValue }] : { column: labelColumn, value: text }, 'ORDER BY': [{ column: labelColumn, direction: 'asc' }], } as any return result; } public static includeKeys(query: QueryRequest): QueryRequest { if (query && query['SELECT']) { return Array.isArray(query['SELECT']) ? { ...query, 'SELECT': { "INCLUDE KEYS": query['SELECT'] } } as any : { ...query } } return { ...query }; } private static getFilterValue(value: DataFilterType | [DataFilterType, DataFilterType], operation: DataFilterOperation, type: string): [DataFilterType, DataFilterType] { const format = (val: any, index?: number) => { return val === null || val === undefined ? null : typeof val === 'boolean' ? val : typeof val === 'number' ? type === 'date' ? index ? `${dateFormat(val, 'yyyy-MM-dd')} 23:59:59:999` : `${dateFormat(val, 'yyyy-MM-dd')}` : Number(val) : typeof val === 'string' ? val === 'true' || val === 'false' ? Boolean(val) : type === 'number' ? Number(val) : type === 'date' ? `${dateFormat(val, 'yyyy-MM-dd')}` : val.toLowerCase() : isDate(val) ? index ? `${dateFormat(val, 'yyyy-MM-dd')} 23:59:59:999` : `${dateFormat(val, 'yyyy-MM-dd')}` : val } if (Array.isArray(value)) { value = value.filter(x => x !== undefined && x !== null) as any; } const result = typeof value === 'boolean' || typeof value === 'number' ? [value] : !value ? [null] as any : Array.isArray(value) ? value.length > 1 ? [format(value[0], 0), format(value[1], 1)] : value.length > 0 ? [format(value[0])] : [null] : [format(value)]; return operation === 'auto' && result[0] && Object.prototype.hasOwnProperty.call(result[0], 'value') ? [format(result[0].value)] : result; } public static isPaging(query: QueryRequest) { return query && query.LIMIT ? Array.isArray(query.LIMIT) ? !!query.LIMIT[0] : !!query.LIMIT.next : false } }