From 58770bf89f0926b684c34ec019e8583c1673a433 Mon Sep 17 00:00:00 2001 From: AntoXa PRO Date: Thu, 14 Sep 2023 18:19:36 +0300 Subject: [PATCH] big fix --- src/{form => forms}/ctrl.ts | 0 src/{form => forms}/fields.ts | 32 +++++++----- src/{form => forms}/helpers.ts | 0 src/{form => forms}/index.ts | 0 src/{form => forms}/model.ts | 2 +- src/index.ts | 8 +-- src/notification.ts | 2 +- src/{ => requests}/data-result.ts | 2 +- src/requests/find-filter.ts | 79 +++++++++++++++++++++++++++++ src/requests/index.ts | 3 ++ src/{ => requests}/pagination.ts | 84 ++++++++++--------------------- src/utils/index.ts | 1 + src/utils/objects.ts | 28 +++++++++++ 13 files changed, 164 insertions(+), 77 deletions(-) rename src/{form => forms}/ctrl.ts (100%) rename src/{form => forms}/fields.ts (95%) rename src/{form => forms}/helpers.ts (100%) rename src/{form => forms}/index.ts (100%) rename src/{form => forms}/model.ts (96%) rename src/{ => requests}/data-result.ts (96%) create mode 100644 src/requests/find-filter.ts create mode 100644 src/requests/index.ts rename src/{ => requests}/pagination.ts (50%) create mode 100644 src/utils/index.ts create mode 100644 src/utils/objects.ts diff --git a/src/form/ctrl.ts b/src/forms/ctrl.ts similarity index 100% rename from src/form/ctrl.ts rename to src/forms/ctrl.ts diff --git a/src/form/fields.ts b/src/forms/fields.ts similarity index 95% rename from src/form/fields.ts rename to src/forms/fields.ts index 25ebbce..cf18f9c 100644 --- a/src/form/fields.ts +++ b/src/forms/fields.ts @@ -36,8 +36,6 @@ export const bFieldsSchema = { string: z .string() .trim() - .min(2) - .max(64) .describe( FormSchemaCtrl.toString({ label: 'Строка', @@ -79,16 +77,6 @@ export const cFieldsSchema = z.object({ dateUpdate: fieldSchema(bFieldsSchema.date, { label: 'Дата изменения' }), - q: fieldSchema( - z.preprocess( - val => String(val).replace(regexSearch, ''), - bFieldsSchema.string - ), - { - label: 'Поиск', - component: 'ui-field-search' - } - ), name: fieldSchema(bFieldsSchema.string, { label: 'Название' }), @@ -187,5 +175,23 @@ export const cFieldsSchema = z.object({ days: fieldSchema(bFieldsSchema.number.array(), { label: 'Дни недели', component: 'ui-picker-days' - }) + }), + q: fieldSchema( + z.preprocess( + val => String(val).replace(regexSearch, ''), + bFieldsSchema.string + ), + { + label: 'Поиск', + component: 'ui-field-search' + } + ), + page: fieldSchema( + z.preprocess(val => Math.abs(Number(val)), bFieldsSchema.number), + { label: 'Страница' } + ), + limit: fieldSchema( + z.preprocess(val => Math.abs(Number(val)), bFieldsSchema.number), + { label: 'Лимит' } + ) }) diff --git a/src/form/helpers.ts b/src/forms/helpers.ts similarity index 100% rename from src/form/helpers.ts rename to src/forms/helpers.ts diff --git a/src/form/index.ts b/src/forms/index.ts similarity index 100% rename from src/form/index.ts rename to src/forms/index.ts diff --git a/src/form/model.ts b/src/forms/model.ts similarity index 96% rename from src/form/model.ts rename to src/forms/model.ts index 9e13620..34ffa4b 100644 --- a/src/form/model.ts +++ b/src/forms/model.ts @@ -27,7 +27,7 @@ export interface IFormModel { /** * Базовая модель для валидирования форм. */ -export class BaseFormModel implements IFormModel { +export class BaseFormModel implements IFormModel { _id: string dateCreate?: Date diff --git a/src/index.ts b/src/index.ts index 8789f68..d29de97 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ -export * from './entities' -export * from './form' +export * from './utils' export * from './notification' -export * from './pagination' -export * from './data-result' +export * from './entities' +export * from './requests' +export * from './forms' diff --git a/src/notification.ts b/src/notification.ts index 1a9ed09..c7850a2 100644 --- a/src/notification.ts +++ b/src/notification.ts @@ -7,7 +7,7 @@ export class NotificationItem implements TNotificationItem { code: string text: string - constructor(args: {code: string, text: string }) { + constructor(args: { code: string; text: string }) { this.code = args.code this.text = args.text } diff --git a/src/data-result.ts b/src/requests/data-result.ts similarity index 96% rename from src/data-result.ts rename to src/requests/data-result.ts index 14ffb73..801516d 100644 --- a/src/data-result.ts +++ b/src/requests/data-result.ts @@ -1,5 +1,5 @@ import type { TPagination } from './pagination' -import type { TNotificationItem } from './notification' +import type { TNotificationItem } from '../notification' import { Pagination } from './pagination' diff --git a/src/requests/find-filter.ts b/src/requests/find-filter.ts new file mode 100644 index 0000000..cde4e9b --- /dev/null +++ b/src/requests/find-filter.ts @@ -0,0 +1,79 @@ +import type { TPagination } from './pagination' + +import { z } from 'zod' +import { isEqual } from '../utils' +import { Pagination, paginationQuerySchema } from './pagination' +import { bFieldsSchema, cFieldsSchema, fieldSchema } from '../forms' + + +export const querySchema = cFieldsSchema + .pick({ q: true }) + .extend(paginationQuerySchema.shape) + .extend({ + sort: fieldSchema(bFieldsSchema.string.min(1).max(64), { + label: 'Сортировка' + }) + }) + +export type TQuery = z.infer + +/** + * Объект для преобразования фильтра в URL. + */ +export type TFindFilter = { + obj?: Omit + pagination?: TPagination + sort?: string +} + +export class FindFilter implements TFindFilter { + obj?: Omit + pagination?: TPagination + sort?: string + + constructor(query?: T) { + let queryCopy = Object.assign({}, query) + + // Pagination. + this.setPagination(queryCopy) + for (const key of Object.keys(this.pagination)) { + if (queryCopy[key]) delete queryCopy[key] + } + + // Sort. + if (queryCopy.sort) { + this.sort = queryCopy.sort + delete queryCopy.sort + } + + // Obj. + this.obj = queryCopy + } + + setPagination(pagination?: TPagination) { + this.pagination = new Pagination(pagination).toObject() + } + + static getQuery (filter: TFindFilter): T { + let query: any = {} + for(const key of Object.keys(filter.obj)) { + query[key] = filter.obj[key] + } + if (filter.pagination?.page) query.page = filter.pagination.page + if (filter.pagination?.limit) query.limit = filter.pagination.limit + if (filter.sort) query.sort = filter.sort + return query + } + + toObject(): TFindFilter { + return { + obj: this.obj, + pagination: this.pagination, + sort: this.sort + } + } + + isEqual(filters: TFindFilter[]) { + return isEqual([this, ...filters]) + } +} diff --git a/src/requests/index.ts b/src/requests/index.ts new file mode 100644 index 0000000..a3db826 --- /dev/null +++ b/src/requests/index.ts @@ -0,0 +1,3 @@ +export * from './pagination' +export * from './data-result' +export * from './find-filter' diff --git a/src/pagination.ts b/src/requests/pagination.ts similarity index 50% rename from src/pagination.ts rename to src/requests/pagination.ts index 89f0fbc..0933aa9 100644 --- a/src/pagination.ts +++ b/src/requests/pagination.ts @@ -1,26 +1,32 @@ import { z } from 'zod' -import { cFieldsSchema, fieldSchema } from './form' +import { cFieldsSchema, fieldSchema } from '../forms' -export const paginationSchema = z.object({ - page: fieldSchema(cFieldsSchema.shape.number, { - label: 'Номер страницы' - }), - limit: fieldSchema(cFieldsSchema.shape.number, { - label: 'Лимит на странице' - }), - total: fieldSchema(cFieldsSchema.shape.number, { - label: 'Общее кол-во' - }), - skip: fieldSchema(cFieldsSchema.shape.number, { - label: 'Пропустить' - }), - pages: fieldSchema(cFieldsSchema.shape.number, { - label: 'Кол-во всех страниц' +export const paginationSchema = cFieldsSchema + .pick({ + page: true, + limit: true }) -}) + .extend({ + total: fieldSchema(cFieldsSchema.shape.number, { + label: 'Общее кол-во' + }), + skip: fieldSchema(cFieldsSchema.shape.number, { + label: 'Пропустить' + }), + pages: fieldSchema(cFieldsSchema.shape.number, { + label: 'Кол-во всех страниц' + }) + }) + .describe('Пагинация') export type TPagination = z.infer +export const paginationQuerySchema = paginationSchema.pick({ + page: true, limit: true +}) + +export type TPaginationQuery = z.infer + // Константы. const DEFAULTS = { page: 1, limit: 10, maxLimit: 100 } @@ -32,43 +38,11 @@ export type TPaginationArguments = { total?: number } -export interface IPagination extends TPagination { +export class Pagination implements TPagination { /** * Максимальный лимит элементов. */ - get maxLimit(): number - - /** - * Парсинг аргументов. - * @param arg - Значение аргумента для парсинга. - * @param defaultReturnValue - Возвращаемое значение по умолчанию. - * @returns Возвращает абсолютное значение числа аргумента. - */ - parseArg( - arg: number | string | undefined, - defaultReturnValue: number - ): number - - /** - * Присваивает значения для основных свойств класса и считает кол-во - * пропускаемых элементов в зависимости от полученных аргументов. - * @param args - Аргументы пагинации. - * @returns Возвращает текущий экземпляр класса. - */ - set(args: TPaginationArguments): this - - /** - * Возвращает простой объект пагинации. - * @returns Объект пагинации. - */ - toObject(): TPagination -} - -export class Pagination implements IPagination { - /** - * Максимальный лимит элементов. - */ - private _maxLimit: number + #maxLimit: number page: number = DEFAULTS.page limit: number = DEFAULTS.limit @@ -89,14 +63,10 @@ export class Pagination implements IPagination { } constructor(args: TPaginationArguments = {}, maxLimit?: number) { - this._maxLimit = this.parseArg(maxLimit, DEFAULTS.maxLimit) + this.#maxLimit = this.parseArg(maxLimit, DEFAULTS.maxLimit) this.set(args) } - get maxLimit() { - return this._maxLimit - } - parseArg(arg: TPaginationParseArg, defaultReturnValue: number): number { return Pagination.parseArg(arg, defaultReturnValue) } @@ -118,7 +88,7 @@ export class Pagination implements IPagination { } // Проверка лимита. - if (this.limit > this.maxLimit) this.limit = this.maxLimit + if (this.limit > this.#maxLimit) this.limit = this.#maxLimit // Общее кол-во. if (args.total && args.total !== this.total) { diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..5749ede --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1 @@ +export * from './objects' diff --git a/src/utils/objects.ts b/src/utils/objects.ts new file mode 100644 index 0000000..983fe2b --- /dev/null +++ b/src/utils/objects.ts @@ -0,0 +1,28 @@ +export const isEqual = (objects: T[]) => { + for (let i = 0; i < objects.length; i++) { + const obj1 = objects[i] + const obj2 = objects[i + 1] + if (obj2) { + const keys1 = Object.keys(obj1) + const keys2 = Object.keys(obj2) + + if (keys1.length !== keys2.length) { + return false + } + + for(const key of keys1) { + if (typeof obj1[key] !== 'object') { + if (obj1[key] !== obj2[key]) { + return false + } + } else { + if (!isEqual([obj1[key], obj2[key]])) { + return false + } + } + } + } + } + + return true +}