@kuzntsv/uikit 1.0.124 → 1.0.126

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"kuzntsv-uikit-ui.mjs","names":[],"sources":["../../ui/src/base/base-toolbar/components/base-toolbar.component.ts","../../ui/src/base/base-toolbar/components/base-toolbar.component.html","../../ui/src/base/base-classes/base-class.ts","../../ui/src/base/base-classes/base-edit-dialog-data.ts","../../ui/src/base/base-classes/base-edit-class.ts","../../ui/src/base/base-classes/base-entity-action.ts","../../ui/src/services/avatar.service.ts","../../ui/src/services/local-storage-service.ts","../../ui/src/services/secure-image.service.ts","../../ui/src/services/export.service.ts","../../ui/src/services/sse/sse.service.ts","../../ui/src/base/base-classes/base-filter-class.ts","../../ui/src/base/base-classes/base-nav-bar-menu-class.ts","../../ui/src/shared/dialog/dialog.component.ts","../../ui/src/shared/dialog/dialog.component.html","../../ui/src/base/base-classes/base-page-class.ts","../../ui/src/base/base-classes/base-service-class.ts","../../ui/src/base/base-classes/base-signal-edit-class.ts","../../ui/src/base/base-classes/base-signal-filter-class.ts","../../ui/src/base/base-classes/base-filter.model.ts","../../ui/src/base/base-classes/base-signal-page-class.ts","../../ui/src/base/base-classes/base-signal-service-class.ts","../../ui/src/directives/disable-if-role.directive.ts","../../ui/src/directives/hide-if-forbidden-role.directive.ts","../../ui/src/directives/set-value.directive.ts","../../ui/src/guards/auth.guard.ts","../../ui/src/guards/redirect.guard.ts","../../ui/src/guards/role.guard.ts","../../ui/src/logger/logger.config.ts","../../ui/src/logger/logger.service.ts","../../ui/src/logger/logger.provider.ts","../../ui/src/models/sec-user-view.model.ts","../../ui/src/models/sec-user.model.ts","../../ui/src/pipes/safe.pipe.ts","../../ui/src/pipes/time.pipe.ts","../../ui/src/pipes/truncate.pipe.ts","../../ui/src/shared/chip-input-autocomplete/chip-input-autocomplete.component.ts","../../ui/src/shared/chip-input-autocomplete/chip-input-autocomplete.component.html","../../ui/src/shared/date-range-input/models/custom-date-adapter.ts","../../ui/src/shared/date-range-input/models/date-range.ts","../../ui/src/shared/date-range-input/date-range-input.component.ts","../../ui/src/shared/date-range-input/date-range-input.component.html","../../ui/src/shared/dialog/models/dialog-action.ts","../../ui/src/shared/empty/empty.ts","../../ui/src/shared/login/models/authenticate.ts","../../ui/src/shared/login/components/login-form/login-form.component.ts","../../ui/src/shared/login/components/login-form/login-form.component.html","../../ui/src/shared/login/components/permit-form/permit-form.component.ts","../../ui/src/shared/login/components/permit-form/permit-form.component.html","../../ui/src/shared/login/components/login-page/login-page.component.ts","../../ui/src/shared/login/components/login-page/login-page.component.html","../../ui/src/shared/navbar/navbar.ts","../../ui/src/shared/navbar/navbar.html","../../ui/src/shared/not-found/not-found.component.ts","../../ui/src/shared/not-found/not-found.component.html","../../ui/src/shared/select-autocomplete-with-vs/select-autocomplete-with-vs.component.ts","../../ui/src/shared/select-autocomplete-with-vs/select-autocomplete-with-vs.component.html","../../ui/src/shared/select-with-group/select-with-group.component.ts","../../ui/src/shared/select-with-group/select-with-group.component.html","../../ui/src/shared/table/models/table-state.ts","../../ui/src/shared/table/ru-paginator.intl.ts","../../ui/src/shared/table/table.component.ts","../../ui/src/shared/table/table.component.html","../../ui/src/validators/unique-code.validator.ts","../../ui/src/validators/unique-name.validator.ts"],"sourcesContent":["import {\n Component,\n computed,\n inject,\n input,\n output,\n ChangeDetectionStrategy,\n} from '@angular/core';\nimport { MatIconButton } from '@angular/material/button';\nimport { MatDivider } from '@angular/material/divider';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';\nimport { MatToolbar } from '@angular/material/toolbar';\nimport { MatTooltip } from '@angular/material/tooltip';\n\nimport { RoleService } from '@kuzntsv/uikit';\nimport { IContextMenuOptions } from '../../../shared/table';\n\n@Component({\n selector: 'ngx-uik-base-toolbar',\n templateUrl: 'base-toolbar.component.html',\n styleUrls: ['base-toolbar.component.scss'],\n changeDetection: ChangeDetectionStrategy.Eager,\n imports: [\n MatToolbar,\n MatIconButton,\n MatTooltip,\n MatIcon,\n MatMenu,\n MatDivider,\n MatMenuTrigger,\n MatMenuItem,\n ],\n})\nexport class BaseToolbarComponent {\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesNewBtn = input<string[]>([]);\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesEditBtn = input<string[]>([]);\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesRemoveBtn = input<string[]>([]);\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesCopyBtn = input<string[]>([]);\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesExcelBtn = input<string[]>([]);\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesCsvBtn = input<string[]>([]);\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesPdfBtn = input<string[]>([]);\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesPrintBtn = input<string[]>([]);\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesRefreshBtn = input<string[]>([]);\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesClearBtn = input<string[]>([]);\n\n // Состояния блокировки\n newBtnDisabled = input<boolean>(false);\n editBtnDisabled = input<boolean>(false);\n removeBtnDisabled = input<boolean>(false);\n copyBtnDisabled = input<boolean>(false);\n excelBtnDisabled = input<boolean>(false);\n csvBtnDisabled = input<boolean>(false);\n pdfBtnDisabled = input<boolean>(false);\n printBtnDisabled = input<boolean>(false);\n refreshBtnDisabled = input<boolean>(false);\n clearBtnDisabled = input<boolean>(false);\n\n // Тултипы\n newBtnTooltip = input<string>('Добавить');\n editBtnTooltip = input<string>('Изменить');\n removeBtnTooltip = input<string>('Удалить');\n copyBtnTooltip = input<string>('Скопировать');\n excelBtnTooltip = input<string>('Экспортировать в Excel');\n csvBtnTooltip = input<string>('Экспортировать в Csv');\n pdfBtnTooltip = input<string>('Экспортировать в Pdf');\n printBtnTooltip = input<string>('Печатать');\n refreshBtnTooltip = input<string>('Обновить данные');\n clearBtnTooltip = input<string>('Очистить фильтр');\n\n /** Список элементов контекстного меню. */\n newBtnOpt = input<IContextMenuOptions<string>[]>([]);\n\n // События\n clickedNewBtn = output();\n clickedEditBtn = output();\n clickedRemoveBtn = output();\n clickedCopyBtn = output();\n clickedExcelBtn = output();\n clickedCsvBtn = output();\n clickedPdfBtn = output();\n clickedPrintBtn = output();\n clickedRefreshBtn = output();\n clickedClearBtn = output();\n\n // DI\n // protected authService = inject(AuthService);\n protected roleService = inject(RoleService);\n\n // Вычисляемые сигналы видимости кнопок.\n readonly isNewBtnVisible = computed(() =>\n this.checkVisibility(this.rolesNewBtn()),\n );\n readonly isEditBtnVisible = computed(() =>\n this.checkVisibility(this.rolesEditBtn()),\n );\n readonly isRemoveBtnVisible = computed(() =>\n this.checkVisibility(this.rolesRemoveBtn()),\n );\n readonly isCopyBtnVisible = computed(() =>\n this.checkVisibility(this.rolesCopyBtn()),\n );\n readonly isExcelBtnVisible = computed(() =>\n this.checkVisibility(this.rolesExcelBtn()),\n );\n readonly isCsvBtnVisible = computed(() =>\n this.checkVisibility(this.rolesCsvBtn()),\n );\n readonly isPdfBtnVisible = computed(() =>\n this.checkVisibility(this.rolesPdfBtn()),\n );\n readonly isPrintBtnVisible = computed(() =>\n this.checkVisibility(this.rolesPrintBtn()),\n );\n readonly isRefreshBtnVisible = computed(() =>\n this.checkVisibility(this.rolesRefreshBtn()),\n );\n readonly isClearBtnVisible = computed(() =>\n this.checkVisibility(this.rolesClearBtn()),\n );\n\n /**\n * Внутренний метод для вычисления видимости.\n * Не вызывается напрямую из шаблона, а служит хелпером для декларативных computed.\n * Проверяет, заблокирован ли доступ к элементу на основе списка ограничений.\n * Возвращает true, если у пользователя есть запрещенная роль или передан маркер 'HIDE'.\n * Администратор (ADMIN) всегда игнорирует любые запреты и маркер 'HIDE'.\n */\n private checkVisibility(forbiddenRoles: string[]): boolean {\n return !this.roleService.hasForbiddenRole(forbiddenRoles);\n }\n\n onNewClick() {\n this.clickedNewBtn.emit();\n }\n\n onEditClick() {\n this.clickedEditBtn.emit();\n }\n\n onRemoveClick() {\n this.clickedRemoveBtn.emit();\n }\n\n onCopyClick() {\n this.clickedCopyBtn.emit();\n }\n\n onExcelClick() {\n this.clickedExcelBtn.emit();\n }\n\n onCsvClick() {\n this.clickedCsvBtn.emit();\n }\n\n onPdfClick() {\n this.clickedPdfBtn.emit();\n }\n\n onPrintClick() {\n this.clickedPrintBtn.emit();\n }\n\n onRefreshGridClick() {\n this.clickedRefreshBtn.emit();\n }\n\n onClearClick() {\n this.clickedClearBtn.emit();\n }\n}\n","<mat-toolbar>\r\n @if (isNewBtnVisible()) {\r\n @if (newBtnOpt() && newBtnOpt().length > 0) {\r\n <button [disabled]=\"newBtnDisabled()\" [matMenuTriggerFor]=\"menuNewBtn\"\r\n mat-icon-button [matTooltip]=\"newBtnTooltip()\">\r\n <mat-icon>add</mat-icon>\r\n </button>\r\n <mat-menu #menuNewBtn=\"matMenu\">\r\n @for (menuItem of newBtnOpt(); track menuItem) {\r\n @if (menuItem.title === '-' && !(menuItem.hideFn ? menuItem.hideFn(\"\") : menuItem.hide)) {\r\n <mat-divider></mat-divider>\r\n }\r\n @if (menuItem.title !== '-' && !(menuItem.hideFn ? menuItem.hideFn(\"\") : menuItem.hide)) {\r\n <button mat-menu-item\r\n (click)=\"menuItem.onClickFn ? menuItem.onClickFn('') : ''\"\r\n [disabled]=\"menuItem.disabledFn ? menuItem.disabledFn('') : menuItem.disabled\">\r\n @if (menuItem.icon) {\r\n <mat-icon>{{menuItem.icon}}</mat-icon>\r\n }\r\n {{ menuItem.title }}\r\n </button>\r\n }\r\n }\r\n </mat-menu>\r\n } \r\n @else {\r\n <button [disabled]=\"newBtnDisabled()\" (click)=\"onNewClick()\"\r\n mat-icon-button routerLink=\"new\" routerLinkActive=\"active\" [matTooltip]=\"newBtnTooltip()\">\r\n <mat-icon>add</mat-icon>\r\n </button>\r\n }\r\n }\r\n\r\n @if (isEditBtnVisible()) {\r\n <button [disabled]=\"editBtnDisabled()\" (click)=\"onEditClick()\"\r\n mat-icon-button routerLink=\"edit\" color=\"primary\" routerLinkActive=\"active\" [matTooltip]=\"editBtnTooltip()\">\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n }\r\n @if (isRemoveBtnVisible()) {\r\n <button [disabled]=\"removeBtnDisabled()\" (click)=\"onRemoveClick()\"\r\n mat-icon-button routerLink=\"delete\" color=\"warn\" routerLinkActive=\"active\" [matTooltip]=\"removeBtnTooltip()\">\r\n <mat-icon>remove</mat-icon>\r\n </button>\r\n }\r\n @if (isCopyBtnVisible()) {\r\n <button [disabled]=\"copyBtnDisabled()\" (click)=\"onCopyClick()\"\r\n mat-icon-button routerLink=\"delete\" routerLinkActive=\"active\" [matTooltip]=\"copyBtnTooltip()\">\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n }\r\n @if (isExcelBtnVisible()) {\r\n <button [disabled]=\"excelBtnDisabled()\" (click)=\"onExcelClick()\"\r\n mat-icon-button routerLink=\"excel\" routerLinkActive=\"active\" [matTooltip]=\"excelBtnTooltip()\">\r\n <mat-icon class=\"material-icons-outlined\">explicit</mat-icon>\r\n </button>\r\n }\r\n @if (isCsvBtnVisible()) {\r\n <button [disabled]=\"csvBtnDisabled()\" (click)=\"onCsvClick()\"\r\n mat-icon-button routerLink=\"csv\" routerLinkActive=\"active\" [matTooltip]=\"csvBtnTooltip()\">\r\n <mat-icon class=\"material-icons-outlined\">download</mat-icon>\r\n </button>\r\n }\r\n @if (isPdfBtnVisible()) {\r\n <button [disabled]=\"pdfBtnDisabled()\" (click)=\"onPdfClick()\"\r\n mat-icon-button routerLink=\"pdf\" routerLinkActive=\"active\" [matTooltip]=\"pdfBtnTooltip()\">\r\n <mat-icon class=\"material-icons-outlined\">picture_as_pdf</mat-icon>\r\n </button>\r\n }\r\n @if (isPrintBtnVisible()) {\r\n <button [disabled]=\"printBtnDisabled()\" (click)=\"onPrintClick()\"\r\n mat-icon-button routerLink=\"print\" routerLinkActive=\"active\" [matTooltip]=\"printBtnTooltip()\">\r\n <mat-icon class=\"material-icons-outlined\">print_outline</mat-icon>\r\n </button>\r\n }\r\n @if (isRefreshBtnVisible()) {\r\n <button [disabled]=\"refreshBtnDisabled()\" (click)=\"onRefreshGridClick()\"\r\n mat-icon-button routerLink=\"refresh\" routerLinkActive=\"active\" [matTooltip]=\"refreshBtnTooltip()\">\r\n <mat-icon>refresh</mat-icon>\r\n </button>\r\n }\r\n @if (isClearBtnVisible()) {\r\n <button [disabled]=\"clearBtnDisabled()\" (click)=\"onClearClick()\"\r\n mat-icon-button routerLink=\"clear\" routerLinkActive=\"active\" [matTooltip]=\"clearBtnTooltip()\">\r\n <mat-icon>clear</mat-icon>\r\n </button>\r\n }\r\n</mat-toolbar>\r\n","import { z } from 'zod';\r\n\r\n// Базовая схема, описывающая, что у каждого объекта ДОЛЖЕН быть id\r\nexport const BaseSchema = z.object({\r\n id: z.number(),\r\n});\r\n\r\n// TypeScript тип для базового объекта\r\nexport type BaseSchemaClass = z.infer<typeof BaseSchema>;\r\n\r\n/** @deprecated */\r\nexport interface BaseClass {\r\n id: number;\r\n}\r\n","/** Объект передаваемый в диалог формы редактирования, оперирует доменной моделью. */\r\nexport interface IEditDialogData<T, K = any> {\r\n action: Action;\r\n /** Здесь всегда доменная модель */\r\n entity: T;\r\n /** Дополнительные данные, например, фото. */\r\n extraData?: K;\r\n}\r\n\r\nexport enum Action {\r\n Add = 'Добавление',\r\n Edit = 'Изменение'\r\n}\r\n","import { Directive, inject, OnDestroy } from '@angular/core';\r\nimport { FormGroup } from '@angular/forms';\r\nimport { MatDialogRef } from '@angular/material/dialog';\r\nimport { Subscription } from 'rxjs';\r\nimport { NotificationService, RoleService, LoaderService } from '@kuzntsv/uikit';\r\n\r\nimport { Action, IEditDialogData } from './base-edit-dialog-data';\r\n\r\n@Directive()\r\nexport abstract class BaseEditClass<T> implements OnDestroy {\r\n /** Заголовок. */\r\n public abstract title: string;\r\n /** Данные диалога. */\r\n protected abstract dialogData?: IEditDialogData<T>;\r\n /** Форма. */\r\n public abstract form?: FormGroup<any>;\r\n /** Ссылка на диалог. */\r\n protected abstract dialogRef?: MatDialogRef<any, IEditDialogData<T> | null>;\r\n /** Сервис индикатор загрузки. */\r\n protected loaderService = inject(LoaderService);\r\n /** Сервис уведомлений. */\r\n protected notificationService = inject(NotificationService);\r\n /** Сервис ролей. */\r\n protected roleService = inject(RoleService);\r\n\r\n /** Объект для отписки (вызывается метод unsubscribe при уничтожении компонента). */\r\n protected subscription = new Subscription();\r\n\r\n ngOnDestroy(): void {\r\n this.subscription.unsubscribe();\r\n }\r\n\r\n onNoClick(event: MouseEvent): void {\r\n this.dialogRef?.close(null);\r\n event.preventDefault(); // иначе сработает onSubmit\r\n }\r\n\r\n onSubmit(): void {\r\n if (this.form) {\r\n if (this.form.valid) {\r\n if (this.dialogData)\r\n Object.keys(this.form.controls).forEach(\r\n (controlName) =>\r\n (this.dialogData!.entity[controlName as keyof T] =\r\n this.form?.controls[controlName].value),\r\n );\r\n this.dialogRef?.close(this.dialogData);\r\n } else {\r\n Object.keys(this.form.controls).forEach((controlName) =>\r\n this.form?.controls[controlName].markAsTouched(),\r\n );\r\n }\r\n }\r\n }\r\n\r\n formActionIsAdd(): boolean {\r\n return this.dialogData?.action === Action.Add;\r\n }\r\n\r\n formActionIsEdit(): boolean {\r\n return this.dialogData?.action === Action.Edit;\r\n }\r\n\r\n /**\r\n * Определяет видимость элемента на основе ЧЕРНОГО списка ролей.\r\n * По умолчанию элемент ВИДИМ. Скрывается (возвращает false), если у пользователя\r\n * есть запрещенная роль или если передан маркер скрытия фичи HIDE_ROLE_MARKER.\r\n */\r\n protected isVisibleForForbiddenRoles(forbiddenRoles: string[]): boolean {\r\n // Если роль запрещена, метод roleService вернет true.\r\n // Мы инвертируем (!), чтобы видимость (isMenuVisible) стала false.\r\n return !this.roleService.hasForbiddenRole(forbiddenRoles);\r\n }\r\n\r\n /**\r\n * Определяет видимость элемента на основе БЕЛОГО списка ролей.\r\n * По умолчанию элемент СКРЫТ. Показывается (возвращает true), только если у пользователя\r\n * есть хотя бы одна из разрешенных ролей. Администратор (ADMIN) всегда видит элемент.\r\n */\r\n protected isVisibleForAllowedRoles(allowedRoles: string[]): boolean {\r\n // Проверяем, есть ли у пользователя хотя бы одна роль из разрешенного списка.\r\n // (Предполагается, что у вашего roleService есть соответствующий метод, например, hasAnyRole)\r\n return this.roleService.hasAnyRole(allowedRoles);\r\n }\r\n}\r\n","export interface IEntityAction<T> {\r\n action: EntityAction;\r\n entity: T | undefined;\r\n}\r\n\r\nexport enum EntityAction {\r\n Init = 'Инициализация',\r\n Add = 'Добавление',\r\n Edit = 'Изменение',\r\n Delete = 'Удаление'\r\n}\r\n","import { HttpClient } from '@angular/common/http';\r\nimport { inject, Service } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\n\r\n@Service()\r\nexport class AvatarService {\r\n baseRoute = 'common/human/';\r\n\r\n private readonly http = inject(HttpClient);\r\n\r\n getAvatarById(idHuman: number): Observable<ArrayBuffer> {\r\n return this.http.get(this.baseRoute + idHuman + '/avatar', { responseType: 'arraybuffer' });\r\n }\r\n\r\n}\r\n","import { Service } from '@angular/core';\r\n\r\n@Service()\r\nexport class LocalStorageService {\r\n\r\n constructor() { }\r\n\r\n public saveData(key: string, value: string) {\r\n localStorage.setItem(key, value);\r\n }\r\n\r\n public getData(key: string) {\r\n return localStorage.getItem(key)\r\n }\r\n public removeData(key: string) {\r\n localStorage.removeItem(key);\r\n }\r\n\r\n public clearData() {\r\n localStorage.clear();\r\n }\r\n\r\n}\r\n","import { inject, Injectable } from '@angular/core';\r\nimport { HttpClient, HttpContext, HttpHeaders, HttpParams } from '@angular/common/http';\r\nimport { DomSanitizer, SafeUrl } from '@angular/platform-browser';\r\nimport { Observable, of } from 'rxjs';\r\nimport { map, catchError } from 'rxjs/operators';\r\nimport { API_NAME, X_SKIP_LOADER, X_SKIP_NOTIFICATION } from '@kuzntsv/uikit';\r\n\r\n@Injectable({\r\n providedIn: 'root' // Сервис будет доступен глобально во всем приложении\r\n})\r\nexport class SecureImageService {\r\n private readonly http = inject(HttpClient);\r\n private readonly sanitizer = inject(DomSanitizer);\r\n\r\n /**\r\n * Загружает защищенное изображение и возвращает SafeUrl\r\n */\r\n getSecureUrl(relativeUrl: string | null | undefined, apiKey: string = 'default', skipErrorNotification = false, skipLoader = false): Observable<SafeUrl | string> {\r\n if (!relativeUrl) {\r\n return of('');\r\n }\r\n\r\n const context = new HttpContext().set(API_NAME, apiKey);\r\n\r\n let headers = new HttpHeaders();\r\n if (skipErrorNotification)\r\n // переход от индекса к номеру страницы\r\n headers = headers.append(X_SKIP_NOTIFICATION, 'true');\r\n if (skipLoader)\r\n headers = headers.append(X_SKIP_LOADER, 'true');\r\n\r\n return this.http.get(relativeUrl, { headers, responseType: 'blob', context }).pipe(\r\n map((blob) => {\r\n const objectUrl = URL.createObjectURL(blob);\r\n return this.sanitizer.bypassSecurityTrustUrl(objectUrl);\r\n }),\r\n catchError((err) => {\r\n console.error(`[SecureImageService] Ошибка загрузки картинки с API \"${apiKey}\":`, err);\r\n return of(''); \r\n })\r\n );\r\n }\r\n}","import { Service } from '@angular/core';\r\n\r\n@Service()\r\nexport class ExportService {\r\n\r\n // Экспорт в CSV\r\n exportCSV(data: any, filename = 'data', arrHeader: any, newHeaders: any) {\r\n const csvData = this.convertToCSV(data, arrHeader, newHeaders);\r\n console.log(csvData);\r\n const blob = new Blob(['\\ufeff' + csvData], { type: 'text/csv;charset=utf-8;' });\r\n const dwldLink = document.createElement('a');\r\n const url = URL.createObjectURL(blob);\r\n const isSafariBrowser = navigator.userAgent.indexOf('Safari') !== -1 && navigator.userAgent.indexOf('Chrome') === -1;\r\n if (isSafariBrowser) { //if Safari open in new window to save file with random filename.\r\n dwldLink.setAttribute('target', '_blank');\r\n }\r\n dwldLink.setAttribute('href', url);\r\n dwldLink.setAttribute('download', filename + '.csv');\r\n dwldLink.style.visibility = 'hidden';\r\n document.body.appendChild(dwldLink);\r\n dwldLink.click();\r\n document.body.removeChild(dwldLink);\r\n }\r\n\r\n convertToCSV(objArray: any, headerList: any, newHeaders: any) {\r\n const array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;\r\n let str = '';\r\n let row = 'S.No,';\r\n for (const index in newHeaders) {\r\n if (Object.prototype.hasOwnProperty.call(newHeaders, index)) {\r\n row += newHeaders[index] + ',';\r\n }\r\n }\r\n row = row.slice(0, -1);\r\n str += row + '\\r\\n';\r\n for (let i = 0; i < array.length; i++) {\r\n let line = (i + 1) + '';\r\n for (const index in headerList) {\r\n if (Object.prototype.hasOwnProperty.call(newHeaders, index)) {\r\n const head = headerList[index];\r\n line += ',' + array[i][head];\r\n }\r\n }\r\n str += line + '\\r\\n';\r\n }\r\n return str;\r\n }\r\n\r\n}\r\n","import { DestroyRef, inject, Injectable } from \"@angular/core\";\r\nimport { Observable, Subject, takeUntil } from \"rxjs\";\r\n\r\nimport { SseUser } from \"./models/sse-user\";\r\nimport { Topic } from \"./models/topic\";\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class SseService<T> {\r\n private readonly destroyRef = inject(DestroyRef);\r\n private activeEventSource: EventSource | null = null;\r\n // Стрим-триггер для принудительной остановки коннектов извне\r\n private readonly stop$ = new Subject<void>();\r\n\r\n constructor() {\r\n this.destroyRef.onDestroy(() => this.closeSseEventSource());\r\n }\r\n\r\n createSseEventSource(baseUrl: string, user: SseUser, topic: Topic): Observable<T> {\r\n return new Observable<T>((subscriber) => {\r\n let eventSource: EventSource | null = null;\r\n let reconnectTimeoutId: any = null;\r\n let isClosed = false;\r\n\r\n // Слушаем глобальный стоп-сигнал сервиса\r\n const stopSubscription = this.stop$.subscribe(() => {\r\n cleanUp();\r\n subscriber.complete();\r\n });\r\n\r\n const connect = () => {\r\n if (isClosed) return;\r\n\r\n const topicUri = topic.getTopic(baseUrl, user);\r\n eventSource = new EventSource(topicUri);\r\n this.activeEventSource = eventSource;\r\n\r\n eventSource.onmessage = (event: MessageEvent) => {\r\n try {\r\n const messageData: T = JSON.parse(event.data);\r\n subscriber.next(messageData);\r\n } catch (err) {\r\n console.error('Ошибка парсинга SSE данных:', err);\r\n }\r\n };\r\n\r\n eventSource.onopen = () => {\r\n console.log('SSE connection opened.');\r\n };\r\n\r\n eventSource.onerror = (error: Event) => {\r\n console.error('SSE error:', error);\r\n \r\n if (eventSource) {\r\n eventSource.close();\r\n }\r\n\r\n if (!isClosed) {\r\n console.log('Reconnecting to SSE in 1 second...');\r\n reconnectTimeoutId = setTimeout(() => connect(), 1000);\r\n }\r\n };\r\n };\r\n\r\n const cleanUp = () => {\r\n isClosed = true;\r\n if (reconnectTimeoutId) {\r\n clearTimeout(reconnectTimeoutId);\r\n }\r\n if (eventSource) {\r\n eventSource.close();\r\n if (this.activeEventSource === eventSource) {\r\n this.activeEventSource = null;\r\n }\r\n console.log('SSE Connection closed');\r\n }\r\n };\r\n\r\n connect();\r\n\r\n // Срабатывает при отписке (.unsubscribe())\r\n return () => {\r\n stopSubscription.unsubscribe();\r\n cleanUp();\r\n };\r\n });\r\n }\r\n\r\n closeSseEventSource(): void {\r\n this.stop$.next(); // Посылаем сигнал всем активным Observable остановить реконнект\r\n if (this.activeEventSource) {\r\n this.activeEventSource.close();\r\n this.activeEventSource = null;\r\n console.log('SSE Connection force closed');\r\n }\r\n }\r\n}\r\n","import { Directive, inject, OnDestroy } from '@angular/core';\r\nimport { Subscription } from 'rxjs';\r\n\r\nimport { LocalStorageService } from '../../services';\r\nimport { NotificationService, LoaderService } from '@kuzntsv/uikit';\r\n\r\n@Directive()\r\nexport class BaseFilterClass implements OnDestroy {\r\n\r\n /** Сервис для работы с LocalStorage. */\r\n protected localStorageService = inject(LocalStorageService);\r\n /** Сервис индикатор загрузки. */\r\n protected loaderService = inject(LoaderService);\r\n /** Сервис уведомлений. */\r\n protected notificationService = inject(NotificationService);\r\n // eslint-disable-next-line no-magic-numbers\r\n defaultDebounceTime = 500;\r\n /** Объект для отписки (вызывается метод unsubscribe при уничтожении компонента). */\r\n subscription = new Subscription();\r\n\r\n constructor() {\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.subscription.unsubscribe();\r\n }\r\n}","import { Directive, inject } from \"@angular/core\";\r\nimport { MatMenuTrigger } from \"@angular/material/menu\";\r\nimport { Router } from \"@angular/router\";\r\nimport { RoleService } from '@kuzntsv/uikit';\r\n\r\n@Directive()\r\nexport class BaseNavBarMenuClass {\r\n\r\n protected roleService = inject(RoleService);\r\n protected router = inject(Router);\r\n\r\n /** \r\n * Определяет видимость пункта меню на основе ЧЕРНОГО списка ролей.\r\n * По умолчанию пункт меню ВИДИМ. Скрывается (возвращает false), если у пользователя \r\n * есть запрещенная роль или если передан маркер скрытия фичи HIDE_ROLE_MARKER.\r\n */\r\n protected isVisibleForForbiddenRoles(forbiddenRoles: string[]): boolean {\r\n // Если роль запрещена, метод roleService вернет true. \r\n // Мы инвертируем (!), чтобы видимость (isMenuVisible) стала false.\r\n return !this.roleService.hasForbiddenRole(forbiddenRoles);\r\n }\r\n\r\n /** \r\n * Определяет видимость пункта меню на основе БЕЛОГО списка ролей.\r\n * По умолчанию пункт меню СКРЫТ. Показывается (возвращает true), только если у пользователя \r\n * есть хотя бы одна из разрешенных ролей. Администратор (ADMIN) всегда видит элемент.\r\n */\r\n protected isVisibleForAllowedRoles(allowedRoles: string[]): boolean {\r\n // Проверяем, есть ли у пользователя хотя бы одна роль из разрешенного списка.\r\n // (Предполагается, что у вашего roleService есть соответствующий метод, например, hasAnyRole)\r\n return this.roleService.hasAnyRole(allowedRoles);\r\n }\r\n\r\n /** Нажата средняя кнопка (открыть ссылку в новой вкладке). */\r\n onMiddleClick(event: MouseEvent, baseUrl: string, menu: MatMenuTrigger) {\r\n // 1 -\tAuxiliary button pressed (usually the middle button)\r\n if (event.button === 1) {\r\n // event.preventDefault();\r\n menu.closeMenu();\r\n const urlTree = this.router.serializeUrl(\r\n this.router.createUrlTree([baseUrl]\r\n )\r\n );\r\n window.open(urlTree, '_blank');\r\n }\r\n }\r\n}","import { Component, inject } from '@angular/core';\nimport { MatButton } from '@angular/material/button';\nimport {\n MAT_DIALOG_DATA,\n MatDialogActions,\n MatDialogClose,\n MatDialogContent,\n MatDialogRef,\n MatDialogTitle,\n} from '@angular/material/dialog';\n\nimport { DialogData } from './models';\n\n@Component({\n selector: 'ngx-uik-dialog',\n templateUrl: './dialog.component.html',\n styleUrls: ['./dialog.component.css'],\n imports: [\n MatDialogTitle,\n MatDialogContent,\n MatDialogActions,\n MatButton,\n MatDialogClose,\n ],\n})\nexport class DialogComponent {\n readonly data = inject<DialogData>(MAT_DIALOG_DATA, { optional: true });\n readonly dialogRef = inject(MatDialogRef<DialogComponent>);\n\n readonly dialogData: DialogData = {\n id: this.data?.id ?? '',\n title: this.data?.title ?? 'Подтверждение',\n message: this.data?.message ?? '',\n btnNoTitle: this.data?.btnNoTitle ?? 'Нет',\n btnYesTitle: this.data?.btnYesTitle ?? 'Да',\n };\n}\n","<h1 mat-dialog-title>{{ dialogData.title }}</h1>\r\n<mat-dialog-content>\r\n <div style=\"white-space: pre-line\">{{ dialogData.message }}</div>\r\n</mat-dialog-content>\r\n<mat-dialog-actions align=\"end\">\r\n <button mat-raised-button [mat-dialog-close]=\"false\" cdkFocusInitial>{{ dialogData.btnNoTitle }}</button>\r\n <button mat-raised-button color=\"warn\" [mat-dialog-close]=\"dialogData.id\">{{ dialogData.btnYesTitle }}</button>\r\n</mat-dialog-actions>\r\n\r\n","import { Directive, OnDestroy, inject, signal } from '@angular/core';\r\nimport { MatDialog, MatDialogConfig, MatDialogRef } from '@angular/material/dialog';\r\nimport { MatMenuTrigger } from '@angular/material/menu';\r\nimport { Router } from '@angular/router';\r\nimport { Subject, Subscription, forkJoin, map, switchMap, tap } from 'rxjs';\r\n\r\nimport { LocalStorageService } from '../../services/local-storage-service';\r\nimport { DialogComponent } from '../../shared/dialog/dialog.component';\r\nimport { IContextMenuOptions, PageState, SortState, TableState } from '../../shared/table';\r\nimport { ObjectKeys, SortDirection, fnCbType, fnGetCountType, fnGetDataType, fnMapEntityType, fnType } from '../../types/types';\r\nimport { Action, IEditDialogData } from './base-edit-dialog-data';\r\nimport { NotificationService, LoaderService } from '@kuzntsv/uikit';\r\n\r\n@Directive()\r\nexport class BasePageClass<T> implements OnDestroy {\r\n\r\n protected dialog = inject(MatDialog);\r\n\r\n /** Данные для табличного компонента. */\r\n data = signal<T[]>([]);\r\n /** Количество записей по фильтру. */\r\n length = signal<number>(0);\r\n\r\n entityService: any;\r\n entityType: any;\r\n entityEditComponent: any;\r\n extraData?: any;\r\n\r\n // eslint-disable-next-line no-magic-numbers\r\n defaultPageIndex = 0;\r\n // eslint-disable-next-line no-magic-numbers\r\n defaultPageSize = 10;\r\n\r\n dialogEditWidth = 'auto';\r\n dialogRemoveWidth = '400px';\r\n\r\n routeAddress: string = '';\r\n\r\n /** Сообщение при удалении записи(й). */\r\n removalMessage: string = '';\r\n /** Заголовок страницы. */\r\n pageTitle: string = '';\r\n\r\n /**\r\n * Создание записи: вызывается перед открытием диалога.\r\n */\r\n beforeOpenDialogOnNewEvent: fnType<T>;\r\n /**\r\n * Редактирование записи: вызывается перед открытием диалога.\r\n */\r\n beforeOpenDialogOnEditEvent: fnType<T>;\r\n /**\r\n * Создание записи: вызывается перед сохранением объекта.\r\n */\r\n beforeSaveOnNewEvent: fnType<T>;\r\n /**\r\n * Редактирование записи: вызывается перед сохранением объекта.\r\n */\r\n beforeSaveOnEditEvent: fnType<T>;\r\n /**\r\n * Создание записи: вызывается после сохранения объекта.\r\n */\r\n afterSaveOnNewEvent: fnCbType<T>;\r\n /**\r\n * Редактирование записи: вызывается после сохранения объекта.\r\n */\r\n afterSaveOnEditEvent: fnCbType<T>;\r\n\r\n editorRoles: string[] = [];\r\n executeRoles: string[] = [];\r\n /** Список ролей, для которых скрыть элемент. */\r\n hideRoles: string[] = ['HIDE'];\r\n\r\n /** Загрузка данных. */\r\n loadData$: Subject<null> = new Subject<null>();\r\n /** Загрузка количества записей. */\r\n loadLength$: Subject<null> = new Subject<null>();\r\n /** Очистка фильтра. */\r\n clearFilter$: Subject<null> = new Subject<null>();\r\n\r\n /** Очистка фильтра (для очистки присвоить пустой объект '{}'). */\r\n clearFilter: any = null;\r\n\r\n /** Разрешен выбор нескольких строк. */\r\n allowMultiSelect = false;\r\n /** Выбранные строки в таблице. */\r\n selected: T[] = [];\r\n\r\n /** Состояние сортировки, пагинации. */\r\n tableState: TableState;\r\n\r\n /** Доступность кнопки \"Изменить\". */\r\n editBtnDisabled = true;\r\n /** Доступность кнопки \"Удалить\". */\r\n removeBtnDisabled = true;\r\n\r\n /** Разрешено ли отправлять событие rowDoubleClicked при двойном щелчке мышью. */\r\n dblClickedEventEnable = true;\r\n\r\n // Список элементов контекстного меню.\r\n opt: IContextMenuOptions<T>[] = [];\r\n\r\n // DI\r\n protected router = inject(Router);\r\n /** Сервис для работы с LocalStorage. */\r\n protected localStorageService = inject(LocalStorageService);\r\n /** Сервис индикатор загрузки. */\r\n protected loaderService = inject(LoaderService);\r\n /** Сервис уведомлений. */\r\n protected notificationService = inject(NotificationService);\r\n /** Объект для отписки (вызывается метод unsubscribe при уничтожении компонента). */\r\n subscription = new Subscription();\r\n\r\n constructor() {\r\n this.tableState = {\r\n sortActive: this.localStorageService.getData(this.constructor.name + 'SortActive') || '',\r\n sortDirection: (this.localStorageService.getData(this.constructor.name + 'SortDirection') || '') as SortDirection,\r\n pageIndex: Number(this.localStorageService.getData(this.constructor.name + 'PageIndex')) || this.defaultPageIndex,\r\n pageSize: Number(this.localStorageService.getData(this.constructor.name + 'PageSize')) || this.defaultPageSize\r\n };\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.subscription.unsubscribe();\r\n }\r\n\r\n subscribeToLoadData( fnGetData: fnGetDataType<T>, fnGetCount: fnGetCountType<T>, fnMapEntity?: fnMapEntityType<T>) {\r\n // отменять стримы, созданные ранее\r\n const subs = this.loadData$\r\n .pipe(\r\n tap(() => this.loaderService.show()),\r\n switchMap(() => fnGetData()),\r\n map(v => fnMapEntity ? v.map(fnMapEntity()) : v),\r\n )\r\n .subscribe({\r\n next: (response: T[]) => {\r\n this.data.set(response);\r\n this.loaderService.hide();\r\n },\r\n error: (error: any) => {\r\n this.loaderService.hide();\r\n console.log(error);\r\n this.notificationService.error('Произошла ошибка: ' + error, 0);\r\n }\r\n });\r\n this.subscription?.add(subs);\r\n\r\n const subs2 = this.loadLength$\r\n .pipe(\r\n switchMap(() => fnGetCount())\r\n )\r\n .subscribe({\r\n next: (response: number) => {\r\n this.length.set(response);\r\n },\r\n error: (error: any) => {\r\n console.log(error);\r\n this.notificationService.error('Произошла ошибка: ' + error, 0);\r\n }\r\n });\r\n this.subscription?.add(subs2);\r\n\r\n // загрузить данные и количество записей\r\n this.loadData$.next(null);\r\n this.loadLength$.next(null);\r\n }\r\n\r\n onPageChange(pageState: PageState) {\r\n this.tableState.pageIndex = pageState.pageIndex;\r\n this.tableState.pageSize = pageState.pageSize;\r\n this.localStorageService.saveData(this.constructor.name + 'PageIndex', pageState.pageIndex.toString());\r\n this.localStorageService.saveData(this.constructor.name + 'PageSize', pageState.pageSize.toString());\r\n\r\n this.loadData$.next(null);\r\n this.loadLength$.next(null);\r\n }\r\n\r\n onSortChange(sortState: SortState) {\r\n this.tableState.sortActive = sortState.sortActive;\r\n this.tableState.sortDirection = sortState.sortDirection;\r\n this.localStorageService.saveData(this.constructor.name + 'SortActive', sortState.sortActive);\r\n this.localStorageService.saveData(this.constructor.name + 'SortDirection', sortState.sortDirection);\r\n\r\n this.loadData$.next(null);\r\n this.loadLength$.next(null);\r\n }\r\n\r\n /** Событие изменение выбранных записей. */\r\n onSelectionChange(selected: T[]) {\r\n this.selected = selected;\r\n this.editBtnDisabledUpdate(this.selected);\r\n this.removeBtnDisabledUpdate(this.selected);\r\n }\r\n\r\n /** Обновление доступности кнопки \"Изменить\" - вызывается при изменении выбранных записей. */\r\n editBtnDisabledUpdate(selected: T[]) {\r\n this.editBtnDisabled = !(selected && selected.length === 1);\r\n }\r\n\r\n /** Обновление доступности кнопки \"Удалить\" - вызывается при изменении выбранных записей. */\r\n removeBtnDisabledUpdate(selected: T[]) {\r\n this.removeBtnDisabled = !(selected && selected.length > 0);\r\n }\r\n\r\n /** Событие двойной клик. */\r\n onRowDoubleClicked() {\r\n this.editEvent();\r\n }\r\n\r\n /** Событие создание. */\r\n newEvent() {\r\n if (this.entityEditComponent) {\r\n const data: IEditDialogData<T> = { action: Action.Add, entity: new this.entityType(null) };\r\n\r\n // Назначить значения полей объекта перед открытием диалога.\r\n if (this.beforeOpenDialogOnNewEvent) {\r\n this.beforeOpenDialogOnNewEvent(data.entity, data.extraData);\r\n }\r\n\r\n // Открытие окна\r\n const dialogRef = this.openDialog(this.entityEditComponent, data, this.dialog);\r\n\r\n // Обработка закрытия окна\r\n const subs = dialogRef.afterClosed().subscribe((result: IEditDialogData<T>) => {\r\n // Проверка результата\r\n if (result && result.entity && (Object.keys(result.entity).length !== 0)) {\r\n // Дополнительные действия перед сохранением объекта.\r\n if (this.beforeSaveOnNewEvent)\r\n this.beforeSaveOnNewEvent(result.entity, result.extraData);\r\n\r\n const subs = this.entityService.newObject(result.entity)\r\n .subscribe({\r\n next: (obj: any) => {\r\n // Дополнительные действия после сохранения объекта.\r\n if (this.afterSaveOnNewEvent) {\r\n const callback = () => {\r\n this.refreshEvent();\r\n this.notificationService.success('Запись добавлена.');\r\n }\r\n this.afterSaveOnNewEvent(callback.bind(this), obj, result.extraData);\r\n } else {\r\n this.refreshEvent();\r\n this.notificationService.success('Запись добавлена.');\r\n }\r\n },\r\n error: (error: any) => {\r\n console.log('error', error);\r\n this.notificationService.error('Произошла ошибка при добавлении записи: ' + error, 0);\r\n }\r\n });\r\n this.subscription.add(subs);\r\n }\r\n });\r\n this.subscription.add(subs);\r\n\r\n // Закрытие окна по нажатию Escape\r\n const subs2 = dialogRef.keydownEvents().subscribe((event: any) => {\r\n if (event.key === 'Escape') {\r\n dialogRef.close(null);\r\n }\r\n });\r\n this.subscription.add(subs2);\r\n } else {\r\n this.notificationService.warning('Действие не доступно.');\r\n }\r\n }\r\n\r\n /** Событие редактирование. */\r\n editEvent() {\r\n if (this.selected && this.selected.length === 1) {\r\n if (this.entityEditComponent) {\r\n const data: IEditDialogData<T> = { action: Action.Edit, entity: this.selected[0] };\r\n\r\n // Назначить значения полей объекта перед открытием диалога.\r\n if (this.beforeOpenDialogOnEditEvent) {\r\n this.beforeOpenDialogOnEditEvent(data.entity, data.extraData);\r\n }\r\n\r\n // Открытие окна\r\n const dialogRef = this.openDialog(this.entityEditComponent, data, this.dialog);\r\n\r\n // Обработка закрытия окна\r\n const subs = dialogRef.afterClosed().subscribe((result: IEditDialogData<T>) => {\r\n // Проверка результата\r\n if (result && result.entity && (Object.keys(result.entity).length !== 0)) {\r\n // Дополнительные действия перед сохранением объекта.\r\n if (this.beforeSaveOnEditEvent)\r\n this.beforeSaveOnEditEvent(result.entity, result.extraData);\r\n\r\n const subs = this.entityService.editObject(result.entity)\r\n .subscribe({\r\n next: () => {\r\n // Дополнительные действия после сохранения объекта.\r\n if (this.afterSaveOnEditEvent) {\r\n const callback = () => {\r\n this.refreshEvent();\r\n this.notificationService.success('Запись изменена.');\r\n }\r\n this.afterSaveOnEditEvent(callback.bind(this), result.entity, result.extraData);\r\n } else {\r\n this.refreshEvent();\r\n this.notificationService.success('Запись изменена.');\r\n }\r\n },\r\n error: (error: any) => {\r\n console.log('error', error);\r\n this.notificationService.error('Произошла ошибка при изменении записи: ' + error, 0);\r\n }\r\n });\r\n this.subscription.add(subs);\r\n }\r\n });\r\n this.subscription.add(subs);\r\n\r\n // Закрытие окна по нажатию Escape\r\n const subs2 = dialogRef.keydownEvents().subscribe((event: any) => {\r\n if (event.key === 'Escape') {\r\n dialogRef.close(null);\r\n }\r\n });\r\n this.subscription.add(subs2);\r\n } else {\r\n this.notificationService.warning('Действие не доступно.');\r\n }\r\n }\r\n }\r\n\r\n /** Событие удаление. */\r\n removeEvent() {\r\n // если выбрана запись(и)\r\n if (this.selected && this.selected.length > 0) {\r\n const dialogRef = this.openDialogRemoveConfirm(this.removalMessage);\r\n if (dialogRef) {\r\n const subs = dialogRef.afterClosed().subscribe((result: any) => {\r\n // при подтверждении возвращается 'delete'\r\n if (result === 'delete') {\r\n // готовим объект с запросами на удаление\r\n const sourcesObject: ObjectKeys = {};\r\n this.selected.forEach((item, index) => sourcesObject['obj' + index] = this.entityService.deleteObject(item));\r\n // ждем, когда выполнятся все запросы\r\n const subs = forkJoin(sourcesObject)\r\n .subscribe({\r\n next: () => {\r\n this.refreshEvent();\r\n this.notificationService.success('Выбранные записи удалены.');\r\n },\r\n error: (error: any) => {\r\n console.log('error', error);\r\n this.notificationService.error('Произошла ошибка при удалении записи: ' + error, 0);\r\n }\r\n });\r\n this.subscription.add(subs);\r\n }\r\n });\r\n this.subscription.add(subs);\r\n\r\n // Закрытие окна по нажатию Escape\r\n const subs2 = dialogRef.keydownEvents().subscribe((event: any) => {\r\n if (event.key === 'Escape') {\r\n dialogRef.close(null);\r\n }\r\n });\r\n this.subscription.add(subs2);\r\n }\r\n }\r\n }\r\n\r\n /** Событие обновления данных. */\r\n refreshEvent() {\r\n this.loadData$.next(null);\r\n this.loadLength$.next(null);\r\n }\r\n\r\n /** Событие очистки фильтра. */\r\n clearEvent() {\r\n this.clearFilter$.next(null);\r\n this.clearFilter = {};\r\n }\r\n\r\n /** Изменение сообщения об удалении. */\r\n onRemovalMessageChange(message: string) {\r\n this.removalMessage = message;\r\n }\r\n\r\n /** Изменение заголовка страницы. */\r\n onPageTitleChange(title: string) {\r\n this.pageTitle = title;\r\n }\r\n\r\n openDialog(entityComponent: any, data: IEditDialogData<T>, dialog: any) {\r\n // create dialog config\r\n const dialogConfig = new MatDialogConfig();\r\n dialogConfig.disableClose = true;\r\n dialogConfig.autoFocus = true;\r\n dialogConfig.width = this.dialogEditWidth;\r\n dialogConfig.data = data;\r\n dialogConfig.panelClass = this.entityType.name + '-edit-dialog';\r\n // return dialog\r\n return dialog.open(entityComponent, dialogConfig);\r\n }\r\n\r\n openDialogRemoveConfirm(removalMessage: string): MatDialogRef<DialogComponent> | undefined {\r\n let message = 'Вы хотите удалить ';\r\n message += removalMessage ?\r\n removalMessage :\r\n this.allowMultiSelect ? `выбранные записи (${this.selected.length})?` : 'выбранную запись?';\r\n return this.dialog.open(DialogComponent, {\r\n width: this.dialogRemoveWidth,\r\n data: {\r\n id: 'delete',\r\n title: 'Подтверждение',\r\n message: message,\r\n btnNoTitle: 'Отмена',\r\n btnYesTitle: 'Удалить'\r\n }\r\n });\r\n }\r\n\r\n // contextMenu: При щелчке ПКМ открыть в новой вкладке.\r\n protected onMiddleButton(baseUrl: string, queryParamName?: string, queryParamValue?: string) {\r\n return ($event: MouseEvent, item: T | undefined, contextMenu: MatMenuTrigger) => {\r\n // Нажата средняя кнопка (в новой вкладке).\r\n // 1 -\tAuxiliary button pressed (usually the middle button)\r\n if ($event.button === 1 && item) {\r\n //$event.preventDefault();\r\n contextMenu.closeMenu();\r\n // Converts the route into a string that can be used\r\n // with the window.open() function\r\n const url = this.router.serializeUrl(\r\n queryParamName && queryParamValue ?\r\n this.router.createUrlTree([baseUrl], { queryParams: { [queryParamName]: item[queryParamValue as keyof T] } })\r\n : this.router.createUrlTree([baseUrl])\r\n );\r\n window.open(url, '_blank');\r\n }\r\n };\r\n }\r\n\r\n // Action в таблице: При щелчке ПКМ открыть в новой вкладке.\r\n protected onActionMiddleButton(baseUrl: string, queryParamName?: string, queryParamValue?: string) {\r\n return ($event: MouseEvent, item: T | undefined) => {\r\n // Нажата средняя кнопка (в новой вкладке).\r\n // 1 -\tAuxiliary button pressed (usually the middle button)\r\n if ($event.button === 1 && item) {\r\n //$event.preventDefault();\r\n // Converts the route into a string that can be used\r\n // with the window.open() function\r\n const url = this.router.serializeUrl(\r\n queryParamName && queryParamValue ?\r\n this.router.createUrlTree([baseUrl], { queryParams: { [queryParamName]: item[queryParamValue as keyof T] } })\r\n : this.router.createUrlTree([baseUrl])\r\n );\r\n window.open(url, '_blank');\r\n }\r\n };\r\n }\r\n\r\n}\r\n\r\n","import { HttpClient, HttpContext, HttpParams } from '@angular/common/http';\r\nimport { inject, Service } from '@angular/core';\r\nimport { API_NAME } from '@kuzntsv/uikit';\r\nimport { Observable } from 'rxjs';\r\nimport { map } from 'rxjs/operators';\r\n\r\nimport { BaseClass } from './base-class';\r\n\r\n@Service()\r\nexport abstract class BaseServiceClass<T extends BaseClass> {\r\n abstract baseRoute: string;\r\n abstract entityType: any;\r\n\r\n protected countRoute = 'count';\r\n\r\n protected pageIndexParam = 'page';\r\n protected pageSizeParam = 'limit';\r\n protected sortColumnParam = 'column';\r\n protected directionParam = 'direction';\r\n\r\n // По умолчанию используем дефолтное API (пустая строка)\r\n protected apiContextName = ''; \r\n\r\n protected http = inject(HttpClient);\r\n\r\n getObjects(): Observable<T[]> {\r\n return this.http.get<T[]>(this.baseRoute, this.getHttpContext())\r\n .pipe(map(data => data.map(item => new this.entityType(item).deserialize(item))));\r\n }\r\n\r\n getObject(id: number): any {\r\n return this.http.get<T>(this.baseRoute + id, this.getHttpContext())\r\n .pipe(map(data => new this.entityType(data).deserialize(data)));\r\n }\r\n\r\n getCount(): Observable<number> {\r\n return this.http.get<number>(this.baseRoute + this.countRoute, this.getHttpContext());\r\n }\r\n\r\n getObjectsByPaging(pageIndex: number, pageSize: number, sortColumn: string, direction: string): Observable<T[]> {\r\n const params = this.getParams(pageIndex, pageSize, sortColumn, direction);\r\n return this.http.get<T[]>(this.baseRoute, { params, ...this.getHttpContext()})\r\n .pipe(map(data => data.map(item => new this.entityType(item).deserialize(item))));\r\n }\r\n\r\n newObject(entity: T): any {\r\n return this.http.post(this.baseRoute, entity, this.getHttpContext());\r\n }\r\n\r\n editObject(entity: T): any {\r\n return this.http.put(this.baseRoute + entity.id, entity, this.getHttpContext());\r\n }\r\n\r\n deleteObject(entity: T): any {\r\n return this.http.delete(this.baseRoute + entity.id, this.getHttpContext());\r\n }\r\n\r\n protected getParams(pageIndex: number, pageSize: number, sortColumn: string, direction: string): HttpParams {\r\n let params = new HttpParams();\r\n if (pageIndex + 1)\r\n // переход от индекса к номеру страницы\r\n params = params.append(this.pageIndexParam, pageIndex + 1);\r\n if (pageSize)\r\n params = params.append(this.pageSizeParam, pageSize);\r\n if (sortColumn)\r\n params = params.append(this.sortColumnParam, sortColumn);\r\n if (direction)\r\n params = params.append(this.directionParam, direction);\r\n return params;\r\n }\r\n\r\n // Вспомогательный метод для сборки опций HttpClient\r\n protected getHttpContext(): { context?: HttpContext } {\r\n // Если имя не задано (пустая строка, null или undefined), возвращаем пустой объект\r\n if (!this.apiContextName) {\r\n return {};\r\n }\r\n\r\n // Если имя задано, создаем и возвращаем контекст\r\n return {\r\n context: new HttpContext().set(API_NAME, this.apiContextName)\r\n };\r\n }\r\n}\r\n","import {\r\n computed,\r\n Directive,\r\n inject,\r\n linkedSignal,\r\n OnDestroy,\r\n WritableSignal,\r\n} from '@angular/core';\r\nimport { FieldTree } from '@angular/forms/signals';\r\nimport { MatDialogRef } from '@angular/material/dialog';\r\nimport { LoaderService, NotificationService, RoleService } from '@kuzntsv/uikit';\r\nimport { Subscription } from 'rxjs';\r\nimport { ZodObject } from 'zod';\r\n\r\nimport { Action, IEditDialogData } from './base-edit-dialog-data';\r\n\r\n@Directive()\r\nexport abstract class BaseSignalEditClass<\r\n TDomain extends Record<string, any>,\r\n TForm extends Record<string, any> = TDomain, // TForm по умолчанию равен TDomain\r\n> implements OnDestroy {\r\n /** Заголовок. */\r\n public abstract title: string;\r\n /** Данные диалога. */\r\n protected abstract dialogData: WritableSignal<IEditDialogData<TDomain>>;\r\n\r\n protected formAction = computed(() => this.dialogData().action);\r\n protected formActionIsAdd = computed(\r\n () => this.dialogData().action === Action.Add,\r\n );\r\n protected formActionIsEdit = computed(\r\n () => this.dialogData().action === Action.Edit,\r\n );\r\n\r\n /** Наследник может передать чистую DTO схему для очистки (опционально). */\r\n protected domainSchema?: ZodObject<any>;\r\n\r\n protected domainModel = computed(() => this.dialogData().entity);\r\n protected formModel = linkedSignal({\r\n source: this.domainModel,\r\n computation: (domainModel) => this.domainModelToFormModel(domainModel),\r\n });\r\n /** Форма. */\r\n protected abstract form: FieldTree<TForm>;\r\n /** Ссылка на диалог. */\r\n protected abstract dialogRef?: MatDialogRef<\r\n any,\r\n IEditDialogData<TDomain> | null\r\n >;\r\n\r\n /** Сервис индикатор загрузки. */\r\n protected loaderService = inject(LoaderService);\r\n /** Сервис уведомлений. */\r\n protected notificationService = inject(NotificationService);\r\n /** Сервис ролей. */\r\n protected roleService = inject(RoleService);\r\n\r\n /** Объект для отписки (вызывается метод unsubscribe при уничтожении компонента).\r\n * @deprecated\r\n */\r\n protected subscription = new Subscription();\r\n\r\n /**\r\n * Маппинг: Домен -> Форма.\r\n * Реализация по умолчанию делает поверхностную копию. Наследник может её переопределить.\r\n */\r\n protected domainModelToFormModel(domainModel: TDomain): TForm {\r\n return { ...domainModel } as unknown as TForm;\r\n }\r\n\r\n /**\r\n * Маппинг: Форма -> Домен.\r\n * Если передана схема домена (domainSchema), Zod сам удалит лишние поля и вернет чистый DTO\r\n * Реализация по умолчанию объединяет старый домен и новые поля формы.\r\n */\r\n protected formModelToDomainModel(\r\n formModel: TForm,\r\n originalDomain?: TDomain,\r\n ): TDomain {\r\n // 1. Если передана схема домена, Zod сам удалит лишние и вернет чистый DTO\r\n if (this.domainSchema) {\r\n return this.domainSchema.parse(formModel) as TDomain;\r\n }\r\n\r\n // 2. Фолбэк на стандартное поведение, если схемы нет\r\n return {\r\n ...originalDomain,\r\n ...(formModel as unknown as Partial<TDomain>),\r\n } as TDomain;\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.subscription.unsubscribe();\r\n }\r\n\r\n onNoClick(event: MouseEvent): void {\r\n this.dialogRef?.close(null);\r\n event.preventDefault(); // иначе сработает onSubmit\r\n }\r\n\r\n onSubmit(): void {\r\n if (this.form().valid()) {\r\n const updatedDomainEntity = this.formModelToDomainModel(this.formModel());\r\n this.dialogData.update(\r\n (currentData) =>\r\n ({\r\n ...currentData,\r\n entity: updatedDomainEntity,\r\n }) as IEditDialogData<TDomain>,\r\n );\r\n this.dialogRef?.close(this.dialogData());\r\n } else {\r\n this.form().markAsTouched();\r\n }\r\n }\r\n\r\n /**\r\n * Определяет видимость элемента на основе ЧЕРНОГО списка ролей.\r\n * По умолчанию элемент ВИДИМ. Скрывается (возвращает false), если у пользователя\r\n * есть запрещенная роль или если передан маркер скрытия фичи HIDE_ROLE_MARKER.\r\n */\r\n protected isVisibleForForbiddenRoles(forbiddenRoles: string[]): boolean {\r\n // Если роль запрещена, метод roleService вернет true.\r\n // Мы инвертируем (!), чтобы видимость (isMenuVisible) стала false.\r\n return !this.roleService.hasForbiddenRole(forbiddenRoles);\r\n }\r\n\r\n /**\r\n * Определяет видимость элемента на основе БЕЛОГО списка ролей.\r\n * По умолчанию элемент СКРЫТ. Показывается (возвращает true), только если у пользователя\r\n * есть хотя бы одна из разрешенных ролей. Администратор (ADMIN) всегда видит элемент.\r\n */\r\n protected isVisibleForAllowedRoles(allowedRoles: string[]): boolean {\r\n // Проверяем, есть ли у пользователя хотя бы одна роль из разрешенного списка.\r\n // (Предполагается, что у вашего roleService есть соответствующий метод, например, hasAnyRole)\r\n return this.roleService.hasAnyRole(allowedRoles);\r\n }\r\n}\r\n","import {\r\n Directive,\r\n effect,\r\n inject,\r\n input,\r\n model,\r\n signal\r\n} from '@angular/core';\r\nimport { NotificationService, LoaderService } from '@kuzntsv/uikit';\r\n\r\nimport { SafeFilterState } from './base-filter.model';\r\n\r\n@Directive()\r\nexport abstract class BaseSignalFilterClass<F extends SafeFilterState> {\r\n /** Сервис индикатор загрузки. */\r\n protected loaderService = inject(LoaderService);\r\n\r\n /** Сервис уведомлений. */\r\n protected notificationService = inject(NotificationService);\r\n\r\n /** Время на успокоение значения фильтра. */\r\n // eslint-disable-next-line no-magic-numbers\r\n defaultDebounceTime = 500;\r\n\r\n /**\r\n * writable-сигнал, Принимаем текущее реактивное состояние фильтров с родительской страницы.\r\n * Родитель передает значение через [(filters)]=\"pageFilters()\".\r\n * При любом изменении полей ввода обновляйте сигнал целиком через метод update.\r\n *\r\n * @example\r\n * updateCategory(newCategory: string) {\r\n * this.filters.update(prev => ({ ...prev, category: newCategory }));\r\n * }\r\n */\r\n\r\n /** Двусторонняя модель теперь строго типизирована вашим SafeFilterState. */\r\n filters = model<F>({} as F);\r\n\r\n /** Входной сигнал для сброса состояния формы. */\r\n clearFilter = input<any>(null);\r\n\r\n protected isUseInternalFilterSignal = 0;\r\n\r\n /** \r\n * Локальный сигнал формы, чтобы изолировать ввод пользователя \r\n * от родительской двусторонней модели filters. \r\n * \r\n * ### ВАЖНО: \r\n * * При использовании для создания формы и в шаблоне, необходимо задать \r\n * isUseInternalFilterSignal = 1, чтобы при clearFilter чистилась правильная модель.\r\n * \r\n * @example\r\n * protected isUseInternalFilterSignal = 1;\r\n * protected form = form(this.internalFilterSignal, (schemaPath) => {\r\n * // Дебаунсим только текстовые инпут dept. Остальные обновятся мгновенно.\r\n * debounce(schemaPath.dept, this.defaultDebounceTime);\r\n * });\r\n *\r\n * */\r\n // Передаем начальное значение из родительского filters()\r\n protected internalFilterSignal = signal<F>({ ...this.filters() });\r\n\r\n protected abstract DEFAULT_FILTER: F;\r\n\r\n /**\r\n * Объект для отписки от внутренних подписок (например, valueChanges у FormControl).\r\n * Метод unsubscribe вызывается при уничтожении компонента.\r\n */\r\n // В сигнальных формах текущее значение поля — это обычный Signal (а точнее, ModelSignal),\r\n // который синхронизирует состояние UI и вашей модели. Чтобы реагировать на его изменения,\r\n // вместо .valueChanges.subscribe(...) используются стандартные инструменты работы с сигналами:\r\n // 1. computed() — если вам нужно создать производное (зависимое) значение на основе измененных данных формы.\r\n // 2. effect() — если при изменении значения формы нужно выполнить побочный эффект\r\n // (например, отправить запрос на бэкенд или вызвать метод сервиса)\r\n // subscription = new Subscription();\r\n\r\n // ngOnDestroy(): void {\r\n // this.subscription.unsubscribe();\r\n // }\r\n\r\n constructor() {\r\n // 3. Синхронизация: когда ЛОКАЛЬНЫЙ сигнал стабилизировался (учел все дебаунсы),\r\n // мы пушим его в родительскую model. Теперь в [(filters)] данные уходят с задержкой!\r\n effect(() => {\r\n if (this.isUseInternalFilterSignal) {\r\n const stableLocalValue = this.internalFilterSignal();\r\n\r\n // Чтобы избежать зацикливания, обновляем родителя только если данные реально отличаются\r\n if (\r\n JSON.stringify(stableLocalValue) !== JSON.stringify(this.filters())\r\n ) {\r\n this.filters.set(stableLocalValue);\r\n }\r\n }\r\n });\r\n\r\n // очистка фильтра\r\n // 4. Слушаем сброс фильтра от родителя: сбрасываем локальное состояние\r\n effect(() => {\r\n const clearFilter = this.clearFilter();\r\n if (this.isUseInternalFilterSignal)\r\n this.internalFilterSignal.set({ ...this.DEFAULT_FILTER });\r\n else this.filters.set({ ...this.DEFAULT_FILTER });\r\n });\r\n }\r\n\r\n /** Мгновенная очистка конкретного поля по крестику у двусторонней модели filters. */\r\n clearField(fieldName: keyof F, defaultValue: any) {\r\n this.filters.update((prev) => ({\r\n ...prev,\r\n [fieldName]: defaultValue,\r\n }));\r\n }\r\n\r\n /** Мгновенная очистка конкретного поля по крестику. */\r\n clearFieldInternal(fieldName: keyof F, defaultValue: any) {\r\n this.internalFilterSignal.update((prev) => ({\r\n ...prev,\r\n [fieldName]: defaultValue,\r\n }));\r\n }\r\n}\r\n","// Ограничиваем типы значений, которые могут быть в фильтрах\r\n// 1. Исходные типы (то, что может прийти на вход функции)\r\nexport type FilterValue = \r\n | string \r\n | number \r\n | boolean \r\n | readonly string[] \r\n | readonly number[] \r\n | null \r\n | undefined;\r\n\r\nexport type SafeFilterState = Readonly<Record<string, FilterValue>>;\r\n\r\n// 2. Типы результата (строго БЕЗ null и undefined)\r\nexport type CleanFilterValue = Exclude<FilterValue, null | undefined>;\r\n\r\n// Конечный тип для результата работы функции\r\nexport type CleanFilterState = Readonly<Record<string, CleanFilterValue>>;\r\n\r\n// 2. Типы результата (строго БЕЗ null и undefined)\r\nexport function cleanFilterParams(filters: SafeFilterState): CleanFilterState {\r\n // Внутренний объект делаем мутабельным для удобства сборки\r\n const cleanParams: Record<string, CleanFilterValue> = {};\r\n\r\n Object.keys(filters).forEach((key) => {\r\n const value = filters[key];\r\n\r\n // 1. Удаляем null, undefined и пустые строки, пустые массивы\r\n if (isEmptyFilterValue(value)) {\r\n return;\r\n }\r\n\r\n // TS теперь уверен, что здесь value не является null или undefined\r\n cleanParams[key] = value as CleanFilterValue;\r\n });\r\n\r\n // Возвращаем объект, который автоматически приводится к типу CleanFilterState (Readonly)\r\n return cleanParams;\r\n}\r\n\r\n/**\r\n * Проверяет, является ли значение фильтра пустым (мусорным),\r\n * которое нужно удалить из URL/LocalStorage, чтобы не спамить бэкенд.\r\n */\r\nexport function isEmptyFilterValue(value: unknown): boolean {\r\n if (value === null || value === undefined || value === '' || value === '-1' || value === 0) {\r\n return true;\r\n }\r\n \r\n if (Array.isArray(value) && value.length === 0) {\r\n return true;\r\n }\r\n \r\n // Дополнительно можно добавить (при необходимости в будущем):\r\n // if (typeof value === 'string' && value.trim() === '') return true;\r\n\r\n return false;\r\n}\r\n","import { HttpResourceRef } from '@angular/common/http';\r\nimport {\r\n Directive,\r\n OnDestroy,\r\n computed,\r\n effect,\r\n inject,\r\n signal,\r\n} from '@angular/core';\r\nimport {\r\n MatDialog,\r\n MatDialogConfig,\r\n MatDialogRef,\r\n} from '@angular/material/dialog';\r\nimport { MatMenuTrigger } from '@angular/material/menu';\r\nimport { Router } from '@angular/router';\r\nimport {\r\n formatZodError,\r\n HIDE_ROLE_MARKER,\r\n LoaderService,\r\n UIKIT_NOTIFICATION_TOKEN,\r\n} from '@kuzntsv/uikit';\r\nimport { Subscription, forkJoin } from 'rxjs';\r\nimport z from 'zod';\r\n\r\nimport { LocalStorageService } from '../../services/local-storage-service';\r\nimport { DialogComponent } from '../../shared/dialog/dialog.component';\r\nimport {\r\n IContextMenuOptions,\r\n PageState,\r\n SortState,\r\n TableState,\r\n} from '../../shared/table';\r\nimport {\r\n ObjectKeys,\r\n SortDirection,\r\n fnCbType,\r\n fnMapEntityType,\r\n fnType,\r\n} from '../../types/types';\r\nimport { BaseSchemaClass } from './base-class';\r\nimport { Action, IEditDialogData } from './base-edit-dialog-data';\r\nimport { SafeFilterState, isEmptyFilterValue } from './base-filter.model';\r\n\r\n@Directive()\r\nexport abstract class BaseSignalPageClass<\r\n TDomain extends BaseSchemaClass,\r\n TForm extends BaseSchemaClass = TDomain,\r\n TFilter extends SafeFilterState = Record<string, never>,\r\n> implements OnDestroy {\r\n protected dialog = inject(MatDialog);\r\n // Для перехода при открытии новых вкладок (щелчок средней кнопкой мыши).\r\n protected router = inject(Router);\r\n /** Сервис для работы с LocalStorage. */\r\n protected localStorageService = inject(LocalStorageService);\r\n /** Сервис индикатор загрузки. */\r\n protected loaderService = inject(LoaderService);\r\n /** Сервис уведомлений. */\r\n protected notificationService = inject(UIKIT_NOTIFICATION_TOKEN);\r\n\r\n protected entityService: any;\r\n protected entityEditComponent?: any;\r\n protected extraData?: any;\r\n\r\n // Гарантирует, что переданная схема валидирует объект, содержащий как минимум { id: number }\r\n protected abstract readonly schemaDTO: z.ZodType<TDomain>;\r\n\r\n protected readonly filterSchema?: z.ZodType<TFilter>;\r\n protected readonly defaultFilters?: TFilter;\r\n\r\n private get storagePrefix(): string {\r\n return `${this.constructor.name}_Filter_`;\r\n }\r\n\r\n // eslint-disable-next-line no-magic-numbers\r\n defaultPageIndex = 0;\r\n // eslint-disable-next-line no-magic-numbers\r\n defaultPageSize = 10;\r\n\r\n dialogEditWidth = 'auto';\r\n dialogRemoveWidth = '400px';\r\n\r\n /** Сообщение при удалении записи(й). */\r\n removalMessage: string = '';\r\n /** Заголовок страницы. */\r\n pageTitle: string = '';\r\n\r\n /**\r\n * Создание записи: вызывается перед открытием диалога.\r\n */\r\n beforeOpenDialogOnNewEvent: fnType<TDomain>;\r\n /**\r\n * Редактирование записи: вызывается перед открытием диалога.\r\n */\r\n beforeOpenDialogOnEditEvent: fnType<TDomain>;\r\n /**\r\n * Создание записи: вызывается перед сохранением объекта.\r\n */\r\n beforeSaveOnNewEvent: fnType<TDomain>;\r\n /**\r\n * Редактирование записи: вызывается перед сохранением объекта.\r\n */\r\n beforeSaveOnEditEvent: fnType<TDomain>;\r\n /**\r\n * Создание записи: вызывается после сохранения объекта.\r\n */\r\n afterSaveOnNewEvent: fnCbType<TDomain>;\r\n /**\r\n * Редактирование записи: вызывается после сохранения объекта.\r\n */\r\n afterSaveOnEditEvent: fnCbType<TDomain>;\r\n\r\n editorRoles: string[] = [];\r\n executeRoles: string[] = [];\r\n /** Список ролей, для которых скрыть элемент. */\r\n hideRoles: string[] = [HIDE_ROLE_MARKER];\r\n\r\n /** Разрешен выбор нескольких строк. */\r\n allowMultiSelect = false;\r\n /** Разрешено ли отправлять событие rowDoubleClicked при двойном щелчке мышью. */\r\n dblClickedEventEnable = true;\r\n /** Выбранные строки в таблице. */\r\n selected = signal<TForm[]>([]);\r\n\r\n /** Доступность кнопки \"Изменить\". */\r\n protected editBtnDisabled = computed(\r\n () => !(this.selected() && this.selected().length === 1),\r\n );\r\n /** Доступность кнопки \"Удалить\". */\r\n protected removeBtnDisabled = computed(\r\n () => !(this.selected() && this.selected().length > 0),\r\n );\r\n\r\n /** Маппинг TDomain в TForm */\r\n protected fnMapEntity: fnMapEntityType<TForm> | undefined;\r\n\r\n /** Ссылка на ресурс получения данных, определяет потомок. */\r\n protected dataResource!: HttpResourceRef<TForm[]>;\r\n /** Ссылка на ресурс получения количества записей, определяет потомок. */\r\n protected countResource!: HttpResourceRef<number>;\r\n\r\n /** Данные для табличного компонента. */\r\n data = computed<TForm[]>(() => {\r\n // Защита на момент старта super()\r\n if (!this.dataResource) return [];\r\n\r\n // ЗАЩИТА: Если ресурс упал (например, 401 или 500),\r\n // возвращаем пустой массив, НЕ вызывая .value(), чтобы не спамить в консоль\r\n if (this.dataResource.error()) {\r\n return [];\r\n }\r\n\r\n const rawData = this.dataResource?.value() || [];\r\n return this.fnMapEntity && Array.isArray(rawData)\r\n ? rawData.map(this.fnMapEntity())\r\n : rawData;\r\n });\r\n\r\n /** Количество записей по фильтру. */\r\n length = computed<number>(() => {\r\n // Защита на момент старта super()\r\n if (!this.countResource) return 0;\r\n\r\n // Защита от спама при ошибке подсчета количества\r\n if (this.countResource.error()) {\r\n return 0;\r\n }\r\n\r\n return this.countResource?.value() || 0;\r\n });\r\n\r\n /** Глобальный индикатор загрузки (для спиннера на странице) */\r\n isLoading = computed<boolean>(() => {\r\n if (!this.dataResource || !this.countResource) return false;\r\n\r\n // Если ресурсы уже в состоянии ошибки, значит загрузка завершена\r\n if (this.dataResource.error() || this.countResource.error()) {\r\n return false;\r\n }\r\n\r\n return this.dataResource.isLoading() || this.countResource.isLoading();\r\n });\r\n\r\n /** Список элементов контекстного меню. */\r\n opt: IContextMenuOptions<TForm>[] = [];\r\n\r\n /** Объект для отписки (вызывается метод unsubscribe при уничтожении компонента). */\r\n subscription = new Subscription();\r\n\r\n /** Единое реактивное хранилище для ВСЕХ фильтров текущей страницы. */\r\n filters = signal<TFilter>({} as TFilter);\r\n\r\n /** Очистка фильтра. (для очистки присвоить пустой объект '{}'). */\r\n clearFilters = signal<any>(null);\r\n\r\n /** Состояние сортировки, пагинации. */\r\n tableState = signal<TableState>({\r\n sortActive: '',\r\n sortDirection: '' as SortDirection,\r\n pageIndex: this.defaultPageIndex,\r\n pageSize: this.defaultPageSize,\r\n });\r\n\r\n constructor() {\r\n this.tableState.set({\r\n sortActive:\r\n this.localStorageService.getData(\r\n this.constructor.name + 'SortActive',\r\n ) || '',\r\n sortDirection: (this.localStorageService.getData(\r\n this.constructor.name + 'SortDirection',\r\n ) || '') as SortDirection,\r\n pageIndex:\r\n Number(\r\n this.localStorageService.getData(this.constructor.name + 'PageIndex'),\r\n ) || this.defaultPageIndex,\r\n pageSize:\r\n Number(\r\n this.localStorageService.getData(this.constructor.name + 'PageSize'),\r\n ) || this.defaultPageSize,\r\n });\r\n\r\n // 3. Эффект для отслеживания изменений фильтров (бывший trackFilterChanges)\r\n let previousFilters = { ...this.filters() };\r\n\r\n effect(() => {\r\n const currentFilters = this.filters();\r\n\r\n let filterChanged = false;\r\n\r\n (Object.keys(currentFilters) as Array<keyof TFilter>).forEach((key) => {\r\n const prevVal = previousFilters[key];\r\n const currVal = currentFilters[key];\r\n\r\n if (prevVal !== currVal) {\r\n filterChanged = true;\r\n const storageKey = `${this.storagePrefix}${String(key)}`;\r\n\r\n // Интегрируем логику вашей функции очистки для LocalStorage!\r\n // Если значение превратилось в то, что cleanFilterParams считает мусором,\r\n // удаляем ключ из localStorage, чтобы не копить пустые значения.\r\n const isValueEmpty = isEmptyFilterValue(currVal);\r\n if (isValueEmpty) {\r\n this.localStorageService.removeData(storageKey);\r\n console.log(\r\n 'removeData',\r\n storageKey,\r\n 'prevVal=',\r\n prevVal,\r\n 'currVal=',\r\n currVal,\r\n );\r\n } else {\r\n this.localStorageService.saveData(\r\n storageKey,\r\n JSON.stringify(currVal),\r\n );\r\n }\r\n }\r\n });\r\n\r\n if (filterChanged) {\r\n // Сброс пагинации:\r\n this.tableState.update((prev) => ({ ...prev, pageIndex: 0 }));\r\n }\r\n previousFilters = { ...currentFilters };\r\n });\r\n\r\n // Перехватываем ошибку Zod из safeParseData прямо в эффекте\r\n effect(() => {\r\n const dataError = this.dataResource?.error();\r\n\r\n if (dataError) {\r\n // Так как safeParseData выбрасывает инстанс Error,\r\n // достаем из него понятный текстовый лог через .message\r\n const errorMessage =\r\n dataError instanceof Error ? dataError.message : String(dataError);\r\n\r\n console.log(\r\n `[Валидация данных] Ошибка структуры JSON от сервера:\\n${errorMessage}`,\r\n );\r\n\r\n this.notificationService.error(\r\n 'Произошла ошибка при чтении/парсинге данных с сервера.',\r\n 0,\r\n );\r\n }\r\n });\r\n\r\n // Отдельный эффект для счетчика пагинации\r\n effect(() => {\r\n const countError = this.countResource?.error();\r\n if (countError) {\r\n const errorMessage =\r\n countError instanceof Error ? countError.message : String(countError);\r\n\r\n console.log(`[Валидация пагинации] ${errorMessage}`);\r\n\r\n this.notificationService.error(\r\n 'Произошла ошибка при чтении/парсинге данных с сервера.',\r\n 0,\r\n );\r\n }\r\n });\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.subscription.unsubscribe();\r\n }\r\n\r\n /** Разово прочитать сохраненные значения из localStorage при старте страницы,\r\n * провалидировать их через Zod-схему и записать в сигнал filters */\r\n protected initFilters(): void {\r\n if (!this.filterSchema || !this.defaultFilters) return;\r\n\r\n const initial: Record<string, any> = { ...this.defaultFilters };\r\n\r\n Object.keys(this.defaultFilters).forEach((key) => {\r\n const storageKey = `${this.storagePrefix}${key}`;\r\n const rawValue = this.localStorageService.getData(storageKey);\r\n console.log(\r\n 'initFilters, storageKey=',\r\n storageKey,\r\n 'rawValue=',\r\n rawValue,\r\n );\r\n\r\n if (rawValue !== null && rawValue !== undefined) {\r\n try {\r\n initial[key] = JSON.parse(rawValue);\r\n } catch {\r\n initial[key] = rawValue;\r\n }\r\n }\r\n });\r\n\r\n // Валидируем собранный объект через Zod-схему\r\n const validation = this.filterSchema.safeParse(initial);\r\n console.log(\r\n 'initFilters, validation=',\r\n validation,\r\n 'validation.success=',\r\n validation.success,\r\n 'validation.data=',\r\n validation.data,\r\n 'validation.error=',\r\n validation.error ? formatZodError(validation.error ,this.constructor.name) : \r\n 'empty',\r\n );\r\n // Записываем финальные данные в сигнал.\r\n // Как только этот сигнал заполнится, автоматически среагирует и effect() в конструкторе,\r\n // и ресурс dataResource для загрузки данных.\r\n this.filters.set(\r\n validation.success ? validation.data : this.defaultFilters,\r\n );\r\n }\r\n\r\n /** Событие очистки фильтра. */\r\n protected clearEvent() {\r\n if (!this.defaultFilters) return;\r\n\r\n Object.keys(this.defaultFilters).forEach((key) => {\r\n this.localStorageService.removeData(`${this.storagePrefix}${key}`);\r\n });\r\n this.tableState.update((prev) => ({ ...prev, pageIndex: 0 }));\r\n this.filters.set({ ...this.defaultFilters });\r\n this.clearFilters.set({});\r\n }\r\n\r\n /** Установка значение фильтра.\r\n * @param key - имя фильтра.\r\n * @param value - значение.\r\n */\r\n protected setFilter<K extends keyof TFilter>(key: K, value: TFilter[K]) {\r\n const storageKey = `${this.storagePrefix}${String(key)}`;\r\n\r\n // При любом изменении фильтра сбрасываем пагинацию на первую страницу\r\n this.tableState.update((prev) => ({ ...prev, pageIndex: 0 }));\r\n\r\n const isValueEmpty = isEmptyFilterValue(value);\r\n\r\n // Сайд-эффекты для LocalStorage\r\n if (isValueEmpty) {\r\n this.localStorageService.removeData(storageKey);\r\n } else {\r\n this.localStorageService.saveData(storageKey, JSON.stringify(value));\r\n }\r\n\r\n // Обновление сигнала\r\n this.filters.update((prev) => {\r\n if (isValueEmpty) {\r\n const next = { ...prev };\r\n delete next[key];\r\n return next;\r\n }\r\n return { ...prev, [key]: value };\r\n });\r\n }\r\n\r\n /**\r\n * Обновление нескольких фильтров одновременно (пачкой)\r\n * @param fields Пачка фильтров в виде объекта { имяПоля: значение }\r\n */\r\n protected setFilters(fields: Partial<TFilter>) {\r\n // 1. При изменении пачки фильтров сбрасываем пагинацию на первую страницу ОДИН раз\r\n this.tableState.update((prev) => ({ ...prev, pageIndex: 0 }));\r\n\r\n // 2. Обновляем сигнал фильтров атомарно\r\n this.filters.update((prev) => {\r\n // Создаем копию текущего состояния фильтров\r\n const next = { ...prev };\r\n\r\n // Проходим по каждому переданному ключу в пачке\r\n (Object.keys(fields) as Array<keyof TFilter>).forEach((key) => {\r\n const value = fields[key];\r\n const storageKey = `${this.constructor.name}_Filter_${String(key)}`;\r\n\r\n // Проверяем значение на \"пустоту\"\r\n const isValueEmpty = isEmptyFilterValue(value);\r\n\r\n if (isValueEmpty) {\r\n // Сайд-эффект для LocalStorage: удаляем\r\n this.localStorageService.removeData(storageKey);\r\n // Удаляем ключ из нового состояния фильтров\r\n delete next[key];\r\n } else {\r\n // Сайд-эффект для LocalStorage: сохраняем\r\n this.localStorageService.saveData(storageKey, JSON.stringify(value));\r\n // Записываем значение в новое состояние фильтров\r\n next[key] = value as any;\r\n }\r\n });\r\n\r\n // Возвращаем новый объект. Изменение ссылки триггерит ОДИН HTTP-запрос в httpResource\r\n return next;\r\n });\r\n }\r\n\r\n onPageChange(pageState: PageState) {\r\n this.localStorageService.saveData(\r\n this.constructor.name + 'PageIndex',\r\n pageState.pageIndex.toString(),\r\n );\r\n this.localStorageService.saveData(\r\n this.constructor.name + 'PageSize',\r\n pageState.pageSize.toString(),\r\n );\r\n\r\n this.tableState.update((prev) => ({\r\n ...prev,\r\n pageIndex: pageState.pageIndex,\r\n pageSize: pageState.pageSize,\r\n }));\r\n }\r\n\r\n onSortChange(sortState: SortState) {\r\n this.localStorageService.saveData(\r\n this.constructor.name + 'SortActive',\r\n sortState.sortActive,\r\n );\r\n this.localStorageService.saveData(\r\n this.constructor.name + 'SortDirection',\r\n sortState.sortDirection,\r\n );\r\n\r\n this.tableState.update((prev) => ({\r\n ...prev,\r\n sortActive: sortState.sortActive,\r\n sortDirection: sortState.sortDirection,\r\n }));\r\n }\r\n\r\n /** Событие изменение выбранных записей. */\r\n onSelectionChange(selected: TForm[]) {\r\n this.selected.set(selected);\r\n }\r\n\r\n /** Событие двойной клик. */\r\n onRowDoubleClicked() {\r\n if (this.dblClickedEventEnable) this.editEvent();\r\n }\r\n\r\n /** Событие создание. */\r\n newEvent() {\r\n if (this.entityEditComponent) {\r\n // Zod создаст дефолтный объект, пропустив пустой объект {} через парсер\r\n const defaultEntity = this.schemaDTO.parse({});\r\n\r\n const data: IEditDialogData<TDomain> = {\r\n action: Action.Add,\r\n entity: defaultEntity,\r\n };\r\n\r\n // Назначить значения полей объекта перед открытием диалога.\r\n if (this.beforeOpenDialogOnNewEvent) {\r\n this.beforeOpenDialogOnNewEvent(data.entity, data.extraData);\r\n }\r\n\r\n // Открытие окна\r\n const dialogRef = this.openDialog(\r\n this.entityEditComponent,\r\n data,\r\n this.dialog,\r\n );\r\n\r\n // Обработка закрытия окна\r\n const subs = dialogRef\r\n .afterClosed()\r\n .subscribe((result: IEditDialogData<TDomain>) => {\r\n // Проверка результата\r\n if (\r\n result &&\r\n result.entity &&\r\n Object.keys(result.entity).length !== 0\r\n ) {\r\n // Дополнительные действия перед сохранением объекта.\r\n if (this.beforeSaveOnNewEvent)\r\n this.beforeSaveOnNewEvent(result.entity, result.extraData);\r\n\r\n const subs = this.entityService.newObject(result.entity).subscribe({\r\n next: (obj: any) => {\r\n // Дополнительные действия после сохранения объекта.\r\n if (this.afterSaveOnNewEvent) {\r\n const callback = () => {\r\n this.refreshEvent();\r\n this.notificationService.success('Запись добавлена.');\r\n };\r\n this.afterSaveOnNewEvent(\r\n callback.bind(this),\r\n obj,\r\n result.extraData,\r\n );\r\n } else {\r\n this.refreshEvent();\r\n this.notificationService?.success('Запись добавлена.');\r\n }\r\n },\r\n error: (error: any) => {\r\n console.log('error', error);\r\n this.notificationService.error(\r\n 'Произошла ошибка при добавлении записи: ' + error,\r\n 0,\r\n );\r\n },\r\n });\r\n this.subscription.add(subs);\r\n }\r\n });\r\n this.subscription.add(subs);\r\n\r\n // Закрытие окна по нажатию Escape\r\n const subs2 = dialogRef.keydownEvents().subscribe((event: any) => {\r\n if (event.key === 'Escape') {\r\n dialogRef.close(null);\r\n }\r\n });\r\n this.subscription.add(subs2);\r\n } else {\r\n this.notificationService.warning('Действие не доступно.');\r\n }\r\n }\r\n\r\n /** Событие редактирование. */\r\n editEvent() {\r\n if (this.selected() && this.selected().length === 1) {\r\n if (this.entityEditComponent) {\r\n const data: IEditDialogData<TDomain> = {\r\n action: Action.Edit,\r\n entity: this.formModelToDomainModel(this.selected()[0]),\r\n };\r\n\r\n // Назначить значения полей объекта перед открытием диалога.\r\n if (this.beforeOpenDialogOnEditEvent) {\r\n this.beforeOpenDialogOnEditEvent(data.entity, data.extraData);\r\n }\r\n\r\n // Открытие окна\r\n const dialogRef = this.openDialog(\r\n this.entityEditComponent,\r\n data,\r\n this.dialog,\r\n );\r\n\r\n // Обработка закрытия окна\r\n const subs = dialogRef\r\n .afterClosed()\r\n .subscribe((result: IEditDialogData<TDomain>) => {\r\n // Проверка результата\r\n if (\r\n result &&\r\n result.entity &&\r\n Object.keys(result.entity).length !== 0\r\n ) {\r\n // Дополнительные действия перед сохранением объекта.\r\n if (this.beforeSaveOnEditEvent)\r\n this.beforeSaveOnEditEvent(result.entity, result.extraData);\r\n\r\n const subs = this.entityService\r\n .editObject(result.entity)\r\n .subscribe({\r\n next: () => {\r\n // Дополнительные действия после сохранения объекта.\r\n if (this.afterSaveOnEditEvent) {\r\n const callback = () => {\r\n this.refreshEvent();\r\n this.notificationService.success('Запись изменена.');\r\n };\r\n this.afterSaveOnEditEvent(\r\n callback.bind(this),\r\n result.entity,\r\n result.extraData,\r\n );\r\n } else {\r\n this.refreshEvent();\r\n this.notificationService.success('Запись изменена.');\r\n }\r\n },\r\n error: (error: any) => {\r\n console.log('error', error);\r\n this.notificationService.error(\r\n 'Произошла ошибка при изменении записи: ' + error,\r\n 0,\r\n );\r\n },\r\n });\r\n this.subscription.add(subs);\r\n }\r\n });\r\n this.subscription.add(subs);\r\n\r\n // Закрытие окна по нажатию Escape\r\n const subs2 = dialogRef.keydownEvents().subscribe((event: any) => {\r\n if (event.key === 'Escape') {\r\n dialogRef.close(null);\r\n }\r\n });\r\n this.subscription.add(subs2);\r\n } else {\r\n this.notificationService.warning('Действие не доступно.');\r\n }\r\n }\r\n }\r\n\r\n /** Событие удаление. */\r\n removeEvent() {\r\n // если выбрана запись(и)\r\n if (this.selected() && this.selected().length > 0) {\r\n const dialogRef = this.openDialogRemoveConfirm(this.removalMessage);\r\n if (dialogRef) {\r\n const subs = dialogRef.afterClosed().subscribe((result: any) => {\r\n // при подтверждении возвращается 'delete'\r\n if (result === 'delete') {\r\n // готовим объект с запросами на удаление\r\n const sourcesObject: ObjectKeys = {};\r\n this.selected().forEach(\r\n (item, index) =>\r\n (sourcesObject['obj' + index] =\r\n this.entityService.deleteObject(item)),\r\n );\r\n // ждем, когда выполнятся все запросы\r\n const subs = forkJoin(sourcesObject).subscribe({\r\n next: () => {\r\n this.refreshEvent();\r\n this.notificationService.success('Выбранные записи удалены.');\r\n },\r\n error: (error: any) => {\r\n console.log('error', error);\r\n this.notificationService?.error(\r\n 'Произошла ошибка при удалении записи: ' + error,\r\n 0,\r\n );\r\n },\r\n });\r\n this.subscription.add(subs);\r\n }\r\n });\r\n this.subscription.add(subs);\r\n\r\n // Закрытие окна по нажатию Escape\r\n const subs2 = dialogRef.keydownEvents().subscribe((event: any) => {\r\n if (event.key === 'Escape') {\r\n dialogRef.close(null);\r\n }\r\n });\r\n this.subscription.add(subs2);\r\n }\r\n }\r\n }\r\n\r\n /** Событие обновления данных. */\r\n refreshEvent() {\r\n this.dataResource?.reload();\r\n this.countResource?.reload();\r\n }\r\n\r\n /** Изменение сообщения об удалении. */\r\n onRemovalMessageChange(message: string) {\r\n this.removalMessage = message;\r\n }\r\n\r\n /** Изменение заголовка страницы. */\r\n onPageTitleChange(title: string) {\r\n this.pageTitle = title;\r\n }\r\n\r\n openDialog(\r\n entityComponent: any,\r\n data: IEditDialogData<TDomain>,\r\n dialog: any,\r\n ) {\r\n // create dialog config\r\n const dialogConfig = new MatDialogConfig();\r\n dialogConfig.disableClose = true;\r\n dialogConfig.autoFocus = true;\r\n dialogConfig.width = this.dialogEditWidth;\r\n dialogConfig.data = data;\r\n dialogConfig.panelClass = this.constructor.name + '-edit-dialog';\r\n // return dialog\r\n return dialog.open(entityComponent, dialogConfig);\r\n }\r\n\r\n openDialogRemoveConfirm(\r\n removalMessage: string,\r\n ): MatDialogRef<DialogComponent> | undefined {\r\n let message = 'Вы хотите удалить ';\r\n message += removalMessage\r\n ? removalMessage\r\n : this.allowMultiSelect\r\n ? `выбранные записи (${this.selected().length})?`\r\n : 'выбранную запись?';\r\n return this.dialog.open(DialogComponent, {\r\n width: this.dialogRemoveWidth,\r\n data: {\r\n id: 'delete',\r\n title: 'Подтверждение',\r\n message: message,\r\n btnNoTitle: 'Отмена',\r\n btnYesTitle: 'Удалить',\r\n },\r\n });\r\n }\r\n\r\n // contextMenu: При щелчке ПКМ открыть в новой вкладке.\r\n protected onMiddleButton(\r\n baseUrl: string,\r\n queryParamName?: string,\r\n queryParamValue?: string,\r\n ) {\r\n return (\r\n $event: MouseEvent,\r\n item: TForm | undefined,\r\n contextMenu: MatMenuTrigger,\r\n ) => {\r\n // Нажата средняя кнопка (в новой вкладке).\r\n // 1 -\tAuxiliary button pressed (usually the middle button)\r\n if ($event.button === 1 && item) {\r\n //$event.preventDefault();\r\n contextMenu.closeMenu();\r\n // Converts the route into a string that can be used\r\n // with the window.open() function\r\n const url = this.router.serializeUrl(\r\n queryParamName && queryParamValue\r\n ? this.router.createUrlTree([baseUrl], {\r\n queryParams: {\r\n [queryParamName]: item[queryParamValue as keyof TForm],\r\n },\r\n })\r\n : this.router.createUrlTree([baseUrl]),\r\n );\r\n window.open(url, '_blank');\r\n }\r\n };\r\n }\r\n\r\n // Action в таблице: При щелчке ПКМ открыть в новой вкладке.\r\n protected onActionMiddleButton(\r\n baseUrl: string,\r\n queryParamName?: string,\r\n queryParamValue?: string,\r\n ) {\r\n return ($event: MouseEvent, item: TForm | undefined) => {\r\n // Нажата средняя кнопка (в новой вкладке).\r\n // 1 -\tAuxiliary button pressed (usually the middle button)\r\n if ($event.button === 1 && item) {\r\n //$event.preventDefault();\r\n // Converts the route into a string that can be used\r\n // with the window.open() function\r\n const url = this.router.serializeUrl(\r\n queryParamName && queryParamValue\r\n ? this.router.createUrlTree([baseUrl], {\r\n queryParams: {\r\n [queryParamName]: item[queryParamValue as keyof TForm],\r\n },\r\n })\r\n : this.router.createUrlTree([baseUrl]),\r\n );\r\n window.open(url, '_blank');\r\n }\r\n };\r\n }\r\n\r\n /**\r\n * Маппинг: Форма -> Домен.\r\n * Реализация по умолчанию объединяет старый домен и новые поля формы.\r\n */\r\n protected formModelToDomainModel(\r\n formModel: TForm,\r\n originalDomain?: TDomain,\r\n ): TDomain {\r\n return {\r\n ...originalDomain,\r\n ...(formModel as unknown as Partial<TDomain>),\r\n } as TDomain;\r\n }\r\n}\r\n","import {\r\n HttpClient,\r\n HttpContext,\r\n HttpParams,\r\n httpResource,\r\n HttpResourceRef,\r\n} from '@angular/common/http';\r\nimport { inject, Injectable, signal } from '@angular/core';\r\nimport { API_NAME, formatZodError } from '@kuzntsv/uikit';\r\nimport { tap } from 'rxjs';\r\nimport z from 'zod';\r\n\r\nimport { TableState } from '../../shared';\r\nimport { BaseSchemaClass } from './base-class';\r\nimport { cleanFilterParams, SafeFilterState } from './base-filter.model';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport abstract class BaseSignalServiceClass<T extends BaseSchemaClass> {\r\n abstract baseRoute: string;\r\n\r\n // Гарантирует, что переданная схема валидирует объект, содержащий как минимум { id: number }\r\n protected abstract readonly schema: z.ZodType<T>;\r\n\r\n // Схема для валидации и очистки при ЗАПИСИ\r\n protected schemaDTO?: z.ZodType<any>;\r\n\r\n protected countRoute = 'count';\r\n\r\n protected pageIndexParam = 'page';\r\n protected pageSizeParam = 'limit';\r\n protected sortColumnParam = 'column';\r\n protected directionParam = 'direction';\r\n\r\n // По умолчанию используем дефолтное API (пустая строка)\r\n protected apiContextName = '';\r\n\r\n protected http = inject(HttpClient);\r\n\r\n // Реактивный триггер для перезапуска списков\r\n protected readonly _refreshTrigger = signal(0);\r\n\r\n // Вспомогательный метод для ручного или автоматического пинка триггера\r\n public refresh(): void {\r\n this._refreshTrigger.update((v) => v + 1);\r\n }\r\n\r\n // 1. Возвращает ResourceRef, который сразу можно использовать в шаблонах или других ресурсах\r\n getObjects(): HttpResourceRef<T[]> {\r\n return httpResource<T[]>(\r\n () => {\r\n // Читаем триггер обновления, чтобы ресурс перезапустился автоматически\r\n this._refreshTrigger();\r\n return { url: this.baseRoute };\r\n },\r\n {\r\n ...this.getHttpContext(),\r\n defaultValue: [],\r\n // Ключевое улучшение v22: трансформация данных прямо на уровне ресурса\r\n parse: (data: unknown) => {\r\n if (!data) return [];\r\n // Валидация через Zod вернет строго тип T, у которого точно есть id\r\n // Было: return z.array(this.schema).parse(data);\r\n return this.safeParseData(z.array(this.schema), data, true); // Стало\r\n },\r\n },\r\n );\r\n }\r\n\r\n getObject(\r\n id: number | (() => number | null | undefined),\r\n ): HttpResourceRef<T | null> {\r\n // Приводим id к функции-сигналу для обеспечения реактивности httpResource\r\n const idSignal = typeof id === 'function' ? id : () => id;\r\n\r\n return httpResource<T | null>(\r\n () => {\r\n // Читаем триггер обновления, чтобы ресурс перезапустился автоматически\r\n this._refreshTrigger();\r\n\r\n const currentId = idSignal();\r\n // Защита: если ID еще нет, не делаем запрос и переводим ресурс в состояние Idle\r\n if (currentId === null || currentId === undefined) {\r\n return undefined;\r\n }\r\n\r\n return { url: `${this.baseRoute}${currentId}` };\r\n },\r\n {\r\n ...this.getHttpContext(),\r\n defaultValue: null,\r\n parse: (data: unknown) => {\r\n if (!data) return null;\r\n // Было: return this.schema.parse(data);\r\n return this.safeParseData(this.schema, data); // Стало\r\n },\r\n },\r\n );\r\n }\r\n\r\n getCount(): HttpResourceRef<number> {\r\n return httpResource<number>(\r\n () => {\r\n // Читаем триггер обновления, чтобы ресурс перезапустился автоматически\r\n this._refreshTrigger();\r\n return {\r\n url: `${this.baseRoute}${this.countRoute}`,\r\n };\r\n },\r\n {\r\n ...this.getHttpContext(),\r\n defaultValue: 0,\r\n parse: (data: unknown) => z.coerce.number().parse(data),\r\n },\r\n );\r\n }\r\n\r\n getObjectsByPaging(tableStateGetter: () => TableState): HttpResourceRef<T[]> {\r\n return httpResource<T[]>(\r\n () => {\r\n // Читаем триггер, чтобы httpResource реагировал на вызов .refresh()\r\n this._refreshTrigger();\r\n\r\n const tableState = tableStateGetter(); \r\n\r\n return {\r\n url: this.baseRoute,\r\n params: this.buildTableParams(tableState),\r\n };\r\n },\r\n {\r\n ...this.getHttpContext(),\r\n defaultValue: [],\r\n parse: (data) => {\r\n if (!data) return [];\r\n // Валидация через Zod вернет строго тип T, у которого точно есть id\r\n return this.safeParseData(z.array(this.schema), data, true); // Стало\r\n },\r\n },\r\n );\r\n }\r\n\r\n /**\r\n * Универсальный метод получения пагинированных данных с фильтрацией.\r\n * Автоматически очищает фильтры от null/undefined/пустых значений с помощью cleanFilterParams.\r\n */\r\n getObjectsByFilterPaging<F extends SafeFilterState>(\r\n tableStateGetter: () => TableState,\r\n filtersGetter: () => F\r\n ): HttpResourceRef<T[]> {\r\n return httpResource<T[]>(\r\n () => {\r\n this._refreshTrigger();\r\n\r\n const tableState = tableStateGetter(); // Читаем сигнал состояния таблицы стороннего компонента\r\n const filters = filtersGetter(); // Читаем сигнал фильтров стороннего компонента\r\n\r\n // 1. Очищаем переданные фильтры вашей функцией\r\n const cleanFields = cleanFilterParams(filters);\r\n // 2. Формируем базовые параметры пагинации\r\n const tableParams = this.buildTableParams(tableState);\r\n\r\n return {\r\n url: this.baseRoute,\r\n params: { ...cleanFields, ...tableParams },\r\n };\r\n },\r\n {\r\n ...this.getHttpContext(),\r\n defaultValue: [],\r\n parse: (data) => {\r\n if (!data) return [];\r\n return this.safeParseData(z.array(this.schema), data, true); // Стало\r\n },\r\n },\r\n );\r\n }\r\n\r\n /**\r\n * Универсальный метод получения КОЛИЧЕСТВА записей с фильтрацией.\r\n * Автоматически очищает фильтры перед отправкой.\r\n */\r\n getObjectsCountByFilter<F extends SafeFilterState>(\r\n filtersGetter: () => F\r\n ): HttpResourceRef<number> {\r\n return httpResource<number>(\r\n () => {\r\n this._refreshTrigger();\r\n\r\n const filters = filtersGetter();\r\n\r\n // Очищаем объект от пустых полей\r\n const cleanFields = cleanFilterParams(filters);\r\n\r\n return {\r\n url: `${this.baseRoute}${this.countRoute}`,\r\n params: { ...cleanFields }, // Отправляем на бэкенд только заполненные ключи\r\n };\r\n },\r\n {\r\n ...this.getHttpContext(),\r\n defaultValue: 0,\r\n parse: (data: unknown) => z.coerce.number().parse(data),\r\n },\r\n );\r\n }\r\n\r\n // Вспомогательный метод для сборки параметров таблицы в плоский объект\r\n protected buildTableParams(\r\n tableState: TableState,\r\n ): Record<string, string | number> {\r\n const queryParams: Record<string, string | number> = {};\r\n const { pageIndex, pageSize, sortActive, sortDirection } = tableState;\r\n\r\n if (pageIndex + 1) queryParams[this.pageIndexParam] = pageIndex + 1;\r\n if (pageSize) queryParams[this.pageSizeParam] = pageSize;\r\n if (sortActive) queryParams[this.sortColumnParam] = sortActive;\r\n if (sortDirection) queryParams[this.directionParam] = sortDirection;\r\n\r\n return queryParams;\r\n }\r\n\r\n /**\r\n * МЕТОД СОЗДАНИЯ (POST)\r\n * Принимает данные БЕЗ id. Тип формируется автоматически через Zod.\r\n */\r\n newObject(entity: Omit<T, 'id'>): any {\r\n // Если задана DTO-схема, очищаем объект от расчетных UI-полей перед отправкой\r\n const payload = this.schemaDTO ? this.schemaDTO.parse(entity) : entity;\r\n return this.http.post(this.baseRoute, payload, this.getHttpContext());\r\n }\r\n\r\n /**\r\n * Метод для СОЗДАНИЯ объекта (POST)\r\n * Тип аргумента генерируется автоматически: это ваш тип T, но БЕЗ поля id.\r\n */\r\n // create(dto: Omit<T, 'id'>): HttpResourceRef<T | undefined> {\r\n // return httpResource<T>(\r\n // () => ({\r\n // url: this.baseRoute,\r\n // method: 'POST',\r\n // body: dto, // Отправляем данные без id\r\n // }),\r\n // {\r\n // ...this.getHttpContext(),\r\n // // Сервер вернет созданный объект уже С присвоенным id, валидируем его полной схемой\r\n // parse: (data: unknown) => this.schema.parse(data),\r\n // },\r\n // );\r\n // }\r\n\r\n editObject(entity: T): any {\r\n // Если задана DTO-схема, очищаем объект от расчетных UI-полей перед отправкой\r\n const payload = this.schemaDTO ? this.schemaDTO.parse(entity) : entity;\r\n return this.http.put(\r\n this.baseRoute + entity.id,\r\n payload,\r\n this.getHttpContext(),\r\n );\r\n }\r\n\r\n /**\r\n * Метод для ОБНОВЛЕНИЯ объекта (PUT / PATCH)\r\n * Принимает id и частичный объект (все свойства T становятся необязательными, кроме id)\r\n */\r\n // update(\r\n // id: number,\r\n // dto: Partial<Omit<T, 'id'>>,\r\n // ): HttpResourceRef<T | undefined> {\r\n // return httpResource<T>(\r\n // () => ({\r\n // url: `${this.baseRoute}/${id}`,\r\n // method: 'PUT',\r\n // body: dto,\r\n // }),\r\n // {\r\n // ...this.getHttpContext(),\r\n // parse: (data: unknown) => this.schema.parse(data),\r\n // },\r\n // );\r\n // }\r\n\r\n /**\r\n * Метод DELETE (Переписанный под новую архитектуру)\r\n * Возвращает Observable. При подписке делает DELETE запрос,\r\n * а оператор 'tap' автоматически обновляет список getObjects() при успехе.\r\n */\r\n deleteObject(entity: T): any {\r\n return this.http\r\n .delete(this.baseRoute + entity.id, this.getHttpContext())\r\n .pipe(\r\n // Как только бэкенд ответит успехом, дергаем триггер обновления\r\n tap(() => this.refresh()),\r\n );\r\n }\r\n\r\n protected getParams(\r\n pageIndex: number,\r\n pageSize: number,\r\n sortColumn: string,\r\n direction: string,\r\n ): HttpParams {\r\n let params = new HttpParams();\r\n if (pageIndex + 1)\r\n // переход от индекса к номеру страницы\r\n params = params.append(this.pageIndexParam, pageIndex + 1);\r\n if (pageSize) params = params.append(this.pageSizeParam, pageSize);\r\n if (sortColumn) params = params.append(this.sortColumnParam, sortColumn);\r\n if (direction) params = params.append(this.directionParam, direction);\r\n return params;\r\n }\r\n\r\n // Вспомогательный метод для сборки опций HttpClient\r\n protected getHttpContext(): { context?: HttpContext } {\r\n // Если имя не задано (пустая строка, null или undefined), возвращаем пустой объект\r\n if (!this.apiContextName) {\r\n return {};\r\n }\r\n\r\n // Если имя задано, создаем и возвращаем контекст\r\n return {\r\n context: new HttpContext().set(API_NAME, this.apiContextName),\r\n };\r\n }\r\n\r\n /**\r\n * Безопасно валидирует данные с помощью Zod схемы.\r\n * Автоматически добавляет имя сервиса и эндпоинт в лог ошибки.\r\n */\r\n protected safeParseData<R>(schema: z.ZodType<R>, data: unknown, isArray = false): R {\r\n const result = schema.safeParse(data);\r\n\r\n if (!result.success) {\r\n // Собираем понятное имя контекста.\r\n // Например: \"UserService (Тип: Array<Schema>, Route: /api/human/)\"\r\n const serviceName = this.constructor.name;\r\n const typeInfo = isArray ? `Array<${serviceName.replace('Service', '')}>` : serviceName.replace('Service', '');\r\n const contextName = `${serviceName} [Ожидаемый тип: ${typeInfo}] (Route: \"${this.baseRoute}\")`;\r\n\r\n const formattedErrorMessage = formatZodError(result.error, contextName);\r\n \r\n throw new Error(formattedErrorMessage);\r\n }\r\n\r\n return result.data;\r\n }\r\n}\r\n","import { Directive, effect, ElementRef, inject, input } from '@angular/core';\r\nimport { RoleService } from '@kuzntsv/uikit';\r\n\r\n@Directive({\r\n selector: '[ngxUikDisableIfRole]',\r\n})\r\nexport class DisableIfRoleDirective {\r\n readonly forbiddenRoles = input<string[]>([], { alias: 'ngxUikDisableIfRole' });\r\n\r\n private readonly el = inject(ElementRef);\r\n private readonly roleService = inject(RoleService);\r\n\r\n constructor() {\r\n effect(() => {\r\n // Спрашиваем у сервиса, заблокирована ли данная конфигурация ролей\r\n const shouldDisable = this.roleService.hasForbiddenRole(this.forbiddenRoles());\r\n\r\n\r\n // 2. Безопасное управление атрибутом для любых элементов\r\n const nativeEl = this.el.nativeElement;\r\n \r\n if ('disabled' in nativeEl) {\r\n nativeEl.disabled = shouldDisable;\r\n } else {\r\n // Для элементов вроде <a>, у которых нет свойства disabled в DOM API\r\n if (shouldDisable) {\r\n nativeEl.setAttribute('disabled', 'true');\r\n } else {\r\n nativeEl.removeAttribute('disabled');\r\n }\r\n }\r\n });\r\n }\r\n}\r\n","import { Directive, ElementRef, effect, inject, input } from '@angular/core';\r\nimport { RoleService } from '@kuzntsv/uikit';\r\n\r\n@Directive({\r\n selector: '[ngxUikHideIfForbiddenRole]',\r\n})\r\nexport class HideIfForbiddenRoleDirective {\r\n readonly forbiddenRoles = input<string[]>([], {\r\n alias: 'ngxUikHideIfForbiddenRole',\r\n });\r\n\r\n private readonly el = inject(ElementRef);\r\n private readonly roleService = inject(RoleService);\r\n\r\n constructor() {\r\n effect(() => {\r\n // Элемент скрывается, если у пользователя есть запрещенная роль или передан маркер HIDE_ROLE_MARKER\r\n const shouldHide = this.roleService.hasForbiddenRole(\r\n this.forbiddenRoles(),\r\n );\r\n\r\n // Управляем отображением. Пустая строка возвращает дефолтный CSS-стиль элемента.\r\n this.el.nativeElement.style.display = shouldHide ? 'none' : '';\r\n });\r\n }\r\n}\r\n","import { Directive, effect, inject, input } from '@angular/core';\r\nimport { NgControl } from '@angular/forms';\r\n\r\n@Directive({\r\n selector: '[setValue]',\r\n})\r\nexport class SetValueDirective {\r\n readonly value = input<any>(null, { alias: 'setValue' });\r\n\r\n // 3. Используем опциональный inject, чтобы директива не падала, если формы нет\r\n private readonly ngControl = inject(NgControl, { optional: true });\r\n\r\n constructor() {\r\n effect(() => {\r\n // Эффект автоматически отслеживает изменение входного значения\r\n const val = this.value();\r\n\r\n // Безопасное приведение undefined к null для стандартизации значений в формах\r\n const normalizedValue = val === undefined ? null : val;\r\n\r\n // Используем проверку, так как на старте ngControl.control может быть еще не создан Angular-ом\r\n if (this.ngControl && this.ngControl.control) {\r\n this.ngControl.control.setValue(normalizedValue, { emitEvent: false });\r\n }\r\n });\r\n }\r\n}\r\n","import { inject } from '@angular/core';\r\nimport { CanActivateFn, Router } from '@angular/router';\r\nimport { AuthService } from '@kuzntsv/uikit';\r\n\r\nexport const authGuard = (allowedRoles: string[]): CanActivateFn => {\r\n return (route, state) => {\r\n const authService = inject(AuthService);\r\n const router = inject(Router);\r\n\r\n const isLogin = authService.loggedIn();\r\n if (!isLogin) {\r\n console.log('state.url =', state.url);\r\n\r\n // Если не зарегистрирован вернуть в форму авторизации\r\n return router.createUrlTree(['/login'], { queryParams: { returnUrl: state.url } });\r\n }\r\n\r\n return isLogin;\r\n };\r\n};","import { ActivatedRouteSnapshot, CanActivateFn } from '@angular/router';\r\n\r\nexport const redirectGuard: CanActivateFn = (route: ActivatedRouteSnapshot) => {\r\n const externalUrl = route.data?.['externalUrl'];\r\n \r\n if (externalUrl) {\r\n // Редирект в текущей вкладке через метод open, \r\n // который легко и легитимно мокается в любых тестах\r\n window.open(externalUrl, '_self');\r\n }\r\n \r\n return true;\r\n};\r\n","import { inject } from '@angular/core';\r\nimport { CanActivateFn } from '@angular/router';\r\nimport { RoleService } from '@kuzntsv/uikit';\r\n\r\n/**\r\n * Пускает на роут только тех пользователей, у которых есть роли из списка allowedRoles.\r\n * ADMIN всегда имеет доступ.\r\n */\r\nexport const roleGuard = (allowedRoles: string[]): CanActivateFn => {\r\n return (route, state) => {\r\n const roleService = inject(RoleService);\r\n\r\n // Проверяем доступ на основе аргумента allowedRoles\r\n return roleService.hasAnyRole(allowedRoles);\r\n };\r\n};","import { InjectionToken } from '@angular/core';\r\n\r\nexport interface LoggerConfig {\r\n isProduction: boolean;\r\n logLevel?: 'debug' | 'info' | 'warn' | 'error';\r\n}\r\n\r\nexport const LOGGER_CONFIG = new InjectionToken<LoggerConfig>('LOGGER_CONFIG');\r\n","import { inject, Service } from '@angular/core';\r\nimport { LOGGER_CONFIG } from './logger.config';\r\n\r\n\r\n@Service()\r\nexport class LoggerService {\r\n public logPrefix: string = '';\r\n private isProduction: boolean;\r\n private readonly config = inject(LOGGER_CONFIG);\r\n\r\n constructor() {\r\n this.isProduction = this.config.isProduction;\r\n }\r\n\r\n log(message: string, ...args: any[]) {\r\n if (!this.isProduction) {\r\n // Prepend log prefix log string\r\n args.unshift(this.logPrefix + ' ');\r\n console.log(`[DEV LOG]: ${message}`, ...args);\r\n }else {\r\n console.log(`[PROD LOG]: ${message}`, ...args);\r\n }\r\n }\r\n\r\n error(message: string, ...args: any[]): void {\r\n console.error(`[ERROR]: ${message}`, ...args);\r\n }\r\n}\r\n\r\n\r\n\r\n","import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\r\nimport { LOGGER_CONFIG, LoggerConfig } from './logger.config';\r\nimport { LoggerService } from './logger.service';\r\n\r\n\r\nexport function provideLogger(config: LoggerConfig): EnvironmentProviders {\r\n return makeEnvironmentProviders([\r\n { provide: LOGGER_CONFIG, useValue: config },\r\n LoggerService\r\n ]);\r\n};\r\n","import z from 'zod';\r\n\r\n// 1. Схема и тип для SecUserView\r\nexport const secUserViewSchema = z.object({\r\n id: z.number().default(0),\r\n idHuman: z.number().default(0).nullable(),\r\n loginAD: z\r\n .string()\r\n .nullable()\r\n .default('')\r\n .transform((val) => (val === null ? '' : val))\r\n .pipe(z.string()),\r\n dept: z.number().default(0).nullable(),\r\n tabnum: z.number().default(0).nullable(),\r\n lastname: z\r\n .string()\r\n .nullable()\r\n .default('')\r\n .transform((val) => (val === null ? '' : val))\r\n .pipe(z.string()),\r\n firstname: z\r\n .string()\r\n .nullable()\r\n .default('')\r\n .transform((val) => (val === null ? '' : val))\r\n .pipe(z.string()),\r\n middlename: z\r\n .string()\r\n .nullable()\r\n .default('')\r\n .transform((val) => (val === null ? '' : val))\r\n .pipe(z.string()),\r\n fio: z\r\n .string()\r\n .nullable()\r\n .default('')\r\n .transform((val) => (val === null ? '' : val))\r\n .pipe(z.string()),\r\n dateHuman: z.coerce.date().optional().nullable(), // Поле dateHuman?: Date\r\n profession: z\r\n .string()\r\n .nullable()\r\n .default('')\r\n .transform((val) => (val === null ? '' : val))\r\n .pipe(z.string()),\r\n});\r\n\r\nexport type SecUserView = z.infer<typeof secUserViewSchema>;\r\n","import z from \"zod\";\r\nimport { secUserViewSchema } from \"./sec-user-view.model\";\r\n\r\n// 2. Схема и тип для SecUser\r\nexport const secUserSchema = z.object({\r\n id: z.number().default(0),\r\n login: z.string().nullable().default('').transform((val) => (val === null ? \"\" : val)).pipe(z.string()),\r\n fio: z.string().nullable().default('').transform((val) => (val === null ? \"\" : val)).pipe(z.string()),\r\n dept: z.number().default(0).nullable(),\r\n tabnum: z.number().default(0).nullable(),\r\n userView: secUserViewSchema.optional().nullable(), // Вложенная схема\r\n});\r\n\r\nexport type SecUser = z.infer<typeof secUserSchema>;","import { inject, Pipe, PipeTransform } from '@angular/core';\r\nimport { DomSanitizer, SafeHtml, SafeResourceUrl, SafeScript, SafeStyle, SafeUrl } from '@angular/platform-browser';\r\n\r\n// Создаем тип для всех возможных безопасных значений Angular\r\nexport type SafeAny = SafeHtml | SafeStyle | SafeScript | SafeUrl | SafeResourceUrl;\r\n\r\n@Pipe({\r\n name: 'safe'\r\n})\r\nexport class SafePipe implements PipeTransform {\r\n\r\n private readonly sanitizer = inject(DomSanitizer);\r\n\r\n transform(url: string | SafeAny | null | undefined, type: 'html' | 'style' | 'script' | 'url' | 'resourceUrl' = 'url'): string | SafeAny {\r\n if (!url) {\r\n return '';\r\n }\r\n\r\n // Проверяем, является ли значение уже объектом SafeUrl.\r\n // Объекты SafeUrl от DomSanitizer имеют скрытые свойства или метод toString(), \r\n // но самый надежный способ в Angular — проверить, что это не обычная строка.\r\n if (typeof url !== 'string') {\r\n return url; // Возвращаем как есть, так как это уже SafeUrl\r\n }\r\n // Расширяем пайп универсальностью с помощью switch-case\r\n switch (type) {\r\n case 'html': return this.sanitizer.bypassSecurityTrustHtml(url);\r\n case 'style': return this.sanitizer.bypassSecurityTrustStyle(url);\r\n case 'script': return this.sanitizer.bypassSecurityTrustScript(url);\r\n case 'url': return this.sanitizer.bypassSecurityTrustUrl(url);\r\n case 'resourceUrl': return this.sanitizer.bypassSecurityTrustResourceUrl(url);\r\n default: throw new Error(`SafePipe: Неизвестный тип безопасности ${type}`);\r\n }\r\n }\r\n}\r\n","import { Pipe, PipeTransform } from '@angular/core';\r\n\r\n@Pipe({\r\n name: 'time'\r\n})\r\nexport class TimePipe implements PipeTransform {\r\n\r\n transform(value: number): string {\r\n // const hour = Math.abs(value) >= 60 ? Math.round(value / 60) + 'ч.' : '';\r\n // const minute = ' ' + Math.abs(value % 60) + 'м.';\r\n // return value === 0 ? '0' : hour + ' ' + minute;\r\n\r\n const hour = Math.abs(value) >= 60 ? Math.floor(Math.abs(value) / 60).toString().padStart(2,'0') : '00';\r\n const minute = Math.abs(value % 60).toString().padStart(2,'0');\r\n const time = hour + ':' + minute;\r\n return value < 0 ? '-' + time : time;\r\n }\r\n\r\n}\r\n","import { Pipe, PipeTransform } from '@angular/core';\r\n\r\n@Pipe({\r\n name: 'truncate'\r\n})\r\nexport class TruncatePipe implements PipeTransform {\r\n // Usage:\r\n // {{ str | truncate:[20] }} // or\r\n // {{ str | truncate:[20, '...'] }} // or|\r\n transform(value: string, args: any[]): string {\r\n const limit = args.length > 0 ? parseInt(args[0], 10) : 20;\r\n const trail = args.length > 1 ? args[1] : '...';\r\n return value.length > limit ? value.substring(0, limit) + trail : value;\r\n }\r\n\r\n}\r\n","import { COMMA, ENTER } from '@angular/cdk/keycodes';\nimport {\n Component,\n computed,\n inject,\n input,\n linkedSignal,\n model,\n} from '@angular/core';\nimport {\n MatAutocompleteModule,\n MatAutocompleteSelectedEvent,\n MatOption,\n} from '@angular/material/autocomplete';\nimport { MatChipsModule } from '@angular/material/chips';\nimport { MatError, MatFormField, MatLabel } from '@angular/material/form-field';\nimport { MatIcon } from '@angular/material/icon';\n\nimport { FormField, FormValueControl } from '@angular/forms/signals';\nimport { ChipItem } from './models';\n\n@Component({\n selector: 'ngx-uik-chip-input-autocomplete',\n templateUrl: './chip-input-autocomplete.component.html',\n styleUrl: './chip-input-autocomplete.component.css',\n imports: [\n MatFormField,\n MatAutocompleteModule,\n MatIcon,\n MatOption,\n MatChipsModule,\n MatLabel,\n MatError\n ],\n})\nexport class ChipInputAutocompleteComponent implements FormValueControl<\n string[]\n> {\n // Инжектируем внешнее поле формы для получения статусов (disabled, invalid)\n private readonly formFieldDirective = inject(FormField, {\n host: true,\n optional: true,\n });\n\n /** Все элементы. */\n items = input<ChipItem[]>([]);\n /** Заголовок. */\n title = input<string>('');\n\n // Реализация контракта FormValueControl через model().\n // Значением контрола является массив строк (ключей). Инициализируем пустым массивом.\n readonly value = model<string[]>([]);\n\n // Сигнал для управления текстом в поисковой строке (инпуте)\n readonly filterQuery = model<string>('');\n\n separatorKeysCodes: number[] = [ENTER, COMMA];\n\n // Синхронизируем массив объектов ChipItem на основе массива ключей value()\n readonly selectedItems = linkedSignal<string[], ChipItem[]>({\n source: () => this.value(),\n computation: (inputKeys) =>\n this.items().filter((item) => inputKeys.includes(item.value)),\n });\n\n // Декларативный computed-сигнал для фильтрации опций в выпадающем списке\n readonly filteredItems = computed<ChipItem[]>(() => {\n const allItems = this.items();\n const search = this.filterQuery().toLowerCase().trim();\n\n if (!search) {\n return allItems;\n }\n\n return allItems.filter((item) =>\n item.viewValue.toLowerCase().includes(search),\n );\n });\n\n // Считываем состояние блокировки напрямую из Signal Forms\n readonly isDisabled = computed(() => {\n return this.formFieldDirective?.state?.().disabled() ?? false;\n });\n\n // Считываем состояние валидности напрямую из Signal Forms\n readonly isInvalid = computed(() => {\n return this.formFieldDirective?.state()?.invalid() ?? false;\n });\n\n remove(value: string): void {\n if (this.isDisabled()) return;\n // Просто обновляем стейт нашей модели, Angular сделает всё остальное реактивно\n this.value.update((keys) => keys.filter((key) => key !== value));\n }\n\n selected(event: MatAutocompleteSelectedEvent): void {\n const selectedValue = event.option.value;\n\n this.value.update((keys) => {\n // Предотвращаем дубликаты в массиве ключей\n return keys.includes(selectedValue) ? keys : [...keys, selectedValue];\n });\n\n // Очищаем строку ввода после выбора элемента\n this.filterQuery.set('');\n }\n\n onCloseClick($event: MouseEvent) {\n $event.stopPropagation();\n if (this.isDisabled()) return;\n\n this.value.set([]);\n this.filterQuery.set('');\n }\n}\n","<mat-form-field class=\"chip-list\" appearance=\"fill\">\n <mat-label>{{ title() }}</mat-label>\n <mat-chip-grid #chipList aria-label=\"'Выбор '+title()\">\n @for (item of selectedItems(); track item.value) {\n <mat-chip-row color=\"primary\" (removed)=\"remove(item.value)\">\n {{ item.viewValue }}\n <button matChipRemove>\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n </mat-chip-grid>\n <input\n #input\n [value]=\"filterQuery()\"\n (input)=\"filterQuery.set($any($event.target).value)\"\n [placeholder]=\"'Введите ' + title() + '...'\"\n [matAutocomplete]=\"auto\"\n [matChipInputFor]=\"chipList\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n [disabled]=\"isDisabled()\"\n />\n <mat-autocomplete #auto=\"matAutocomplete\" (optionSelected)=\"selected($event)\">\n @for (item of filteredItems(); track item.value) {\n <mat-option\n [value]=\"item.value\"\n [disabled]=\"selectedItems().includes(item)\"\n >\n {{ item.viewValue }}\n </mat-option>\n }\n </mat-autocomplete>\n @if (!isDisabled() && value().length > 0) {\n <button\n matSuffix\n mat-icon-button\n aria-label=\"Clear\"\n (click)=\"onCloseClick($event)\"\n >\n <mat-icon>close</mat-icon>\n </button>\n }\n <!-- Блок вывода ошибки валидации родительской формы -->\n @if (isInvalid()) {\n <mat-error>Поле \"{{ title() }}\" заполнено некорректно</mat-error>\n }\n</mat-form-field>\n","import { Injectable } from '@angular/core';\r\nimport { NativeDateAdapter } from '@angular/material/core';\r\n\r\n@Injectable()\r\nexport class CustomDateAdapter extends NativeDateAdapter {\r\n \r\n // 1. Как дата ПАРСИТСЯ, когда пользователь вводит её руками в инпут\r\n override parse(value: any): Date | null {\r\n if (typeof value === 'string' && value.indexOf('.') > -1) {\r\n const str = value.split('.');\r\n const year = Number(str[2]);\r\n const month = Number(str[1]) - 1;\r\n const day = Number(str[0]);\r\n return new Date(year, month, day);\r\n }\r\n const timestamp = typeof value === 'number' ? value : Date.parse(value);\r\n return isNaN(timestamp) ? null : new Date(timestamp);\r\n }\r\n\r\n // 2. Как дата ОТОБРАЖАЕТСЯ в самом инпуте\r\n override format(date: Date, displayFormat: Object): string {\r\n if (displayFormat === 'input') {\r\n const day = String(date.getDate()).padStart(2, '0');\r\n const month = String(date.getMonth() + 1).padStart(2, '0');\r\n const year = date.getFullYear();\r\n return `${day}.${month}.${year}`; // Наш строгий DD.MM.YYYY\r\n }\r\n // Для всех остальных элементов (выбор месяца, года) оставляем стандартное поведение локали\r\n return super.format(date, displayFormat);\r\n }\r\n}\r\n\r\n// Объект форматов для NativeDateAdapter\r\nexport const MY_NATIVE_FORMATS = {\r\n parse: {\r\n dateInput: 'input',\r\n },\r\n display: {\r\n dateInput: 'input', // Маркер 'input' будет перехвачен нашим методом format() выше\r\n monthYearLabel: { year: 'numeric', month: 'short' },\r\n dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },\r\n monthYearA11yLabel: { year: 'numeric', month: 'long' },\r\n },\r\n};","import { z } from 'zod';\r\n\r\n// Безопасная функция перевода Date в ISO-строку \"YYYY-MM-DD\"\r\nconst toIsoString = (date: Date | null): string => {\r\n if (!date) return '';\r\n // .toISOString() всегда возвращает формат \"2026-10-28T06:00:00.000Z\"\r\n // .split('T')[0] срезает всё после времени, оставляя чистое \"2026-10-28\"\r\n return date.toISOString().split('T')[0];\r\n};\r\n\r\nexport const dateRangeFormSchema = z.object({\r\n begin: z\r\n .instanceof(Date)\r\n .nullable(),\r\n end: z\r\n .instanceof(Date)\r\n .nullable(),\r\n });\r\n\r\n// Тип вывода { begin: Date | null; end: Date | null; }\r\nexport type DateRangeForm = z.output<typeof dateRangeFormSchema>;\r\n\r\n// Создаем динамическую схему валидации\r\nexport const dateRangeSchema = dateRangeFormSchema.transform((data) => ({\r\n begin: toIsoString(data.begin),\r\n end: toIsoString(data.end),\r\n }));\r\n\r\n// Тип вывода { begin: string; end: string; }\r\nexport type DateRange = z.output<typeof dateRangeSchema>;\r\n","import {\n Component,\n effect,\n input,\n output,\n signal,\n untracked\n} from '@angular/core';\nimport { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';\nimport {\n MatDatepickerToggle,\n MatDateRangeInput,\n MatDateRangePicker,\n MatEndDate,\n MatStartDate,\n} from '@angular/material/datepicker';\nimport {\n MatError,\n MatFormField,\n MatLabel,\n MatSuffix,\n} from '@angular/material/form-field';\n\nimport { debounce, form, FormField, required, validateStandardSchema } from '@angular/forms/signals';\nimport { DateRange, DateRangeForm, dateRangeFormSchema, dateRangeSchema } from './models';\nimport {\n CustomDateAdapter,\n MY_NATIVE_FORMATS,\n} from './models/custom-date-adapter';\n\n@Component({\n selector: 'ngx-uik-date-range-input',\n templateUrl: './date-range-input.component.html',\n styleUrls: ['./date-range-input.component.scss'],\n imports: [\n FormField,\n MatFormField,\n MatLabel,\n MatDateRangeInput,\n MatStartDate,\n MatEndDate,\n MatDatepickerToggle,\n MatSuffix,\n MatDateRangePicker,\n MatError,\n ],\n providers: [\n { provide: DateAdapter, useClass: CustomDateAdapter },\n { provide: MAT_DATE_FORMATS, useValue: MY_NATIVE_FORMATS },\n ],\n})\nexport class DateRangeInputComponent {\n readonly DEFAULT_MIN_DATE = new Date(2020, 0, 1);\n\n label = input<string>('');\n dateRange = input<DateRange>(<DateRange>{ begin: '', end: '' });\n minDate = input<Date>(this.DEFAULT_MIN_DATE);\n clearInput = input<any>(null);\n required = input<boolean>(false);\n dateRangeChange = output<DateRange>();\n\n formModel = signal<DateRangeForm>({ begin: null, end: null });\n\n form = form(this.formModel, (schemaPath) => {\n validateStandardSchema(schemaPath, dateRangeFormSchema);\n required(schemaPath.begin, {message: \"Укажите период\", when: () => this.required()});\n required(schemaPath.end, {message: \"Укажите период\", when: () => this.required()});\n debounce(schemaPath.begin, 500);\n debounce(schemaPath.end, 500);\n });\n\n constructor() {\n effect(() => {\n this.clearInput();\n \n untracked(() => this.form().reset());\n });\n\n effect(() => {\n const value = this.dateRange();\n\n untracked(() => {\n this.form.begin().value.set(value.begin ? new Date(value.begin) : null);\n this.form.end().value.set(value.end ? new Date(value.end) : null);\n });\n });\n\n effect(() => {\n const currentValues = this.form().value();\n\n if (this.form().valid()) {\n const formattedRange = dateRangeSchema.safeParse(currentValues);\n if (formattedRange.success) {\n this.dateRangeChange.emit(formattedRange.data);\n }\n }\n });\n }\n\n}\n","<mat-form-field appearance=\"fill\">\r\n <mat-label>{{ label() }}</mat-label>\r\n <mat-date-range-input\r\n [rangePicker]=\"picker\"\r\n [min]=\"minDate()\"\r\n >\r\n <input matStartDate [formField]=\"form.begin\" placeholder=\"Дата начала\" />\r\n <input matEndDate [formField]=\"form.end\" placeholder=\"Дата окончания\" />\r\n </mat-date-range-input>\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-date-range-picker #picker></mat-date-range-picker>\r\n @if (form.begin().touched() && form.begin().invalid()) {\r\n <ng-container ngProjectAs=\"mat-error\">\r\n <mat-error>{{ form.begin().errors()[0]?.message }}</mat-error>\r\n </ng-container>\r\n }\r\n @if (form.end().touched() && form.end().invalid()) {\r\n <ng-container ngProjectAs=\"mat-error\">\r\n <mat-error>{{ form.end().errors()[0]?.message }}</mat-error>\r\n </ng-container>\r\n }\r\n</mat-form-field>\r\n","export enum DialogAction {\r\n Add = 'Добавить',\r\n Edit = 'Изменить',\r\n Delete = 'Удалить',\r\n None = ''\r\n }","import { Component } from '@angular/core';\n\n@Component({\n selector: 'ngx-uik-empty-route-guard-holder',\n template: '', // пустой шаблон, так как гуард сразу уводит пользователя со страницы\n})\nexport class EmptyComponent {}\n","import { z } from 'zod';\r\n\r\n// 1. Создаем Zod-схему авторизации\r\nexport const loginSchema = z.object({\r\n username: z\r\n .string()\r\n .min(1, { message: 'Пожалуйста, заполните это поле' })\r\n .regex(/^[A-Za-z]{1,}\\.[A-Za-z]{1,}\\.[A-Za-z]*$/, {\r\n message: 'Пожалуйста, используйте формат \"a.p.petrov\"',\r\n }),\r\n password: z.string().min(1, { message: 'Пожалуйста, заполните это поле' }),\r\n});\r\n\r\n// 2. Автоматически генерируем тип Authenticate из созданной схемы\r\n// Больше никакой ручной поддержки интерфейса — изменения в схеме обновят тип сами!\r\nexport type Authenticate = z.infer<typeof loginSchema>;\r\n","import { Component, input, output, signal } from '@angular/core';\nimport { MatButton } from '@angular/material/button';\nimport {\n MatCard,\n MatCardContent,\n MatCardHeader,\n MatCardTitle,\n} from '@angular/material/card';\nimport {\n MatError,\n MatFormField,\n MatLabel,\n MatSuffix,\n} from '@angular/material/form-field';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatInput } from '@angular/material/input';\n\nimport {\n disabled,\n form,\n FormField,\n FormRoot,\n validateStandardSchema,\n} from '@angular/forms/signals';\nimport { Authenticate, loginSchema } from '../../models/authenticate';\n\n@Component({\n selector: 'ngx-uik-login-form',\n templateUrl: 'login-form.component.html',\n styleUrls: ['login-form.component.scss'],\n imports: [\n FormRoot,\n FormField,\n MatCard,\n MatCardHeader,\n MatCardTitle,\n MatCardContent,\n MatFormField,\n MatLabel,\n MatInput,\n MatError,\n MatIcon,\n MatSuffix,\n MatButton,\n ],\n})\nexport class LoginFormComponent {\n pending = input<boolean>(false);\n submitted = output<Authenticate>();\n\n readonly isHidePassword = signal(true);\n\n formModel = signal<Authenticate>({ username: '', password: '' });\n\n form = form(\n this.formModel,\n (schemaPath) => {\n validateStandardSchema(schemaPath, loginSchema);\n disabled(schemaPath.username, { when: () => this.pending() });\n disabled(schemaPath.password, { when: () => this.pending() });\n },\n {\n submission: {\n action: async (field) => {\n this.submitted.emit(field().value());\n return;\n },\n },\n },\n );\n\n // Метод для показа пароля (вызывается при нажатии)\n showPassword(): void {\n this.isHidePassword.set(false);\n }\n\n // Метод для скрытия пароля (вызывается при отпускании)\n hidePassword(): void {\n this.isHidePassword.set(true);\n }\n}\n","<mat-card appearance=\"outlined\">\r\n <mat-card-header>\r\n <mat-card-title> Авторизация </mat-card-title>\r\n </mat-card-header>\r\n <mat-card-content>\r\n <form [formRoot]=\"form\">\r\n <mat-form-field class=\"login-field\">\r\n <mat-label>Имя пользователя</mat-label>\r\n <input\r\n type=\"text\"\r\n matInput\r\n autocomplete=\"on\"\r\n placeholder=\"Имя пользователя\"\r\n [formField]=\"form.username\"\r\n />\r\n @if (form.username().touched() && form.username().invalid()) {\r\n <ng-container ngProjectAs=\"mat-error\">\r\n <mat-error>{{ form.username().errors()[0]?.message }}</mat-error>\r\n </ng-container>\r\n }\r\n </mat-form-field>\r\n\r\n <mat-form-field class=\"login-field\">\r\n <mat-label>Пароль</mat-label>\r\n <input\r\n [type]=\"isHidePassword() ? 'password' : 'text'\"\r\n matInput\r\n placeholder=\"Пароль\"\r\n [formField]=\"form.password\"\r\n />\r\n <mat-icon\r\n class=\"watcher\"\r\n matSuffix\r\n (mousedown)=\"showPassword()\"\r\n (mouseup)=\"hidePassword()\"\r\n >{{ isHidePassword() ? \"visibility_off\" : \"visibility\" }}</mat-icon\r\n >\r\n @if (form.password().touched() && form.password().invalid()) {\r\n <ng-container ngProjectAs=\"mat-error\">\r\n <mat-error>{{ form.password().errors()[0]?.message }}</mat-error>\r\n </ng-container>\r\n }\r\n </mat-form-field>\r\n\r\n <div class=\"loginButtons\">\r\n <button\r\n type=\"submit\"\r\n mat-button\r\n mat-stroked-button\r\n color=\"primary\"\r\n [disabled]=\"!form().valid() || pending()\"\r\n >\r\n Войти\r\n </button>\r\n </div>\r\n </form>\r\n </mat-card-content>\r\n</mat-card>\r\n","import {\n Component,\n effect,\n ElementRef,\n HostListener,\n output,\n viewChild\n} from '@angular/core';\nimport {\n MatCard,\n MatCardContent,\n MatCardHeader,\n MatCardTitle,\n} from '@angular/material/card';\n\n@Component({\n selector: 'ngx-uik-permit-form',\n templateUrl: 'permit-form.component.html',\n styleUrls: ['permit-form.component.scss'],\n imports: [MatCard, MatCardHeader, MatCardTitle, MatCardContent],\n})\nexport class PermitFormComponent {\n readonly hidy = viewChild<ElementRef<HTMLInputElement>>('hidy');\n submitted = output<string>();\n\n constructor() {\n // Эффект сработает автоматически, как только элемент появится в DOM\n effect(() => {\n // Обнуляем значение Input\n const inputEl = this.hidy()?.nativeElement;\n if (inputEl) {\n inputEl.focus();\n }\n });\n }\n\n /**\n * Метод для возврата фокуса в инпут\n */\n @HostListener('document:mouseup') \n focusInput(): void {\n this.hidy()?.nativeElement.focus();\n }\n\n /**\n * Обработка ввода с клавиатуры/сканера\n */\n onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Enter') {\n const inputEl = this.hidy()?.nativeElement;\n if (inputEl?.value && inputEl.value.trim()) {\n this.submitted.emit(inputEl.value);\n inputEl.value = '';\n }\n }\n }\n}\n","<mat-card appearance=\"outlined\">\r\n <mat-card-header>\r\n <mat-card-title>\r\n Приложите пропуск\r\n </mat-card-title>\r\n </mat-card-header>\r\n <mat-card-content>\r\n <div class=\"permit\"></div>\r\n </mat-card-content>\r\n</mat-card>\r\n<input #hidy class=\"hidy\" type=\"text\" (keydown)=\"onKeydown($event)\"/>","import { Component, inject, input, signal } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { AuthService, UIKIT_NOTIFICATION_TOKEN } from '@kuzntsv/uikit';\nimport { lastValueFrom } from 'rxjs';\n\nimport { Authenticate } from '../../models/authenticate';\nimport { LoginFormComponent } from '../login-form/login-form.component';\nimport { PermitFormComponent } from '../permit-form/permit-form.component';\n\n@Component({\n selector: 'ngx-uik-login-page',\n templateUrl: 'login-page.component.html',\n styleUrls: ['login-page.component.scss'],\n imports: [LoginFormComponent, PermitFormComponent],\n})\nexport class LoginPageComponent {\n pending = signal<boolean>(false);\n isKiosk = signal<boolean>(false);\n\n /**\n * Идентификатор АС получаем автоматически из ActivatedRoute Data!\n * (Для этого в настройках роутера должен быть включен withComponentInputBinding())\n */\n idCas = input<number>(0);\n\n private readonly authService = inject(AuthService);\n private readonly router = inject(Router);\n private readonly notificationService = inject(UIKIT_NOTIFICATION_TOKEN, {\n optional: true,\n });\n\n constructor() {\n // Вместо ngOnInit проверяем localStorage сразу при инициализации класса\n if (\n localStorage.getItem('id_human') ||\n localStorage.getItem('kiosk-keyboard-layout')\n ) {\n // this.isKiosk.set(true);\n }\n }\n\n async onSubmit(event: Authenticate) {\n this.startLoading();\n\n try {\n // Превращаем Observable в Promise. Вызовется метод login, выполнится и завершится.\n await lastValueFrom(\n this.authService.login(event.username, event.password, this.idCas()),\n );\n // Срабатывает строго при успешном разрешении промиса\n this.handleSuccessLogin();\n } catch (error) {\n // Срабатывает, если сервер вернул ошибку\n this.handleError(error);\n } finally {\n // Блок finally гарантирует выполнение, заменяя оператор `finalize` из RxJS\n this.finishLoading();\n }\n }\n\n async onSubmitPermit(permit: string) {\n this.startLoading();\n\n try {\n await lastValueFrom(\n this.authService.loginByPermit(permit, this.idCas())\n );\n this.handleSuccessLogin();\n } catch (error) {\n this.handleError(error);\n } finally {\n this.finishLoading();\n }\n }\n\n private startLoading(): void {\n this.pending.set(true);\n }\n\n private finishLoading(): void {\n this.pending.set(false);\n }\n\n private handleError(error: any): void {\n const errorMsg =\n 'Ошибка при авторизации: ' +\n (error.error || error.error?.message || error.message);\n this.notificationService?.error(errorMsg, 0);\n }\n\n private handleSuccessLogin(): void {\n this.notificationService?.success('Успешная авторизация');\n\n if (!this.router) return;\n\n // ЛОГИКА ВОЗВРАТА ПОСЛЕ УСПЕШНОГО ЛОГИНА\n\n // Извлекаем returnUrl из текущего query-параметра текущего маршрута\n const currentUrlTree = this.router.parseUrl(this.router.url);\n const returnUrl = currentUrlTree.queryParamMap.get('returnUrl');\n\n if (returnUrl) {\n // Декодируем и перенаправляем пользователя туда, где он был\n this.router.navigateByUrl(decodeURIComponent(returnUrl));\n } else {\n // Если returnUrl нет, идем на главную\n this.router.navigate(['/']);\n }\n }\n}\n","@if (isKiosk()) {\r\n <ngx-uik-permit-form (submitted)=\"onSubmitPermit($event)\" />\r\n} @else {\r\n <ngx-uik-login-form (submitted)=\"onSubmit($event)\" [pending]=\"pending()\" />\r\n}\r\n","import {\n ChangeDetectionStrategy,\n Component,\n inject,\n input,\n output,\n} from '@angular/core';\nimport { MatAnchor } from '@angular/material/button';\nimport { MatDialog } from '@angular/material/dialog';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatTooltip } from '@angular/material/tooltip';\nimport { SafeUrl } from '@angular/platform-browser';\nimport { filter, take } from 'rxjs';\n\nimport { BaseNavBarMenuClass } from '../../base';\nimport { SafePipe } from '../../pipes';\nimport { DialogComponent } from '../dialog';\n\n@Component({\n selector: 'ngx-uik-navbar',\n templateUrl: 'navbar.html',\n styleUrls: ['./navbar.scss'],\n changeDetection: ChangeDetectionStrategy.Eager,\n imports: [MatAnchor, MatIcon, MatTooltip, SafePipe],\n})\nexport class NavBarComponent extends BaseNavBarMenuClass {\n /** Видимость панели, когда loggedIn === false. */\n visibleOnLogout = input<boolean>(false);\n /** Видимость аватара. */\n visibleAvatar = input<boolean>(true);\n /** Видимость кнопки \"Выйти\". */\n visibleLogoutBtn = input<boolean>(true);\n /** Признак, что пользователь авторизован. */\n loggedIn = input<boolean>(false);\n /** ФИО пользователя. */\n fioUser = input<string>('');\n /** Всплывающая подсказка о пользователе. */\n userTooltip = input<string>('');\n /** URL аватара */\n avatarURL = input<string | SafeUrl>('');\n\n /** Нажата кнопка \"Выйти\". */\n logout = output<string>();\n\n private readonly dialog = inject(MatDialog);\n\n onLogout() {\n this.logout.emit(this.router.url);\n }\n\n openDialog(): void {\n const dialogRef = this.dialog.open(DialogComponent, {\n width: '400px',\n data: {\n id: 'logout',\n title: 'Подтверждение',\n message: 'Вы хотите выйти?',\n btnNoTitle: 'Отмена',\n btnYesTitle: 'Выйти',\n },\n });\n\n dialogRef\n .afterClosed()\n .pipe(\n take(1), // Берем только одно значение (когда закрылся)\n filter((id) => !!id), // Пропускаем дальше, только если id существует (нажали \"Выйти\")\n )\n .subscribe((id: any) => {\n if (id) {\n this.onLogout();\n }\n });\n }\n}\n","@if (visibleOnLogout() || loggedIn()) {\r\n <nav class=\"ngx-uik-navbar-header\">\r\n \r\n <ng-content></ng-content>\r\n\r\n <div class=\"flex-spacer\"></div>\r\n \r\n @if (visibleAvatar() && (loggedIn() === false || !avatarURL())) {\r\n <mat-icon [matTooltip]=\"userTooltip()\">account_circle</mat-icon>\r\n }\r\n @if (visibleAvatar() && loggedIn() && !!avatarURL()) {\r\n <img\r\n class=\"user-photo\"\r\n [src]=\"avatarURL() | safe\"\r\n loading=\"lazy\"\r\n [alt]=\"fioUser()\"\r\n [matTooltip]=\"userTooltip()\">\r\n }\r\n\r\n <span class = \"user-name\" [matTooltip]=\"userTooltip()\">\r\n {{ fioUser() }}\r\n </span>\r\n\r\n @if (visibleLogoutBtn()) {\r\n <a mat-button class=\"pm-button\" (click)=\"openDialog()\">Выйти <mat-icon>logout</mat-icon></a>\r\n }\r\n </nav>\r\n}","import { Component, ChangeDetectionStrategy } from '@angular/core';\n\n@Component({\n selector: 'ngx-uik-not-found',\n templateUrl: './not-found.component.html',\n styleUrls: ['./not-found.component.css'],\n})\nexport class NotFoundComponent {}\n","<div class=\"center\">\r\n <h3 class=\"mat-display-1\">Страница не найдена</h3>\r\n</div>\r\n","import { ScrollingModule } from '@angular/cdk/scrolling';\nimport {\n Component,\n computed,\n debounced,\n effect,\n inject,\n input,\n model\n} from '@angular/core';\nimport { FormField, FormValueControl } from '@angular/forms/signals';\nimport {\n MatAutocompleteModule,\n MatAutocompleteSelectedEvent,\n MatOption,\n} from '@angular/material/autocomplete';\nimport {\n MatError,\n MatFormField,\n MatHint,\n MatLabel,\n} from '@angular/material/form-field';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatInput } from '@angular/material/input';\n\nimport { SelectItem } from './models';\n\n@Component({\n selector: 'ngx-uik-select-autocomplete-with-vs',\n templateUrl: './select-autocomplete-with-vs.component.html',\n styleUrl: './select-autocomplete-with-vs.component.css',\n\n imports: [\n MatAutocompleteModule,\n MatHint,\n MatError,\n MatOption,\n MatIcon,\n MatFormField,\n ScrollingModule,\n MatInput,\n MatLabel,\n ],\n})\nexport class SelectAutocompleteWithVsComponent\n implements FormValueControl<string | undefined>\n{\n readonly ITEM_HEIGHT_PX = 50;\n readonly MAX_VISIBLE_ITEMS = 4;\n readonly MAX_HEIGHT_PX = 200;\n\n // Инжектим директиву FormField, примененную к нашему компоненту снаружи.\n // { host: true, optional: true } гарантирует, что если компонент рендерят просто так (вне формы), приложение не упадет.\n private readonly formFieldDirective = inject(FormField, { host: true, optional: true });\n\n /** Все элементы. */\n items = input<SelectItem[]>([]); \n /** Заголовок. */\n title = input<string>('');\n /** Ширина. */\n width = input<string>('200');\n\n // Реализация FormValueControl: обязательное свойство value в виде Writable Signal / Model\n readonly value = model<string | undefined>(undefined);\n\n // Сигнал для текстового ввода пользователя, на основе которого идет фильтрация\n readonly filterQuery = model<string>('');\n\n // Декларативно получаем статус disabled напрямую из Signal Forms родителя\n readonly isDisabled = computed(() => {\n return this.formFieldDirective?.state()?.disabled() ?? false;\n });\n\n // Проверяем состояние валидности для отображения ошибки\n readonly isInvalid = computed(() => {\n return this.formFieldDirective?.state()?.invalid() ?? false;\n });\n\n // Создаем дебаунс-сигнал на 200мс от оригинальной модели\n readonly debouncedQuery = debounced(this.filterQuery, 500);\n\n // отфильтрованные (отображаемые) элементы\n // Декларативная фильтрация через computed. Срабатывает автоматически при изменении любого сигнала внутри.\n readonly filteredItems = computed<SelectItem[]>(() => {\n const allItems = this.items();\n const query = this.debouncedQuery.value().toLowerCase().trim();\n\n if (!query) {\n return allItems;\n }\n\n return allItems.filter((option) =>\n option.viewValue.toLowerCase().includes(query)\n );\n });\n\n // Автоматический расчет высоты для Virtual Scroll на основе отфильтрованных элементов\n readonly height = computed<string>(() => {\n const count = this.filteredItems().length;\n return count < this.MAX_VISIBLE_ITEMS ? `${count * this.ITEM_HEIGHT_PX}px` : `${this.MAX_HEIGHT_PX}px`;\n });\n\n constructor() {\n // Решаем проблему №1: Синхронизируем строку ввода при инициализации формы \n // или при программном изменении значения из родительского компонента\n effect(() => {\n const selected = this.selectedItemObject();\n if (selected && this.filterQuery() !== selected.viewValue) {\n this.filterQuery.set(selected.viewValue);\n }\n });\n }\n\n // constructor() {\n // effect(() => {\n // console.log('ITEMS =', this.items());\n // //this.filteredItems = this.items();\n\n // console.log('selectedItem =', this.selectedItemInput());\n // if (this.items().length > 0) {\n // console.log('filteredItems SET');\n // this.setFileredItems(this.items());\n // this.inputCtrl.setValue(this.selectedItemInput());\n // }\n // });\n // }\n\n // ngOnInit(): void {\n // // Listen for changes to the input\n // const subs = this.inputCtrl.valueChanges\n // .pipe(\n // startWith(''),\n // // eslint-disable-next-line no-magic-numbers\n // debounceTime(500),\n // distinctUntilChanged(),\n // // Note: If the option value is bound to object, after selecting the option\n // // Note: the value will change from string to {}. We want to perform search\n // // Note: only when the type is string (no match)\n // //filter(q => typeof q === 'string'),\n // //tap((v) => console.log('v=', v)),\n // map((value) => {\n // // Filter the options\n // console.log('typeof value =', typeof value);\n\n // if (typeof value === 'undefined') {\n // this.setFileredItems(this.items());\n // } else {\n // if (typeof value !== 'object') {\n // console.log('v1=', value);\n // this.setFileredItems(\n // this.items().filter((option) =>\n // option.viewValue.toLowerCase().includes(value.toLowerCase()),\n // ),\n // );\n // } else {\n // // typeof value === 'object'\n // console.log('v2=', value);\n // if (value) {\n // // this.predmet = value;\n // this.setFileredItems(\n // this.items().filter((option) =>\n // option.viewValue\n // .toLowerCase()\n // .includes(value.viewValue.toLowerCase()),\n // ),\n // );\n // console.log('v3=', value);\n // } else {\n // this.setFileredItems(this.items());\n // console.log('v4=', value);\n // }\n // }\n // }\n // }),\n // )\n // .subscribe();\n // this.subscription.add(subs);\n\n // // if (this.isDisabled()) {\n // // this.inputCtrl.disable();\n // // } else {\n // // this.inputCtrl.enable();\n // // }\n // }\n\n\n // onSelectedItemChange(item: any) {\n // console.log('onSelectedItemChange, item=', item);\n // this.selectedItem.set(item);\n // this.selectedItemChange.emit(item);\n // }\n\n // 3. Вычисляем текущий выбранный объект для отображения в шаблоне на основе строки value()\n readonly selectedItemObject = computed(() => {\n const currentKey = this.value();\n return this.items().find(item => item.value === currentKey);\n });\n\n // Срабатывает при физическом клике по опции в автокомплите\n onOptionSelected(event: MatAutocompleteSelectedEvent): void {\n const selected: SelectItem = event.option.value;\n this.value.set(selected.value);\n this.filterQuery.set(selected.viewValue); // Фиксируем текст в инпуте\n }\n\n // Обновление поискового запроса при вводе текста пользователем\n onInputChanges(event: Event): void {\n const inputElement = event.target as HTMLInputElement;\n const currentText = inputElement.value;\n\n this.filterQuery.set(currentText);\n \n // Сбрасываем только если поле полностью пустое!\n if (!currentText) {\n this.value.set(undefined);\n }\n }\n\n // Новая логика: проверка валидности введенного текста строго при потере фокуса\n onBlur(): void {\n const currentText = this.filterQuery().trim();\n const currentSelected = this.selectedItemObject();\n\n // Если текст в инпуте не пустой, но он не совпадает с viewValue выбранного объекта,\n // значит пользователь ввёл случайный набор букв и ушёл из поля. Сбрасываем всё.\n if (currentText && currentText !== currentSelected?.viewValue) {\n this.value.set(undefined);\n this.filterQuery.set('');\n }\n }\n\n onClearClick($event: MouseEvent) {\n $event.stopPropagation();\n this.value.set(undefined);\n this.filterQuery.set('');\n }\n\n displayWithFn(item: SelectItem | null | undefined): string {\n return item ? item.viewValue : '';\n }\n\n // private setFileredItems(items: SelectItem[]) {\n // this.filteredItems = items;\n // // Recompute how big the viewport should be.\n // // eslint-disable-next-line no-magic-numbers\n // if (items.length < 4) {\n // // eslint-disable-next-line no-magic-numbers\n // this.height = items.length * 50 + 'px';\n // } else {\n // this.height = '200px';\n // }\n // console.log('update filteredItems =', this.filteredItems);\n // }\n}\n","<mat-form-field [style.width.px]=\"width()\">\r\n <mat-label>{{ title() }}</mat-label>\r\n <input type=\"text\" matInput [matAutocomplete]=\"auto\" aria-label=\"Number\"\r\n [placeholder]=title() \r\n [value]=\"filterQuery()\"\r\n (input)=\"onInputChanges($event)\"\r\n (blur)=\"onBlur()\"\r\n [disabled]=\"isDisabled()\"\r\n >\r\n @if (!isDisabled() && value()) {\r\n <button mat-button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"onClearClick($event)\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n <mat-autocomplete #auto=\"matAutocomplete\" [displayWith]=\"displayWithFn\" showPanel=\"true\" (optionSelected)=\"onOptionSelected($event)\">\r\n <cdk-virtual-scroll-viewport class=\"autocomplete-test-viewport\" [style.height]=\"height()\" itemSize=\"25\">\r\n <mat-option *cdkVirtualFor=\"let option of filteredItems()\" [value]=\"option.value\" class=\"autocomplete-item\">\r\n {{option.viewValue}}\r\n </mat-option>\r\n </cdk-virtual-scroll-viewport>\r\n </mat-autocomplete>\r\n\r\n <!-- Показываем ошибку, если Signal Forms сообщил, что поле invalid -->\r\n @if (isInvalid()) {\r\n <mat-error>Заполните поле \"{{ title() }}\"</mat-error>\r\n }\r\n\r\n @if (!filterQuery() && !value()) {\r\n <mat-hint>Начните вводить ...</mat-hint>\r\n }\r\n</mat-form-field>\r\n","import { COMMA, ENTER } from '@angular/cdk/keycodes';\n\nimport { Component, input, model } from '@angular/core';\nimport { MatOptgroup, MatOption } from '@angular/material/core';\nimport { MatIcon } from '@angular/material/icon';\nimport {\n MatFormField,\n MatLabel,\n MatSelect,\n MatSelectChange,\n} from '@angular/material/select';\n\nimport { SelectGroup } from './models';\nimport { FormValueControl } from '@angular/forms/signals';\n\n@Component({\n selector: 'ngx-uik-select-with-group',\n templateUrl: './select-with-group.component.html',\n styleUrls: ['./select-with-group.component.css'],\n imports: [MatIcon, MatOption, MatOptgroup, MatSelect, MatFormField, MatLabel],\n})\nexport class SelectWithGroupComponent implements FormValueControl<string[]> {\n /** Все группы. */\n groups = input<SelectGroup[]>([]);\n /** Заголовок. */\n title = input<string>('');\n // FormValueControl требует обязательное свойство value в виде модели/сигнала\n // Инициализируем пустым массивом, так как undefined запрещен в Signal Forms\n /** Выбранные элементы, ключи (BaseSelectItem.value). */\n readonly value = model<string[]>([]);\n\n readonly separatorKeysCodes = [ENTER, COMMA];\n\n onSelectionChange(event: MatSelectChange): void {\n this.value.set(event.value ?? []);\n }\n\n onClearClick($event: MouseEvent) {\n $event.stopPropagation();\n this.value.set([]);\n }\n}\n","<mat-form-field class=\"select-with-group\" appearance=\"fill\">\r\n <mat-label>{{ title() }}</mat-label>\r\n <mat-select [value]=\"value()\" (selectionChange)=\"onSelectionChange($event)\" multiple>\r\n @for (group of groups(); track group.name) {\r\n <mat-optgroup [label]=\"group.name\">\r\n @for (item of group.items; track item.value) {\r\n <mat-option [value]=\"item.value\" >\r\n {{item.viewValue}}\r\n </mat-option>\r\n }\r\n </mat-optgroup>\r\n }\r\n\r\n </mat-select>\r\n @if (value().length > 0) {\r\n <button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"onClearClick($event)\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n</mat-form-field>\r\n","import z from \"zod\";\r\nimport { SortDirection } from \"../../../types/types\";\r\n\r\nexport const SortDirectionSchema = z.custom<SortDirection>(\r\n (val) => val === 'asc' || val === 'desc' || val === '',\r\n { message: \"Допустимы только значения 'asc', 'desc' или ''\" }\r\n);\r\n\r\n// Схема состояния сортировки\r\nexport const SortStateSchema = z.object({\r\n sortActive: z.string(),\r\n sortDirection: SortDirectionSchema,\r\n});\r\n\r\n// Схема состояния пагинации\r\nexport const PageStateSchema = z.object({\r\n pageIndex: z.number().int().min(0),\r\n pageSize: z.number().int().positive(),\r\n});\r\n\r\n// Объединенная схема для состояния таблицы\r\nexport const TableStateSchema = SortStateSchema.merge(PageStateSchema);\r\n\r\n// Автоматически выведенные TypeScript-типы из Zod-схем\r\nexport type SortState = z.infer<typeof SortStateSchema>;\r\nexport type PageState = z.infer<typeof PageStateSchema>;\r\nexport type TableState = z.infer<typeof TableStateSchema>;\r\n","import { MatPaginatorIntl } from '@angular/material/paginator';\r\n\r\nexport function getRuPaginatorIntl() {\r\n const intl = new MatPaginatorIntl();\r\n intl.itemsPerPageLabel = 'Записей на странице';\r\n intl.firstPageLabel = 'Первая страница';\r\n intl.previousPageLabel = 'Предыдущая страница';\r\n intl.nextPageLabel = 'Следующая страница';\r\n intl.lastPageLabel = 'Последняя страница';\r\n return intl;\r\n}\r\n","import {\n Component,\n computed,\n effect,\n input,\n linkedSignal,\n output,\n untracked,\n viewChild,\n} from '@angular/core';\nimport { MatIconButton } from '@angular/material/button';\nimport { MatCheckbox } from '@angular/material/checkbox';\nimport { MatDivider } from '@angular/material/divider';\nimport { MatIcon } from '@angular/material/icon';\nimport {\n MatMenu,\n MatMenuContent,\n MatMenuItem,\n MatMenuTrigger,\n} from '@angular/material/menu';\nimport {\n MatPaginator,\n MatPaginatorIntl,\n MatPaginatorModule,\n PageEvent,\n} from '@angular/material/paginator';\nimport { MatSort, MatSortModule, Sort } from '@angular/material/sort';\nimport { MatTableDataSource, MatTableModule } from '@angular/material/table';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { RouterLink } from '@angular/router';\n\nimport { SignalSelectionModel } from '@kuzntsv/uikit';\nimport { BaseSchemaClass } from '../../base';\nimport { IColumnOptions } from './models/column-options.interface';\nimport { IContextMenuOptions } from './models/context-menu-options.interface';\nimport { PageState, SortState, TableState } from './models/table-state';\nimport { getRuPaginatorIntl } from './ru-paginator.intl';\n\n@Component({\n selector: 'ngx-uik-table',\n templateUrl: './table.component.html',\n styleUrls: ['./table.component.css'],\n imports: [\n MatTableModule, // Оптимизировано: импортируем модуль целиком вместо поштучных директив\n MatSortModule,\n MatPaginatorModule,\n MatCheckbox,\n MatIcon,\n RouterLink,\n MatMenuTrigger,\n MatMenu,\n MatMenuContent,\n MatDivider,\n MatMenuItem,\n MatTooltipModule,\n MatIconButton,\n ],\n providers: [{ provide: MatPaginatorIntl, useFactory: getRuPaginatorIntl }],\n})\nexport class TableComponent<T extends BaseSchemaClass> {\n /** Отображаемые данные. */\n data = input<T[]>([]);\n /** Количество записей. */\n length = input<number>(0);\n /** Настройки колонок. */\n columnOptions = input<IColumnOptions<T>[]>([]);\n /** Состояние сортировки, пагинации. */\n tableState = input.required<TableState>();\n /** Разрешен выбор нескольких строк. */\n allowMultiSelect = input<boolean>(false);\n /** Список элементов контекстного меню. */\n opt = input<IContextMenuOptions<T>[]>([]);\n /** Отправка события rowDoubleClicked (при двойном щелчке мышью) отключена. */\n rowDblClickedDisable = input<boolean>(false);\n /** Отображать строку с итогом. */\n footer = input<boolean>(false);\n\n /** Изменение страницы. */\n pageStateChange = output<PageState>();\n /** Изменение сортировки. */\n sortStateChange = output<SortState>();\n /** Изменение выбранных записей. */\n selectionChange = output<T[]>();\n /** Двойной щелчек ЛКМ*/\n rowDoubleClicked = output<T>();\n\n readonly sort = viewChild(MatSort);\n readonly paginator = viewChild(MatPaginator);\n readonly contextMenu = viewChild(MatMenuTrigger);\n\n pageState = linkedSignal<PageState>(() => {\n return {\n pageIndex: this.tableState().pageIndex,\n pageSize: this.tableState().pageSize,\n };\n });\n\n sortState = linkedSignal<SortState>(() => {\n return {\n sortActive: this.tableState().sortActive,\n sortDirection: this.tableState().sortDirection,\n };\n });\n\n /** Выбранная строка, для которого будет показываться меню при нажатии правой кнопки мыши. */\n itemForMenu?: T;\n /** Позиция в которой отображается контекстное меню. */\n contextMenuPosition = { x: '0px', y: '0px' };\n\n // eslint-disable-next-line no-magic-numbers\n readonly defaultPageIndex = 0;\n // eslint-disable-next-line no-magic-numbers\n readonly defaultPageSize = 10;\n\n /** Источник данных для отображения. */\n dataSource = new MatTableDataSource<T>();\n\n /** Выбранные записи. */\n // Инициализируем нашу кастомную модель выбора.\n // Использование computed позволяет пересоздавать модель только при изменении allowMultiSelect.\n selection = computed(() => {\n return new SignalSelectionModel<T>(\n this.allowMultiSelect(),\n [],\n (a, b) => a?.id === b?.id, // Сравнение по бизнес-ключу (id) для защиты при смене страниц\n );\n });\n\n /** Список отображаемых колонок (формируется из @columnOptions). */\n // 3. Вычисляемые сигналы (computed) для автоматического расчета колонок\n displayedColumns = computed<string[]>(() => {\n const cols =\n this.columnOptions()\n ?.filter((c) => !c.hide)\n .map((item) => item.name) || [];\n return ['select', ...cols];\n });\n\n // Оптимизированный подсчет итогов через computed\n totals = computed<Record<string, number | string>>(() => {\n const currentData = this.data();\n const options = this.columnOptions();\n const result: Record<string, number | string> = {};\n\n options.forEach((col) => {\n if (!col.footer) return;\n const values = currentData\n .map((t) => t[col.name as keyof T] as unknown)\n .filter((v): v is number => typeof v === 'number');\n\n result[col.name] = values.length\n ? values.reduce((acc, v) => acc + v, 0)\n : '';\n });\n\n return result;\n });\n\n constructor() {\n // 4. Декларативное связывание данных бэкенда с таблицей Angular Material\n effect(() => {\n // Ключевой момент: [...arr] создает новую ссылку, что заставляет MatTable перерисоваться при OnPush\n this.dataSource.data = [...this.data()];\n\n // Автоматическое сохранение выделения по ссылке (или по ID)\n const currentData = this.data();\n const model = this.selection();\n\n untracked(() => {\n // Находим элементы на новой странице, которые соответствуют ранее выбранным ID\n const nextSelected = currentData.filter((item) =>\n model.isSelected(item),\n );\n\n // Синхронизируем состояние модели без зацикливания эффекта\n if (nextSelected.length > 0) {\n model.select(...nextSelected);\n }\n });\n });\n\n // Эффект для уведомления родительского компонента об изменении выделения\n effect(() => {\n const selectedArray = this.selection().selected();\n untracked(() => this.selectionChange.emit(selectedArray));\n });\n }\n\n onPageEvent(event: PageEvent) {\n const newState = { pageIndex: event.pageIndex, pageSize: event.pageSize };\n this.pageState.set(newState);\n this.pageStateChange.emit(newState);\n }\n\n onSortEvent(sort: Sort) {\n const newState = { sortActive: sort.active, sortDirection: sort.direction };\n this.sortState.set(newState);\n this.sortStateChange.emit(newState);\n }\n\n /** Whether the number of selected elements matches the total number of rows. */\n isAllSelected() {\n const pageRows = this.dataSource.data;\n if (pageRows.length === 0) return false;\n return pageRows.every((row) => this.selection().isSelected(row));\n }\n\n /** Selects all rows if they are not all selected; otherwise clear selection. */\n masterToggle() {\n if (this.isAllSelected()) {\n this.selection().clear();\n } else {\n this.selection().select(...this.dataSource.data);\n }\n }\n\n /** При щелчке по строке. */\n onRowClicked(row: T) {\n this.selection().toggle(row);\n }\n\n /** При двойном щелчке по строке. */\n onRowDblClicked(row: T) {\n // выделение строки при двойном щелчке по строке\n this.selection().clear();\n this.selection().select(row);\n if (!this.rowDblClickedDisable()) this.rowDoubleClicked.emit(row);\n }\n\n /** При вызове контекстного меню. */\n onContextMenu(event: MouseEvent, itemForMenu: T | undefined) {\n if (this.opt() && this.opt().length === 0) {\n // если нет пунктов меню, то не показываем меню\n return;\n }\n event.preventDefault();\n this.itemForMenu = itemForMenu;\n this.contextMenuPosition.x = event.clientX + 'px';\n this.contextMenuPosition.y = event.clientY + 'px';\n // как это (menuData) использовать в шаблоне не понятно, поэтому использую this.itemForMenu\n // https://www.concretepage.com/angular-material/passing-data-to-mat-menu-angular-material\n const contextMenu = this.contextMenu();\n if (contextMenu) {\n contextMenu.menuData = { itemForMenu };\n contextMenu.menu?.focusFirstItem('mouse');\n contextMenu.openMenu();\n }\n }\n}\n","<div class=\"component-container\">\r\n <div class=\"table-container\">\r\n <table\r\n mat-table\r\n [dataSource]=\"dataSource\"\r\n matSort\r\n [matSortActive]=\"sortState().sortActive\"\r\n [matSortDirection]=\"sortState().sortDirection\"\r\n (matSortChange)=\"onSortEvent($event)\"\r\n matSortDisableClear\r\n >\r\n <!-- Выбор строки Column -->\r\n <ng-container matColumnDef=\"select\">\r\n <th mat-header-cell *matHeaderCellDef>\r\n @if (allowMultiSelect()) {\r\n <mat-checkbox\r\n (change)=\"$event ? masterToggle() : null\"\r\n [checked]=\"selection().hasValue() && isAllSelected()\"\r\n [indeterminate]=\"selection().hasValue() && !isAllSelected()\"\r\n >\r\n </mat-checkbox>\r\n }\r\n </th>\r\n <td mat-cell *matCellDef=\"let row\">\r\n <mat-checkbox\r\n (click)=\"$event.stopPropagation()\"\r\n (change)=\"$event ? onRowClicked(row) : null\"\r\n [checked]=\"selection().isSelected(row)\"\r\n >\r\n </mat-checkbox>\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n }\r\n </ng-container>\r\n\r\n @for (item of columnOptions(); track item.name) {\r\n <ng-container [matColumnDef]=\"item.name\">\r\n <th\r\n mat-header-cell\r\n *matHeaderCellDef\r\n mat-sort-header\r\n [disabled]=\"item.titleSortDisable\"\r\n >\r\n {{ item.title }}\r\n </th>\r\n\r\n <td\r\n mat-cell\r\n *matCellDef=\"let element\"\r\n (contextmenu)=\"onContextMenu($event, element)\"\r\n [matTooltip]=\"item.tooltip ?? ''\"\r\n >\r\n @switch (item.format) {\r\n @case (\"pre-wrap\") {\r\n {{ element[item.name] }}\r\n }\r\n @case (\"link\") {\r\n <a [href]=\"element[item.name]\" target=\"_blank\">{{\r\n element[item.name]\r\n }}</a>\r\n }\r\n @case (\"linkIcon\") {\r\n @if (element[item.name]) {\r\n <a [href]=\"element[item.name]\" target=\"_blank\">\r\n @if (item.icon) {\r\n <mat-icon\r\n [class]=\"item.classList ? item.classList : ''\"\r\n >{{ item.icon }}</mat-icon\r\n >\r\n }\r\n @if (item.symbol) {\r\n <span [class]=\"item.classList ? item.classList : ''\">{{\r\n item.symbol\r\n }}</span>\r\n }\r\n </a>\r\n }\r\n }\r\n @case (\"routerLink\") {\r\n <a [routerLink]=\"[element[item.name]]\">{{\r\n element[item.name]\r\n }}</a>\r\n }\r\n @case (\"routerLinkIcon\") {\r\n @if (element[item.name]) {\r\n <a [routerLink]=\"[element[item.name]]\">\r\n @if (item.icon) {\r\n <mat-icon\r\n [class]=\"item.classList ? item.classList : ''\"\r\n >{{ item.icon }}</mat-icon\r\n >\r\n }\r\n @if (item.symbol) {\r\n <span [class]=\"item.classList ? item.classList : ''\">{{\r\n item.symbol\r\n }}</span>\r\n }\r\n </a>\r\n }\r\n }\r\n @case (\"checkbox\") {\r\n <mat-checkbox\r\n [checked]=\"element[item.name] === 1\"\r\n [disabled]=\"true\"\r\n ></mat-checkbox>\r\n }\r\n @case (\"icon\") {\r\n @if (item.icon) {\r\n <mat-icon [class]=\"item.classList ? item.classList : ''\">{{\r\n item.icon\r\n }}</mat-icon>\r\n }\r\n @if (item.symbol) {\r\n <span [class]=\"item.classList ? item.classList : ''\">{{\r\n item.symbol\r\n }}</span>\r\n }\r\n }\r\n @case (\"icons\") {\r\n @if (item.icons) {\r\n <mat-icon\r\n [class]=\"\r\n item.classList ? item.classList[element[item.name]] : ''\r\n \"\r\n [matTooltip]=\"\r\n item.tooltips ? item.tooltips[element[item.name]] : ''\r\n \"\r\n >{{ item.icons[element[item.name]] }}</mat-icon\r\n >\r\n }\r\n @if (item.symbols) {\r\n <span\r\n [class]=\"\r\n item.classList ? item.classList[element[item.name]] : ''\r\n \"\r\n >{{ item.symbols[element[item.name]] }}</span\r\n >\r\n }\r\n }\r\n @case (\"actions\") {\r\n @if (item.actions) {\r\n <div class=\"actions-container\">\r\n @for (action of item.actions; track action) {\r\n @if (\r\n !(action.hideFn ? action.hideFn(element) : action.hide)\r\n ) {\r\n <button\r\n mat-icon-button\r\n (click)=\"\r\n action.onClickFn ? action.onClickFn(element) : ''\r\n \"\r\n (mousedown)=\"\r\n action.onClickMiddleFn\r\n ? action.onClickMiddleFn($event, element)\r\n : ''\r\n \"\r\n [disabled]=\"\r\n action.disabledFn\r\n ? action.disabledFn(element)\r\n : action.disabled\r\n \"\r\n [matTooltip]=\"action.tooltip ? action.tooltip : ''\"\r\n >\r\n @if (action.icon) {\r\n <mat-icon\r\n [class]=\"action.classList ? action.classList : ''\"\r\n >{{ action.icon }}</mat-icon\r\n >\r\n }\r\n @if (action.symbol) {\r\n <span\r\n [class]=\"action.classList ? action.classList : ''\"\r\n >{{ action.symbol }}</span\r\n >\r\n }\r\n {{ action.title }}\r\n </button>\r\n }\r\n }\r\n </div>\r\n }\r\n }\r\n @case (\"image\") {\r\n @if (element[item.name]) {\r\n <img\r\n [src]=\"element[item.name]\"\r\n [alt]=\"\r\n item.imageAlt && element[item.imageAlt]\r\n ? element[item.imageAlt]\r\n : ''\r\n \"\r\n [class]=\"item.classList ? item.classList : ''\"\r\n />\r\n }\r\n }\r\n @default {\r\n {{ element[item.name] }}\r\n }\r\n }\r\n </td>\r\n\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (footer()) {\r\n @if (!item.format && item.footer) {\r\n <strong>{{ totals()[item.name] }}</strong>\r\n }\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n\r\n <tr class=\"mat-row\" *matNoDataRow>\r\n <td class=\"mat-cell\" colspan=\"9999\">Нет данных для отображения</td>\r\n </tr>\r\n\r\n <tr\r\n mat-header-row\r\n *matHeaderRowDef=\"displayedColumns(); sticky: true\"\r\n ></tr>\r\n <tr\r\n mat-row\r\n *matRowDef=\"let row; columns: displayedColumns()\"\r\n (click)=\"onRowClicked(row)\"\r\n (dblclick)=\"onRowDblClicked(row)\"\r\n class=\"element-row\"\r\n [class.selected-row]=\"selection().isSelected(row)\"\r\n ></tr>\r\n @if (footer()) {\r\n <tr\r\n mat-footer-row\r\n *matFooterRowDef=\"displayedColumns(); sticky: true\"\r\n ></tr>\r\n }\r\n </table>\r\n <div\r\n style=\"visibility: hidden; position: fixed\"\r\n [style.left]=\"contextMenuPosition.x\"\r\n [style.top]=\"contextMenuPosition.y\"\r\n [matMenuTriggerFor]=\"contextMenu\"\r\n #menuTrigger=\"matMenuTrigger\"\r\n ></div>\r\n <mat-menu #contextMenu=\"matMenu\">\r\n <ng-template matMenuContent let-id=\"id\">\r\n @for (menuItem of opt(); track menuItem) {\r\n @if (\r\n menuItem.title === \"-\" &&\r\n !(menuItem.hideFn ? menuItem.hideFn(itemForMenu) : menuItem.hide)\r\n ) {\r\n <mat-divider></mat-divider>\r\n }\r\n @if (\r\n menuItem.title !== \"-\" &&\r\n !(menuItem.hideFn ? menuItem.hideFn(itemForMenu) : menuItem.hide)\r\n ) {\r\n <button\r\n mat-menu-item\r\n (click)=\"\r\n menuItem.onClickFn ? menuItem.onClickFn(itemForMenu) : ''\r\n \"\r\n (mousedown)=\"\r\n menuItem.onClickMiddleFn\r\n ? menuItem.onClickMiddleFn($event, itemForMenu, menuTrigger)\r\n : ''\r\n \"\r\n [disabled]=\"\r\n menuItem.disabledFn\r\n ? menuItem.disabledFn(itemForMenu)\r\n : menuItem.disabled\r\n \"\r\n >\r\n @if (menuItem.icon) {\r\n <mat-icon\r\n [class]=\"menuItem.classList ? menuItem.classList : ''\"\r\n >{{ menuItem.icon }}</mat-icon\r\n >\r\n }\r\n @if (menuItem.symbol) {\r\n <span [class]=\"menuItem.classList ? menuItem.classList : ''\">{{\r\n menuItem.symbol\r\n }}</span>\r\n }\r\n {{ menuItem.title }}\r\n </button>\r\n }\r\n }\r\n </ng-template>\r\n </mat-menu>\r\n </div>\r\n\r\n <mat-paginator\r\n [length]=\"length()\"\r\n [pageIndex]=\"pageState().pageIndex || defaultPageIndex\"\r\n [pageSizeOptions]=\"[5, 10, 20, 50, 100]\"\r\n [pageSize]=\"pageState().pageSize || defaultPageSize\"\r\n (page)=\"onPageEvent($event)\"\r\n showFirstLastButtons\r\n itemsPerPageLabel=\"\"\r\n ></mat-paginator>\r\n</div>\r\n","import { HttpErrorResponse, HttpHeaders } from '@angular/common/http';\r\nimport { SchemaPath, validateHttp } from '@angular/forms/signals';\r\nimport { X_SKIP_LOADER, X_SKIP_NOTIFICATION } from '@kuzntsv/uikit';\r\n\r\ninterface UniqueCodeOptions {\r\n endpoint: string;\r\n errorMessage: string;\r\n useEquals?: boolean;\r\n}\r\n\r\nexport function uniqueCodeValidator(\r\n field: SchemaPath<number | null>,\r\n formSchema: any,\r\n options: UniqueCodeOptions,\r\n) {\r\n validateHttp(field, {\r\n debounce: 500,\r\n\r\n // Конфигурируем запрос через объект\r\n request: ({ value }) => {\r\n const code = value();\r\n if (code === null || code === undefined) return undefined;\r\n\r\n const divider = options.useEquals ? '=' : '/';\r\n return {\r\n url: `${options.endpoint}${divider}${encodeURIComponent(code)}`,\r\n method: 'GET',\r\n headers: new HttpHeaders({\r\n [X_SKIP_NOTIFICATION]: 'true',\r\n [X_SKIP_LOADER]: 'true'\r\n }),\r\n };\r\n },\r\n onSuccess: (\r\n foundEntity: { id: number; code: number } | null,\r\n { value, valueOf },\r\n ) => {\r\n // Объект с таким кодом не найден — имя уникально\r\n if (!foundEntity) return null;\r\n\r\n const currentId = valueOf(formSchema.id);\r\n const currentCode = value() || 0;\r\n\r\n // Если код совпал, но это та же самая запись, которую мы редактируем — всё ок.\r\n // Если ID разные — код занят.\r\n const isUnique =\r\n currentId === foundEntity.id ||\r\n (currentId !== foundEntity.id && currentCode !== foundEntity.code);\r\n return isUnique\r\n ? null\r\n : { kind: 'uniqueCode', message: options.errorMessage };\r\n },\r\n onError: (error: unknown) => {\r\n // Если прилетел 404 статус — это наш \"успех\" (записи нет, имя уникально)\r\n if (error instanceof HttpErrorResponse && error.status === 404)\r\n return null;\r\n console.error(`Ошибка валидации кода на ${options.endpoint}:`, error);\r\n return {\r\n kind: 'serverError',\r\n message: 'Не удалось проверить код на сервере',\r\n };\r\n },\r\n });\r\n}\r\n","import { HttpErrorResponse, HttpHeaders } from '@angular/common/http';\r\nimport { SchemaPath, validateHttp } from '@angular/forms/signals';\r\nimport { X_SKIP_LOADER, X_SKIP_NOTIFICATION } from '@kuzntsv/uikit';\r\n\r\ninterface UniqueNameOptions {\r\n endpoint: string;\r\n errorMessage: string;\r\n useEquals?: boolean;\r\n}\r\n\r\nexport function uniqueNameValidator(\r\n field: SchemaPath<string>,\r\n formSchema: any,\r\n options: UniqueNameOptions,\r\n) {\r\n validateHttp(field, {\r\n debounce: 500,\r\n\r\n // Конфигурируем запрос через объект\r\n request: ({ value }) => {\r\n const name = (value() || '').trim();\r\n if (!name) return undefined;\r\n\r\n const divider = options.useEquals ? '=' : '/';\r\n return {\r\n url: `${options.endpoint}${divider}${encodeURIComponent(name)}`,\r\n method: 'GET',\r\n headers: new HttpHeaders({\r\n [X_SKIP_NOTIFICATION]: 'true',\r\n [X_SKIP_LOADER]: 'true'\r\n }),\r\n };\r\n },\r\n onSuccess: (\r\n foundEntity: { id: number; name: string } | null,\r\n { value, valueOf },\r\n ) => {\r\n // Объект с таким именем не найден — имя уникально\r\n if (!foundEntity) return null;\r\n\r\n const currentId = valueOf(formSchema.id);\r\n const currentName = (value() || '').trim();\r\n\r\n // Если имя совпало, но это та же самая запись, которую мы редактируем — всё ок.\r\n // Если ID разные — имя занято.\r\n const isUnique =\r\n currentId === foundEntity.id ||\r\n (currentId !== foundEntity.id &&\r\n currentName.toUpperCase() !== foundEntity.name.toUpperCase());\r\n return isUnique\r\n ? null\r\n : { kind: 'uniqueName', message: options.errorMessage };\r\n },\r\n onError: (error: unknown) => {\r\n // Если прилетел 404 статус — это наш \"успех\" (записи нет, имя уникально)\r\n if (error instanceof HttpErrorResponse && error.status === 404)\r\n return null;\r\n console.error(`Ошибка валидации имени на ${options.endpoint}:`, error);\r\n return {\r\n kind: 'serverError',\r\n message: 'Не удалось проверить имя на сервере',\r\n };\r\n },\r\n });\r\n}\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"kuzntsv-uikit-ui.mjs","names":[],"sources":["../../ui/src/base/base-toolbar/components/base-toolbar.component.ts","../../ui/src/base/base-toolbar/components/base-toolbar.component.html","../../ui/src/base/base-classes/base-class.ts","../../ui/src/base/base-classes/base-edit-dialog-data.ts","../../ui/src/base/base-classes/base-edit-class.ts","../../ui/src/base/base-classes/base-entity-action.ts","../../ui/src/services/avatar.service.ts","../../ui/src/services/local-storage-service.ts","../../ui/src/services/secure-image.service.ts","../../ui/src/services/export.service.ts","../../ui/src/services/sse/sse.service.ts","../../ui/src/base/base-classes/base-filter-class.ts","../../ui/src/base/base-classes/base-nav-bar-menu-class.ts","../../ui/src/shared/dialog/dialog.component.ts","../../ui/src/shared/dialog/dialog.component.html","../../ui/src/base/base-classes/base-page-class.ts","../../ui/src/base/base-classes/base-service-class.ts","../../ui/src/base/base-classes/base-signal-edit-class.ts","../../ui/src/base/base-classes/base-signal-filter-class.ts","../../ui/src/base/base-classes/base-filter.model.ts","../../ui/src/base/base-classes/base-signal-page-class.ts","../../ui/src/base/base-classes/base-signal-service-class.ts","../../ui/src/directives/disable-if-role.directive.ts","../../ui/src/directives/hide-if-forbidden-role.directive.ts","../../ui/src/directives/set-value.directive.ts","../../ui/src/guards/auth.guard.ts","../../ui/src/guards/redirect.guard.ts","../../ui/src/guards/role.guard.ts","../../ui/src/logger/logger.config.ts","../../ui/src/logger/logger.service.ts","../../ui/src/logger/logger.provider.ts","../../ui/src/models/sec-user-view.model.ts","../../ui/src/models/sec-user.model.ts","../../ui/src/pipes/safe.pipe.ts","../../ui/src/pipes/time.pipe.ts","../../ui/src/pipes/truncate.pipe.ts","../../ui/src/shared/chip-input-autocomplete/chip-input-autocomplete.component.ts","../../ui/src/shared/chip-input-autocomplete/chip-input-autocomplete.component.html","../../ui/src/shared/date-range-input/models/custom-date-adapter.ts","../../ui/src/shared/date-range-input/models/date-range.ts","../../ui/src/shared/date-range-input/date-range-input.component.ts","../../ui/src/shared/date-range-input/date-range-input.component.html","../../ui/src/shared/dialog/models/dialog-action.ts","../../ui/src/shared/empty/empty.ts","../../ui/src/shared/login/models/authenticate.ts","../../ui/src/shared/login/components/login-form/login-form.component.ts","../../ui/src/shared/login/components/login-form/login-form.component.html","../../ui/src/shared/login/components/permit-form/permit-form.component.ts","../../ui/src/shared/login/components/permit-form/permit-form.component.html","../../ui/src/shared/login/components/login-page/login-page.component.ts","../../ui/src/shared/login/components/login-page/login-page.component.html","../../ui/src/shared/navbar/navbar.ts","../../ui/src/shared/navbar/navbar.html","../../ui/src/shared/not-found/not-found.component.ts","../../ui/src/shared/not-found/not-found.component.html","../../ui/src/shared/select-autocomplete-with-vs/select-autocomplete-with-vs.component.ts","../../ui/src/shared/select-autocomplete-with-vs/select-autocomplete-with-vs.component.html","../../ui/src/shared/select-with-group/select-with-group.component.ts","../../ui/src/shared/select-with-group/select-with-group.component.html","../../ui/src/shared/table/models/table-state.ts","../../ui/src/shared/table/ru-paginator.intl.ts","../../ui/src/shared/table/table.component.ts","../../ui/src/shared/table/table.component.html","../../ui/src/validators/unique-code.validator.ts","../../ui/src/validators/unique-name.validator.ts"],"sourcesContent":["import {\n Component,\n computed,\n inject,\n input,\n output,\n ChangeDetectionStrategy,\n} from '@angular/core';\nimport { MatIconButton } from '@angular/material/button';\nimport { MatDivider } from '@angular/material/divider';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';\nimport { MatToolbar } from '@angular/material/toolbar';\nimport { MatTooltip } from '@angular/material/tooltip';\n\nimport { RoleService } from '@kuzntsv/uikit';\nimport { IContextMenuOptions } from '../../../shared/table';\n\n@Component({\n selector: 'ngx-uik-base-toolbar',\n templateUrl: 'base-toolbar.component.html',\n styleUrls: ['base-toolbar.component.scss'],\n changeDetection: ChangeDetectionStrategy.Eager,\n imports: [\n MatToolbar,\n MatIconButton,\n MatTooltip,\n MatIcon,\n MatMenu,\n MatDivider,\n MatMenuTrigger,\n MatMenuItem,\n ],\n})\nexport class BaseToolbarComponent {\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesNewBtn = input<string[]>([]);\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesEditBtn = input<string[]>([]);\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesRemoveBtn = input<string[]>([]);\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesCopyBtn = input<string[]>([]);\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesExcelBtn = input<string[]>([]);\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesCsvBtn = input<string[]>([]);\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesPdfBtn = input<string[]>([]);\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesPrintBtn = input<string[]>([]);\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesRefreshBtn = input<string[]>([]);\n /**\n * Список Ролей, для которых кнопка видна. Если в списке есть роль 'HIDE', то скрывается.\n */\n rolesClearBtn = input<string[]>([]);\n\n // Состояния блокировки\n newBtnDisabled = input<boolean>(false);\n editBtnDisabled = input<boolean>(false);\n removeBtnDisabled = input<boolean>(false);\n copyBtnDisabled = input<boolean>(false);\n excelBtnDisabled = input<boolean>(false);\n csvBtnDisabled = input<boolean>(false);\n pdfBtnDisabled = input<boolean>(false);\n printBtnDisabled = input<boolean>(false);\n refreshBtnDisabled = input<boolean>(false);\n clearBtnDisabled = input<boolean>(false);\n\n // Тултипы\n newBtnTooltip = input<string>('Добавить');\n editBtnTooltip = input<string>('Изменить');\n removeBtnTooltip = input<string>('Удалить');\n copyBtnTooltip = input<string>('Скопировать');\n excelBtnTooltip = input<string>('Экспортировать в Excel');\n csvBtnTooltip = input<string>('Экспортировать в Csv');\n pdfBtnTooltip = input<string>('Экспортировать в Pdf');\n printBtnTooltip = input<string>('Печатать');\n refreshBtnTooltip = input<string>('Обновить данные');\n clearBtnTooltip = input<string>('Очистить фильтр');\n\n /** Список элементов контекстного меню. */\n newBtnOpt = input<IContextMenuOptions<string>[]>([]);\n\n // События\n clickedNewBtn = output();\n clickedEditBtn = output();\n clickedRemoveBtn = output();\n clickedCopyBtn = output();\n clickedExcelBtn = output();\n clickedCsvBtn = output();\n clickedPdfBtn = output();\n clickedPrintBtn = output();\n clickedRefreshBtn = output();\n clickedClearBtn = output();\n\n // DI\n // protected authService = inject(AuthService);\n protected roleService = inject(RoleService);\n\n // Вычисляемые сигналы видимости кнопок.\n readonly isNewBtnVisible = computed(() =>\n this.checkVisibility(this.rolesNewBtn()),\n );\n readonly isEditBtnVisible = computed(() =>\n this.checkVisibility(this.rolesEditBtn()),\n );\n readonly isRemoveBtnVisible = computed(() =>\n this.checkVisibility(this.rolesRemoveBtn()),\n );\n readonly isCopyBtnVisible = computed(() =>\n this.checkVisibility(this.rolesCopyBtn()),\n );\n readonly isExcelBtnVisible = computed(() =>\n this.checkVisibility(this.rolesExcelBtn()),\n );\n readonly isCsvBtnVisible = computed(() =>\n this.checkVisibility(this.rolesCsvBtn()),\n );\n readonly isPdfBtnVisible = computed(() =>\n this.checkVisibility(this.rolesPdfBtn()),\n );\n readonly isPrintBtnVisible = computed(() =>\n this.checkVisibility(this.rolesPrintBtn()),\n );\n readonly isRefreshBtnVisible = computed(() =>\n this.checkVisibility(this.rolesRefreshBtn()),\n );\n readonly isClearBtnVisible = computed(() =>\n this.checkVisibility(this.rolesClearBtn()),\n );\n\n /**\n * Внутренний метод для вычисления видимости.\n * Не вызывается напрямую из шаблона, а служит хелпером для декларативных computed.\n * Проверяет, заблокирован ли доступ к элементу на основе списка ограничений.\n * Возвращает true, если у пользователя есть запрещенная роль или передан маркер 'HIDE'.\n * Администратор (ADMIN) всегда игнорирует любые запреты и маркер 'HIDE'.\n */\n private checkVisibility(forbiddenRoles: string[]): boolean {\n return !this.roleService.hasForbiddenRole(forbiddenRoles);\n }\n\n onNewClick() {\n this.clickedNewBtn.emit();\n }\n\n onEditClick() {\n this.clickedEditBtn.emit();\n }\n\n onRemoveClick() {\n this.clickedRemoveBtn.emit();\n }\n\n onCopyClick() {\n this.clickedCopyBtn.emit();\n }\n\n onExcelClick() {\n this.clickedExcelBtn.emit();\n }\n\n onCsvClick() {\n this.clickedCsvBtn.emit();\n }\n\n onPdfClick() {\n this.clickedPdfBtn.emit();\n }\n\n onPrintClick() {\n this.clickedPrintBtn.emit();\n }\n\n onRefreshGridClick() {\n this.clickedRefreshBtn.emit();\n }\n\n onClearClick() {\n this.clickedClearBtn.emit();\n }\n}\n","<mat-toolbar>\r\n @if (isNewBtnVisible()) {\r\n @if (newBtnOpt() && newBtnOpt().length > 0) {\r\n <button [disabled]=\"newBtnDisabled()\" [matMenuTriggerFor]=\"menuNewBtn\"\r\n mat-icon-button [matTooltip]=\"newBtnTooltip()\">\r\n <mat-icon>add</mat-icon>\r\n </button>\r\n <mat-menu #menuNewBtn=\"matMenu\">\r\n @for (menuItem of newBtnOpt(); track menuItem) {\r\n @if (menuItem.title === '-' && !(menuItem.hideFn ? menuItem.hideFn(\"\") : menuItem.hide)) {\r\n <mat-divider></mat-divider>\r\n }\r\n @if (menuItem.title !== '-' && !(menuItem.hideFn ? menuItem.hideFn(\"\") : menuItem.hide)) {\r\n <button mat-menu-item\r\n (click)=\"menuItem.onClickFn ? menuItem.onClickFn('') : ''\"\r\n [disabled]=\"menuItem.disabledFn ? menuItem.disabledFn('') : menuItem.disabled\">\r\n @if (menuItem.icon) {\r\n <mat-icon>{{menuItem.icon}}</mat-icon>\r\n }\r\n {{ menuItem.title }}\r\n </button>\r\n }\r\n }\r\n </mat-menu>\r\n } \r\n @else {\r\n <button [disabled]=\"newBtnDisabled()\" (click)=\"onNewClick()\"\r\n mat-icon-button routerLink=\"new\" routerLinkActive=\"active\" [matTooltip]=\"newBtnTooltip()\">\r\n <mat-icon>add</mat-icon>\r\n </button>\r\n }\r\n }\r\n\r\n @if (isEditBtnVisible()) {\r\n <button [disabled]=\"editBtnDisabled()\" (click)=\"onEditClick()\"\r\n mat-icon-button routerLink=\"edit\" color=\"primary\" routerLinkActive=\"active\" [matTooltip]=\"editBtnTooltip()\">\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n }\r\n @if (isRemoveBtnVisible()) {\r\n <button [disabled]=\"removeBtnDisabled()\" (click)=\"onRemoveClick()\"\r\n mat-icon-button routerLink=\"delete\" color=\"warn\" routerLinkActive=\"active\" [matTooltip]=\"removeBtnTooltip()\">\r\n <mat-icon>remove</mat-icon>\r\n </button>\r\n }\r\n @if (isCopyBtnVisible()) {\r\n <button [disabled]=\"copyBtnDisabled()\" (click)=\"onCopyClick()\"\r\n mat-icon-button routerLink=\"delete\" routerLinkActive=\"active\" [matTooltip]=\"copyBtnTooltip()\">\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n }\r\n @if (isExcelBtnVisible()) {\r\n <button [disabled]=\"excelBtnDisabled()\" (click)=\"onExcelClick()\"\r\n mat-icon-button routerLink=\"excel\" routerLinkActive=\"active\" [matTooltip]=\"excelBtnTooltip()\">\r\n <mat-icon class=\"material-icons-outlined\">explicit</mat-icon>\r\n </button>\r\n }\r\n @if (isCsvBtnVisible()) {\r\n <button [disabled]=\"csvBtnDisabled()\" (click)=\"onCsvClick()\"\r\n mat-icon-button routerLink=\"csv\" routerLinkActive=\"active\" [matTooltip]=\"csvBtnTooltip()\">\r\n <mat-icon class=\"material-icons-outlined\">download</mat-icon>\r\n </button>\r\n }\r\n @if (isPdfBtnVisible()) {\r\n <button [disabled]=\"pdfBtnDisabled()\" (click)=\"onPdfClick()\"\r\n mat-icon-button routerLink=\"pdf\" routerLinkActive=\"active\" [matTooltip]=\"pdfBtnTooltip()\">\r\n <mat-icon class=\"material-icons-outlined\">picture_as_pdf</mat-icon>\r\n </button>\r\n }\r\n @if (isPrintBtnVisible()) {\r\n <button [disabled]=\"printBtnDisabled()\" (click)=\"onPrintClick()\"\r\n mat-icon-button routerLink=\"print\" routerLinkActive=\"active\" [matTooltip]=\"printBtnTooltip()\">\r\n <mat-icon class=\"material-icons-outlined\">print_outline</mat-icon>\r\n </button>\r\n }\r\n @if (isRefreshBtnVisible()) {\r\n <button [disabled]=\"refreshBtnDisabled()\" (click)=\"onRefreshGridClick()\"\r\n mat-icon-button routerLink=\"refresh\" routerLinkActive=\"active\" [matTooltip]=\"refreshBtnTooltip()\">\r\n <mat-icon>refresh</mat-icon>\r\n </button>\r\n }\r\n @if (isClearBtnVisible()) {\r\n <button [disabled]=\"clearBtnDisabled()\" (click)=\"onClearClick()\"\r\n mat-icon-button routerLink=\"clear\" routerLinkActive=\"active\" [matTooltip]=\"clearBtnTooltip()\">\r\n <mat-icon>clear</mat-icon>\r\n </button>\r\n }\r\n</mat-toolbar>\r\n","import { z } from 'zod';\r\n\r\n// Базовая схема, описывающая, что у каждого объекта ДОЛЖЕН быть id\r\nexport const BaseSchema = z.object({\r\n id: z.number(),\r\n});\r\n\r\n// TypeScript тип для базового объекта\r\nexport type BaseSchemaClass = z.infer<typeof BaseSchema>;\r\n\r\n/** @deprecated */\r\nexport interface BaseClass {\r\n id: number;\r\n}\r\n","/** Объект передаваемый в диалог формы редактирования, оперирует доменной моделью. */\r\nexport interface IEditDialogData<T, K = any> {\r\n action: Action;\r\n /** Здесь всегда доменная модель */\r\n entity: T;\r\n /** Дополнительные данные, например, фото. */\r\n extraData?: K;\r\n}\r\n\r\nexport enum Action {\r\n Add = 'Добавление',\r\n Edit = 'Изменение'\r\n}\r\n","import { Directive, inject, OnDestroy } from '@angular/core';\r\nimport { FormGroup } from '@angular/forms';\r\nimport { MatDialogRef } from '@angular/material/dialog';\r\nimport { Subscription } from 'rxjs';\r\nimport { NotificationService, RoleService, LoaderService } from '@kuzntsv/uikit';\r\n\r\nimport { Action, IEditDialogData } from './base-edit-dialog-data';\r\n\r\n@Directive()\r\nexport abstract class BaseEditClass<T> implements OnDestroy {\r\n /** Заголовок. */\r\n public abstract title: string;\r\n /** Данные диалога. */\r\n protected abstract dialogData?: IEditDialogData<T>;\r\n /** Форма. */\r\n public abstract form?: FormGroup<any>;\r\n /** Ссылка на диалог. */\r\n protected abstract dialogRef?: MatDialogRef<any, IEditDialogData<T> | null>;\r\n /** Сервис индикатор загрузки. */\r\n protected loaderService = inject(LoaderService);\r\n /** Сервис уведомлений. */\r\n protected notificationService = inject(NotificationService);\r\n /** Сервис ролей. */\r\n protected roleService = inject(RoleService);\r\n\r\n /** Объект для отписки (вызывается метод unsubscribe при уничтожении компонента). */\r\n protected subscription = new Subscription();\r\n\r\n ngOnDestroy(): void {\r\n this.subscription.unsubscribe();\r\n }\r\n\r\n onNoClick(event: MouseEvent): void {\r\n this.dialogRef?.close(null);\r\n event.preventDefault(); // иначе сработает onSubmit\r\n }\r\n\r\n onSubmit(): void {\r\n if (this.form) {\r\n if (this.form.valid) {\r\n if (this.dialogData)\r\n Object.keys(this.form.controls).forEach(\r\n (controlName) =>\r\n (this.dialogData!.entity[controlName as keyof T] =\r\n this.form?.controls[controlName].value),\r\n );\r\n this.dialogRef?.close(this.dialogData);\r\n } else {\r\n Object.keys(this.form.controls).forEach((controlName) =>\r\n this.form?.controls[controlName].markAsTouched(),\r\n );\r\n }\r\n }\r\n }\r\n\r\n formActionIsAdd(): boolean {\r\n return this.dialogData?.action === Action.Add;\r\n }\r\n\r\n formActionIsEdit(): boolean {\r\n return this.dialogData?.action === Action.Edit;\r\n }\r\n\r\n /**\r\n * Определяет видимость элемента на основе ЧЕРНОГО списка ролей.\r\n * По умолчанию элемент ВИДИМ. Скрывается (возвращает false), если у пользователя\r\n * есть запрещенная роль или если передан маркер скрытия фичи HIDE_ROLE_MARKER.\r\n */\r\n protected isVisibleForForbiddenRoles(forbiddenRoles: string[]): boolean {\r\n // Если роль запрещена, метод roleService вернет true.\r\n // Мы инвертируем (!), чтобы видимость (isMenuVisible) стала false.\r\n return !this.roleService.hasForbiddenRole(forbiddenRoles);\r\n }\r\n\r\n /**\r\n * Определяет видимость элемента на основе БЕЛОГО списка ролей.\r\n * По умолчанию элемент СКРЫТ. Показывается (возвращает true), только если у пользователя\r\n * есть хотя бы одна из разрешенных ролей. Администратор (ADMIN) всегда видит элемент.\r\n */\r\n protected isVisibleForAllowedRoles(allowedRoles: string[]): boolean {\r\n // Проверяем, есть ли у пользователя хотя бы одна роль из разрешенного списка.\r\n // (Предполагается, что у вашего roleService есть соответствующий метод, например, hasAnyRole)\r\n return this.roleService.hasAnyRole(allowedRoles);\r\n }\r\n}\r\n","export interface IEntityAction<T> {\r\n action: EntityAction;\r\n entity: T | undefined;\r\n}\r\n\r\nexport enum EntityAction {\r\n Init = 'Инициализация',\r\n Add = 'Добавление',\r\n Edit = 'Изменение',\r\n Delete = 'Удаление'\r\n}\r\n","import { HttpClient } from '@angular/common/http';\r\nimport { inject, Service } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\n\r\n@Service()\r\nexport class AvatarService {\r\n baseRoute = 'common/human/';\r\n\r\n private readonly http = inject(HttpClient);\r\n\r\n getAvatarById(idHuman: number): Observable<ArrayBuffer> {\r\n return this.http.get(this.baseRoute + idHuman + '/avatar', { responseType: 'arraybuffer' });\r\n }\r\n\r\n}\r\n","import { Service } from '@angular/core';\r\n\r\n@Service()\r\nexport class LocalStorageService {\r\n\r\n constructor() { }\r\n\r\n public saveData(key: string, value: string) {\r\n localStorage.setItem(key, value);\r\n }\r\n\r\n public getData(key: string) {\r\n return localStorage.getItem(key)\r\n }\r\n public removeData(key: string) {\r\n localStorage.removeItem(key);\r\n }\r\n\r\n public clearData() {\r\n localStorage.clear();\r\n }\r\n\r\n}\r\n","import { inject, Injectable } from '@angular/core';\r\nimport { HttpClient, HttpContext, HttpHeaders, HttpParams } from '@angular/common/http';\r\nimport { DomSanitizer, SafeUrl } from '@angular/platform-browser';\r\nimport { Observable, of } from 'rxjs';\r\nimport { map, catchError } from 'rxjs/operators';\r\nimport { API_NAME, X_SKIP_LOADER, X_SKIP_NOTIFICATION } from '@kuzntsv/uikit';\r\n\r\n@Injectable({\r\n providedIn: 'root' // Сервис будет доступен глобально во всем приложении\r\n})\r\nexport class SecureImageService {\r\n private readonly http = inject(HttpClient);\r\n private readonly sanitizer = inject(DomSanitizer);\r\n\r\n /**\r\n * Загружает защищенное изображение и возвращает SafeUrl\r\n */\r\n getSecureUrl(relativeUrl: string | null | undefined, apiKey: string = 'default', skipErrorNotification = false, skipLoader = false): Observable<SafeUrl | string> {\r\n if (!relativeUrl) {\r\n return of('');\r\n }\r\n\r\n const context = new HttpContext().set(API_NAME, apiKey);\r\n\r\n let headers = new HttpHeaders();\r\n if (skipErrorNotification)\r\n // переход от индекса к номеру страницы\r\n headers = headers.append(X_SKIP_NOTIFICATION, 'true');\r\n if (skipLoader)\r\n headers = headers.append(X_SKIP_LOADER, 'true');\r\n\r\n return this.http.get(relativeUrl, { headers, responseType: 'blob', context }).pipe(\r\n map((blob) => {\r\n const objectUrl = URL.createObjectURL(blob);\r\n return this.sanitizer.bypassSecurityTrustUrl(objectUrl);\r\n }),\r\n catchError((err) => {\r\n console.error(`[SecureImageService] Ошибка загрузки картинки с API \"${apiKey}\":`, err);\r\n return of(''); \r\n })\r\n );\r\n }\r\n}","import { Service } from '@angular/core';\r\n\r\n@Service()\r\nexport class ExportService {\r\n\r\n // Экспорт в CSV\r\n exportCSV(data: any, filename = 'data', arrHeader: any, newHeaders: any) {\r\n const csvData = this.convertToCSV(data, arrHeader, newHeaders);\r\n console.log(csvData);\r\n const blob = new Blob(['\\ufeff' + csvData], { type: 'text/csv;charset=utf-8;' });\r\n const dwldLink = document.createElement('a');\r\n const url = URL.createObjectURL(blob);\r\n const isSafariBrowser = navigator.userAgent.indexOf('Safari') !== -1 && navigator.userAgent.indexOf('Chrome') === -1;\r\n if (isSafariBrowser) { //if Safari open in new window to save file with random filename.\r\n dwldLink.setAttribute('target', '_blank');\r\n }\r\n dwldLink.setAttribute('href', url);\r\n dwldLink.setAttribute('download', filename + '.csv');\r\n dwldLink.style.visibility = 'hidden';\r\n document.body.appendChild(dwldLink);\r\n dwldLink.click();\r\n document.body.removeChild(dwldLink);\r\n }\r\n\r\n convertToCSV(objArray: any, headerList: any, newHeaders: any) {\r\n const array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;\r\n let str = '';\r\n let row = 'S.No,';\r\n for (const index in newHeaders) {\r\n if (Object.prototype.hasOwnProperty.call(newHeaders, index)) {\r\n row += newHeaders[index] + ',';\r\n }\r\n }\r\n row = row.slice(0, -1);\r\n str += row + '\\r\\n';\r\n for (let i = 0; i < array.length; i++) {\r\n let line = (i + 1) + '';\r\n for (const index in headerList) {\r\n if (Object.prototype.hasOwnProperty.call(newHeaders, index)) {\r\n const head = headerList[index];\r\n line += ',' + array[i][head];\r\n }\r\n }\r\n str += line + '\\r\\n';\r\n }\r\n return str;\r\n }\r\n\r\n}\r\n","import { DestroyRef, inject, Injectable } from \"@angular/core\";\r\nimport { Observable, Subject, takeUntil } from \"rxjs\";\r\n\r\nimport { SseUser } from \"./models/sse-user\";\r\nimport { Topic } from \"./models/topic\";\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class SseService<T> {\r\n private readonly destroyRef = inject(DestroyRef);\r\n private activeEventSource: EventSource | null = null;\r\n // Стрим-триггер для принудительной остановки коннектов извне\r\n private readonly stop$ = new Subject<void>();\r\n\r\n constructor() {\r\n this.destroyRef.onDestroy(() => this.closeSseEventSource());\r\n }\r\n\r\n createSseEventSource(baseUrl: string, user: SseUser, topic: Topic): Observable<T> {\r\n return new Observable<T>((subscriber) => {\r\n let eventSource: EventSource | null = null;\r\n let reconnectTimeoutId: any = null;\r\n let isClosed = false;\r\n\r\n // Слушаем глобальный стоп-сигнал сервиса\r\n const stopSubscription = this.stop$.subscribe(() => {\r\n cleanUp();\r\n subscriber.complete();\r\n });\r\n\r\n const connect = () => {\r\n if (isClosed) return;\r\n\r\n const topicUri = topic.getTopic(baseUrl, user);\r\n eventSource = new EventSource(topicUri);\r\n this.activeEventSource = eventSource;\r\n\r\n eventSource.onmessage = (event: MessageEvent) => {\r\n try {\r\n const messageData: T = JSON.parse(event.data);\r\n subscriber.next(messageData);\r\n } catch (err) {\r\n console.error('Ошибка парсинга SSE данных:', err);\r\n }\r\n };\r\n\r\n eventSource.onopen = () => {\r\n console.log('SSE connection opened.');\r\n };\r\n\r\n eventSource.onerror = (error: Event) => {\r\n console.error('SSE error:', error);\r\n \r\n if (eventSource) {\r\n eventSource.close();\r\n }\r\n\r\n if (!isClosed) {\r\n console.log('Reconnecting to SSE in 1 second...');\r\n reconnectTimeoutId = setTimeout(() => connect(), 1000);\r\n }\r\n };\r\n };\r\n\r\n const cleanUp = () => {\r\n isClosed = true;\r\n if (reconnectTimeoutId) {\r\n clearTimeout(reconnectTimeoutId);\r\n }\r\n if (eventSource) {\r\n eventSource.close();\r\n if (this.activeEventSource === eventSource) {\r\n this.activeEventSource = null;\r\n }\r\n console.log('SSE Connection closed');\r\n }\r\n };\r\n\r\n connect();\r\n\r\n // Срабатывает при отписке (.unsubscribe())\r\n return () => {\r\n stopSubscription.unsubscribe();\r\n cleanUp();\r\n };\r\n });\r\n }\r\n\r\n closeSseEventSource(): void {\r\n this.stop$.next(); // Посылаем сигнал всем активным Observable остановить реконнект\r\n if (this.activeEventSource) {\r\n this.activeEventSource.close();\r\n this.activeEventSource = null;\r\n console.log('SSE Connection force closed');\r\n }\r\n }\r\n}\r\n","import { Directive, inject, OnDestroy } from '@angular/core';\r\nimport { Subscription } from 'rxjs';\r\n\r\nimport { LocalStorageService } from '../../services';\r\nimport { NotificationService, LoaderService } from '@kuzntsv/uikit';\r\n\r\n@Directive()\r\nexport class BaseFilterClass implements OnDestroy {\r\n\r\n /** Сервис для работы с LocalStorage. */\r\n protected localStorageService = inject(LocalStorageService);\r\n /** Сервис индикатор загрузки. */\r\n protected loaderService = inject(LoaderService);\r\n /** Сервис уведомлений. */\r\n protected notificationService = inject(NotificationService);\r\n // eslint-disable-next-line no-magic-numbers\r\n defaultDebounceTime = 500;\r\n /** Объект для отписки (вызывается метод unsubscribe при уничтожении компонента). */\r\n subscription = new Subscription();\r\n\r\n constructor() {\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.subscription.unsubscribe();\r\n }\r\n}","import { Directive, inject } from \"@angular/core\";\r\nimport { MatMenuTrigger } from \"@angular/material/menu\";\r\nimport { Router } from \"@angular/router\";\r\nimport { RoleService } from '@kuzntsv/uikit';\r\n\r\n@Directive()\r\nexport class BaseNavBarMenuClass {\r\n\r\n protected roleService = inject(RoleService);\r\n protected router = inject(Router);\r\n\r\n /** \r\n * Определяет видимость пункта меню на основе ЧЕРНОГО списка ролей.\r\n * По умолчанию пункт меню ВИДИМ. Скрывается (возвращает false), если у пользователя \r\n * есть запрещенная роль или если передан маркер скрытия фичи HIDE_ROLE_MARKER.\r\n */\r\n protected isVisibleForForbiddenRoles(forbiddenRoles: string[]): boolean {\r\n // Если роль запрещена, метод roleService вернет true. \r\n // Мы инвертируем (!), чтобы видимость (isMenuVisible) стала false.\r\n return !this.roleService.hasForbiddenRole(forbiddenRoles);\r\n }\r\n\r\n /** \r\n * Определяет видимость пункта меню на основе БЕЛОГО списка ролей.\r\n * По умолчанию пункт меню СКРЫТ. Показывается (возвращает true), только если у пользователя \r\n * есть хотя бы одна из разрешенных ролей. Администратор (ADMIN) всегда видит элемент.\r\n */\r\n protected isVisibleForAllowedRoles(allowedRoles: string[]): boolean {\r\n // Проверяем, есть ли у пользователя хотя бы одна роль из разрешенного списка.\r\n // (Предполагается, что у вашего roleService есть соответствующий метод, например, hasAnyRole)\r\n return this.roleService.hasAnyRole(allowedRoles);\r\n }\r\n\r\n /** Нажата средняя кнопка (открыть ссылку в новой вкладке). */\r\n onMiddleClick(event: MouseEvent, baseUrl: string, menu: MatMenuTrigger) {\r\n // 1 -\tAuxiliary button pressed (usually the middle button)\r\n if (event.button === 1) {\r\n // event.preventDefault();\r\n menu.closeMenu();\r\n const urlTree = this.router.serializeUrl(\r\n this.router.createUrlTree([baseUrl]\r\n )\r\n );\r\n window.open(urlTree, '_blank');\r\n }\r\n }\r\n}","import { Component, inject } from '@angular/core';\nimport { MatButton } from '@angular/material/button';\nimport {\n MAT_DIALOG_DATA,\n MatDialogActions,\n MatDialogClose,\n MatDialogContent,\n MatDialogRef,\n MatDialogTitle,\n} from '@angular/material/dialog';\n\nimport { DialogData } from './models';\n\n@Component({\n selector: 'ngx-uik-dialog',\n templateUrl: './dialog.component.html',\n styleUrls: ['./dialog.component.css'],\n imports: [\n MatDialogTitle,\n MatDialogContent,\n MatDialogActions,\n MatButton,\n MatDialogClose,\n ],\n})\nexport class DialogComponent {\n readonly data = inject<DialogData>(MAT_DIALOG_DATA, { optional: true });\n readonly dialogRef = inject(MatDialogRef<DialogComponent>);\n\n readonly dialogData: DialogData = {\n id: this.data?.id ?? '',\n title: this.data?.title ?? 'Подтверждение',\n message: this.data?.message ?? '',\n btnNoTitle: this.data?.btnNoTitle ?? 'Нет',\n btnYesTitle: this.data?.btnYesTitle ?? 'Да',\n };\n}\n","<h1 mat-dialog-title>{{ dialogData.title }}</h1>\r\n<mat-dialog-content>\r\n <div style=\"white-space: pre-line\">{{ dialogData.message }}</div>\r\n</mat-dialog-content>\r\n<mat-dialog-actions align=\"end\">\r\n <button mat-raised-button [mat-dialog-close]=\"false\" cdkFocusInitial>{{ dialogData.btnNoTitle }}</button>\r\n <button mat-raised-button color=\"warn\" [mat-dialog-close]=\"dialogData.id\">{{ dialogData.btnYesTitle }}</button>\r\n</mat-dialog-actions>\r\n\r\n","import { Directive, OnDestroy, inject, signal } from '@angular/core';\r\nimport { MatDialog, MatDialogConfig, MatDialogRef } from '@angular/material/dialog';\r\nimport { MatMenuTrigger } from '@angular/material/menu';\r\nimport { Router } from '@angular/router';\r\nimport { Subject, Subscription, forkJoin, map, switchMap, tap } from 'rxjs';\r\n\r\nimport { LocalStorageService } from '../../services/local-storage-service';\r\nimport { DialogComponent } from '../../shared/dialog/dialog.component';\r\nimport { IContextMenuOptions, PageState, SortState, TableState } from '../../shared/table';\r\nimport { ObjectKeys, SortDirection, fnCbType, fnGetCountType, fnGetDataType, fnMapEntityType, fnType } from '../../types/types';\r\nimport { Action, IEditDialogData } from './base-edit-dialog-data';\r\nimport { NotificationService, LoaderService } from '@kuzntsv/uikit';\r\n\r\n@Directive()\r\nexport class BasePageClass<T> implements OnDestroy {\r\n\r\n protected dialog = inject(MatDialog);\r\n\r\n /** Данные для табличного компонента. */\r\n data = signal<T[]>([]);\r\n /** Количество записей по фильтру. */\r\n length = signal<number>(0);\r\n\r\n entityService: any;\r\n entityType: any;\r\n entityEditComponent: any;\r\n extraData?: any;\r\n\r\n // eslint-disable-next-line no-magic-numbers\r\n defaultPageIndex = 0;\r\n // eslint-disable-next-line no-magic-numbers\r\n defaultPageSize = 10;\r\n\r\n dialogEditWidth = 'auto';\r\n dialogRemoveWidth = '400px';\r\n\r\n routeAddress: string = '';\r\n\r\n /** Сообщение при удалении записи(й). */\r\n removalMessage: string = '';\r\n /** Заголовок страницы. */\r\n pageTitle: string = '';\r\n\r\n /**\r\n * Создание записи: вызывается перед открытием диалога.\r\n */\r\n beforeOpenDialogOnNewEvent: fnType<T>;\r\n /**\r\n * Редактирование записи: вызывается перед открытием диалога.\r\n */\r\n beforeOpenDialogOnEditEvent: fnType<T>;\r\n /**\r\n * Создание записи: вызывается перед сохранением объекта.\r\n */\r\n beforeSaveOnNewEvent: fnType<T>;\r\n /**\r\n * Редактирование записи: вызывается перед сохранением объекта.\r\n */\r\n beforeSaveOnEditEvent: fnType<T>;\r\n /**\r\n * Создание записи: вызывается после сохранения объекта.\r\n */\r\n afterSaveOnNewEvent: fnCbType<T>;\r\n /**\r\n * Редактирование записи: вызывается после сохранения объекта.\r\n */\r\n afterSaveOnEditEvent: fnCbType<T>;\r\n\r\n editorRoles: string[] = [];\r\n executeRoles: string[] = [];\r\n /** Список ролей, для которых скрыть элемент. */\r\n hideRoles: string[] = ['HIDE'];\r\n\r\n /** Загрузка данных. */\r\n loadData$: Subject<null> = new Subject<null>();\r\n /** Загрузка количества записей. */\r\n loadLength$: Subject<null> = new Subject<null>();\r\n /** Очистка фильтра. */\r\n clearFilter$: Subject<null> = new Subject<null>();\r\n\r\n /** Очистка фильтра (для очистки присвоить пустой объект '{}'). */\r\n clearFilter: any = null;\r\n\r\n /** Разрешен выбор нескольких строк. */\r\n allowMultiSelect = false;\r\n /** Выбранные строки в таблице. */\r\n selected: T[] = [];\r\n\r\n /** Состояние сортировки, пагинации. */\r\n tableState: TableState;\r\n\r\n /** Доступность кнопки \"Изменить\". */\r\n editBtnDisabled = true;\r\n /** Доступность кнопки \"Удалить\". */\r\n removeBtnDisabled = true;\r\n\r\n /** Разрешено ли отправлять событие rowDoubleClicked при двойном щелчке мышью. */\r\n dblClickedEventEnable = true;\r\n\r\n // Список элементов контекстного меню.\r\n opt: IContextMenuOptions<T>[] = [];\r\n\r\n // DI\r\n protected router = inject(Router);\r\n /** Сервис для работы с LocalStorage. */\r\n protected localStorageService = inject(LocalStorageService);\r\n /** Сервис индикатор загрузки. */\r\n protected loaderService = inject(LoaderService);\r\n /** Сервис уведомлений. */\r\n protected notificationService = inject(NotificationService);\r\n /** Объект для отписки (вызывается метод unsubscribe при уничтожении компонента). */\r\n subscription = new Subscription();\r\n\r\n constructor() {\r\n this.tableState = {\r\n sortActive: this.localStorageService.getData(this.constructor.name + 'SortActive') || '',\r\n sortDirection: (this.localStorageService.getData(this.constructor.name + 'SortDirection') || '') as SortDirection,\r\n pageIndex: Number(this.localStorageService.getData(this.constructor.name + 'PageIndex')) || this.defaultPageIndex,\r\n pageSize: Number(this.localStorageService.getData(this.constructor.name + 'PageSize')) || this.defaultPageSize\r\n };\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.subscription.unsubscribe();\r\n }\r\n\r\n subscribeToLoadData( fnGetData: fnGetDataType<T>, fnGetCount: fnGetCountType<T>, fnMapEntity?: fnMapEntityType<T>) {\r\n // отменять стримы, созданные ранее\r\n const subs = this.loadData$\r\n .pipe(\r\n tap(() => this.loaderService.show()),\r\n switchMap(() => fnGetData()),\r\n map(v => fnMapEntity ? v.map(fnMapEntity()) : v),\r\n )\r\n .subscribe({\r\n next: (response: T[]) => {\r\n this.data.set(response);\r\n this.loaderService.hide();\r\n },\r\n error: (error: any) => {\r\n this.loaderService.hide();\r\n console.log(error);\r\n this.notificationService.error('Произошла ошибка: ' + error, 0);\r\n }\r\n });\r\n this.subscription?.add(subs);\r\n\r\n const subs2 = this.loadLength$\r\n .pipe(\r\n switchMap(() => fnGetCount())\r\n )\r\n .subscribe({\r\n next: (response: number) => {\r\n this.length.set(response);\r\n },\r\n error: (error: any) => {\r\n console.log(error);\r\n this.notificationService.error('Произошла ошибка: ' + error, 0);\r\n }\r\n });\r\n this.subscription?.add(subs2);\r\n\r\n // загрузить данные и количество записей\r\n this.loadData$.next(null);\r\n this.loadLength$.next(null);\r\n }\r\n\r\n onPageChange(pageState: PageState) {\r\n this.tableState.pageIndex = pageState.pageIndex;\r\n this.tableState.pageSize = pageState.pageSize;\r\n this.localStorageService.saveData(this.constructor.name + 'PageIndex', pageState.pageIndex.toString());\r\n this.localStorageService.saveData(this.constructor.name + 'PageSize', pageState.pageSize.toString());\r\n\r\n this.loadData$.next(null);\r\n this.loadLength$.next(null);\r\n }\r\n\r\n onSortChange(sortState: SortState) {\r\n this.tableState.sortActive = sortState.sortActive;\r\n this.tableState.sortDirection = sortState.sortDirection;\r\n this.localStorageService.saveData(this.constructor.name + 'SortActive', sortState.sortActive);\r\n this.localStorageService.saveData(this.constructor.name + 'SortDirection', sortState.sortDirection);\r\n\r\n this.loadData$.next(null);\r\n this.loadLength$.next(null);\r\n }\r\n\r\n /** Событие изменение выбранных записей. */\r\n onSelectionChange(selected: T[]) {\r\n this.selected = selected;\r\n this.editBtnDisabledUpdate(this.selected);\r\n this.removeBtnDisabledUpdate(this.selected);\r\n }\r\n\r\n /** Обновление доступности кнопки \"Изменить\" - вызывается при изменении выбранных записей. */\r\n editBtnDisabledUpdate(selected: T[]) {\r\n this.editBtnDisabled = !(selected && selected.length === 1);\r\n }\r\n\r\n /** Обновление доступности кнопки \"Удалить\" - вызывается при изменении выбранных записей. */\r\n removeBtnDisabledUpdate(selected: T[]) {\r\n this.removeBtnDisabled = !(selected && selected.length > 0);\r\n }\r\n\r\n /** Событие двойной клик. */\r\n onRowDoubleClicked() {\r\n this.editEvent();\r\n }\r\n\r\n /** Событие создание. */\r\n newEvent() {\r\n if (this.entityEditComponent) {\r\n const data: IEditDialogData<T> = { action: Action.Add, entity: new this.entityType(null) };\r\n\r\n // Назначить значения полей объекта перед открытием диалога.\r\n if (this.beforeOpenDialogOnNewEvent) {\r\n this.beforeOpenDialogOnNewEvent(data.entity, data.extraData);\r\n }\r\n\r\n // Открытие окна\r\n const dialogRef = this.openDialog(this.entityEditComponent, data, this.dialog);\r\n\r\n // Обработка закрытия окна\r\n const subs = dialogRef.afterClosed().subscribe((result: IEditDialogData<T>) => {\r\n // Проверка результата\r\n if (result && result.entity && (Object.keys(result.entity).length !== 0)) {\r\n // Дополнительные действия перед сохранением объекта.\r\n if (this.beforeSaveOnNewEvent)\r\n this.beforeSaveOnNewEvent(result.entity, result.extraData);\r\n\r\n const subs = this.entityService.newObject(result.entity)\r\n .subscribe({\r\n next: (obj: any) => {\r\n // Дополнительные действия после сохранения объекта.\r\n if (this.afterSaveOnNewEvent) {\r\n const callback = () => {\r\n this.refreshEvent();\r\n this.notificationService.success('Запись добавлена.');\r\n }\r\n this.afterSaveOnNewEvent(callback.bind(this), obj, result.extraData);\r\n } else {\r\n this.refreshEvent();\r\n this.notificationService.success('Запись добавлена.');\r\n }\r\n },\r\n error: (error: any) => {\r\n console.log('error', error);\r\n this.notificationService.error('Произошла ошибка при добавлении записи: ' + error, 0);\r\n }\r\n });\r\n this.subscription.add(subs);\r\n }\r\n });\r\n this.subscription.add(subs);\r\n\r\n // Закрытие окна по нажатию Escape\r\n const subs2 = dialogRef.keydownEvents().subscribe((event: any) => {\r\n if (event.key === 'Escape') {\r\n dialogRef.close(null);\r\n }\r\n });\r\n this.subscription.add(subs2);\r\n } else {\r\n this.notificationService.warning('Действие не доступно.');\r\n }\r\n }\r\n\r\n /** Событие редактирование. */\r\n editEvent() {\r\n if (this.selected && this.selected.length === 1) {\r\n if (this.entityEditComponent) {\r\n const data: IEditDialogData<T> = { action: Action.Edit, entity: this.selected[0] };\r\n\r\n // Назначить значения полей объекта перед открытием диалога.\r\n if (this.beforeOpenDialogOnEditEvent) {\r\n this.beforeOpenDialogOnEditEvent(data.entity, data.extraData);\r\n }\r\n\r\n // Открытие окна\r\n const dialogRef = this.openDialog(this.entityEditComponent, data, this.dialog);\r\n\r\n // Обработка закрытия окна\r\n const subs = dialogRef.afterClosed().subscribe((result: IEditDialogData<T>) => {\r\n // Проверка результата\r\n if (result && result.entity && (Object.keys(result.entity).length !== 0)) {\r\n // Дополнительные действия перед сохранением объекта.\r\n if (this.beforeSaveOnEditEvent)\r\n this.beforeSaveOnEditEvent(result.entity, result.extraData);\r\n\r\n const subs = this.entityService.editObject(result.entity)\r\n .subscribe({\r\n next: () => {\r\n // Дополнительные действия после сохранения объекта.\r\n if (this.afterSaveOnEditEvent) {\r\n const callback = () => {\r\n this.refreshEvent();\r\n this.notificationService.success('Запись изменена.');\r\n }\r\n this.afterSaveOnEditEvent(callback.bind(this), result.entity, result.extraData);\r\n } else {\r\n this.refreshEvent();\r\n this.notificationService.success('Запись изменена.');\r\n }\r\n },\r\n error: (error: any) => {\r\n console.log('error', error);\r\n this.notificationService.error('Произошла ошибка при изменении записи: ' + error, 0);\r\n }\r\n });\r\n this.subscription.add(subs);\r\n }\r\n });\r\n this.subscription.add(subs);\r\n\r\n // Закрытие окна по нажатию Escape\r\n const subs2 = dialogRef.keydownEvents().subscribe((event: any) => {\r\n if (event.key === 'Escape') {\r\n dialogRef.close(null);\r\n }\r\n });\r\n this.subscription.add(subs2);\r\n } else {\r\n this.notificationService.warning('Действие не доступно.');\r\n }\r\n }\r\n }\r\n\r\n /** Событие удаление. */\r\n removeEvent() {\r\n // если выбрана запись(и)\r\n if (this.selected && this.selected.length > 0) {\r\n const dialogRef = this.openDialogRemoveConfirm(this.removalMessage);\r\n if (dialogRef) {\r\n const subs = dialogRef.afterClosed().subscribe((result: any) => {\r\n // при подтверждении возвращается 'delete'\r\n if (result === 'delete') {\r\n // готовим объект с запросами на удаление\r\n const sourcesObject: ObjectKeys = {};\r\n this.selected.forEach((item, index) => sourcesObject['obj' + index] = this.entityService.deleteObject(item));\r\n // ждем, когда выполнятся все запросы\r\n const subs = forkJoin(sourcesObject)\r\n .subscribe({\r\n next: () => {\r\n this.refreshEvent();\r\n this.notificationService.success('Выбранные записи удалены.');\r\n },\r\n error: (error: any) => {\r\n console.log('error', error);\r\n this.notificationService.error('Произошла ошибка при удалении записи: ' + error, 0);\r\n }\r\n });\r\n this.subscription.add(subs);\r\n }\r\n });\r\n this.subscription.add(subs);\r\n\r\n // Закрытие окна по нажатию Escape\r\n const subs2 = dialogRef.keydownEvents().subscribe((event: any) => {\r\n if (event.key === 'Escape') {\r\n dialogRef.close(null);\r\n }\r\n });\r\n this.subscription.add(subs2);\r\n }\r\n }\r\n }\r\n\r\n /** Событие обновления данных. */\r\n refreshEvent() {\r\n this.loadData$.next(null);\r\n this.loadLength$.next(null);\r\n }\r\n\r\n /** Событие очистки фильтра. */\r\n clearEvent() {\r\n this.clearFilter$.next(null);\r\n this.clearFilter = {};\r\n }\r\n\r\n /** Изменение сообщения об удалении. */\r\n onRemovalMessageChange(message: string) {\r\n this.removalMessage = message;\r\n }\r\n\r\n /** Изменение заголовка страницы. */\r\n onPageTitleChange(title: string) {\r\n this.pageTitle = title;\r\n }\r\n\r\n openDialog(entityComponent: any, data: IEditDialogData<T>, dialog: any) {\r\n // create dialog config\r\n const dialogConfig = new MatDialogConfig();\r\n dialogConfig.disableClose = true;\r\n dialogConfig.autoFocus = true;\r\n dialogConfig.width = this.dialogEditWidth;\r\n dialogConfig.data = data;\r\n dialogConfig.panelClass = this.entityType.name + '-edit-dialog';\r\n // return dialog\r\n return dialog.open(entityComponent, dialogConfig);\r\n }\r\n\r\n openDialogRemoveConfirm(removalMessage: string): MatDialogRef<DialogComponent> | undefined {\r\n let message = 'Вы хотите удалить ';\r\n message += removalMessage ?\r\n removalMessage :\r\n this.allowMultiSelect ? `выбранные записи (${this.selected.length})?` : 'выбранную запись?';\r\n return this.dialog.open(DialogComponent, {\r\n width: this.dialogRemoveWidth,\r\n data: {\r\n id: 'delete',\r\n title: 'Подтверждение',\r\n message: message,\r\n btnNoTitle: 'Отмена',\r\n btnYesTitle: 'Удалить'\r\n }\r\n });\r\n }\r\n\r\n // contextMenu: При щелчке ПКМ открыть в новой вкладке.\r\n protected onMiddleButton(baseUrl: string, queryParamName?: string, queryParamValue?: string) {\r\n return ($event: MouseEvent, item: T | undefined, contextMenu: MatMenuTrigger) => {\r\n // Нажата средняя кнопка (в новой вкладке).\r\n // 1 -\tAuxiliary button pressed (usually the middle button)\r\n if ($event.button === 1 && item) {\r\n //$event.preventDefault();\r\n contextMenu.closeMenu();\r\n // Converts the route into a string that can be used\r\n // with the window.open() function\r\n const url = this.router.serializeUrl(\r\n queryParamName && queryParamValue ?\r\n this.router.createUrlTree([baseUrl], { queryParams: { [queryParamName]: item[queryParamValue as keyof T] } })\r\n : this.router.createUrlTree([baseUrl])\r\n );\r\n window.open(url, '_blank');\r\n }\r\n };\r\n }\r\n\r\n // Action в таблице: При щелчке ПКМ открыть в новой вкладке.\r\n protected onActionMiddleButton(baseUrl: string, queryParamName?: string, queryParamValue?: string) {\r\n return ($event: MouseEvent, item: T | undefined) => {\r\n // Нажата средняя кнопка (в новой вкладке).\r\n // 1 -\tAuxiliary button pressed (usually the middle button)\r\n if ($event.button === 1 && item) {\r\n //$event.preventDefault();\r\n // Converts the route into a string that can be used\r\n // with the window.open() function\r\n const url = this.router.serializeUrl(\r\n queryParamName && queryParamValue ?\r\n this.router.createUrlTree([baseUrl], { queryParams: { [queryParamName]: item[queryParamValue as keyof T] } })\r\n : this.router.createUrlTree([baseUrl])\r\n );\r\n window.open(url, '_blank');\r\n }\r\n };\r\n }\r\n\r\n}\r\n\r\n","import { HttpClient, HttpContext, HttpParams } from '@angular/common/http';\r\nimport { inject, Service } from '@angular/core';\r\nimport { API_NAME } from '@kuzntsv/uikit';\r\nimport { Observable } from 'rxjs';\r\nimport { map } from 'rxjs/operators';\r\n\r\nimport { BaseClass } from './base-class';\r\n\r\n@Service()\r\nexport abstract class BaseServiceClass<T extends BaseClass> {\r\n abstract baseRoute: string;\r\n abstract entityType: any;\r\n\r\n protected countRoute = 'count';\r\n\r\n protected pageIndexParam = 'page';\r\n protected pageSizeParam = 'limit';\r\n protected sortColumnParam = 'column';\r\n protected directionParam = 'direction';\r\n\r\n // По умолчанию используем дефолтное API (пустая строка)\r\n protected apiContextName = ''; \r\n\r\n protected http = inject(HttpClient);\r\n\r\n getObjects(): Observable<T[]> {\r\n return this.http.get<T[]>(this.baseRoute, this.getHttpContext())\r\n .pipe(map(data => data.map(item => new this.entityType(item).deserialize(item))));\r\n }\r\n\r\n getObject(id: number): any {\r\n return this.http.get<T>(this.baseRoute + id, this.getHttpContext())\r\n .pipe(map(data => new this.entityType(data).deserialize(data)));\r\n }\r\n\r\n getCount(): Observable<number> {\r\n return this.http.get<number>(this.baseRoute + this.countRoute, this.getHttpContext());\r\n }\r\n\r\n getObjectsByPaging(pageIndex: number, pageSize: number, sortColumn: string, direction: string): Observable<T[]> {\r\n const params = this.getParams(pageIndex, pageSize, sortColumn, direction);\r\n return this.http.get<T[]>(this.baseRoute, { params, ...this.getHttpContext()})\r\n .pipe(map(data => data.map(item => new this.entityType(item).deserialize(item))));\r\n }\r\n\r\n newObject(entity: T): any {\r\n return this.http.post(this.baseRoute, entity, this.getHttpContext());\r\n }\r\n\r\n editObject(entity: T): any {\r\n return this.http.put(this.baseRoute + entity.id, entity, this.getHttpContext());\r\n }\r\n\r\n deleteObject(entity: T): any {\r\n return this.http.delete(this.baseRoute + entity.id, this.getHttpContext());\r\n }\r\n\r\n protected getParams(pageIndex: number, pageSize: number, sortColumn: string, direction: string): HttpParams {\r\n let params = new HttpParams();\r\n if (pageIndex + 1)\r\n // переход от индекса к номеру страницы\r\n params = params.append(this.pageIndexParam, pageIndex + 1);\r\n if (pageSize)\r\n params = params.append(this.pageSizeParam, pageSize);\r\n if (sortColumn)\r\n params = params.append(this.sortColumnParam, sortColumn);\r\n if (direction)\r\n params = params.append(this.directionParam, direction);\r\n return params;\r\n }\r\n\r\n // Вспомогательный метод для сборки опций HttpClient\r\n protected getHttpContext(): { context?: HttpContext } {\r\n // Если имя не задано (пустая строка, null или undefined), возвращаем пустой объект\r\n if (!this.apiContextName) {\r\n return {};\r\n }\r\n\r\n // Если имя задано, создаем и возвращаем контекст\r\n return {\r\n context: new HttpContext().set(API_NAME, this.apiContextName)\r\n };\r\n }\r\n}\r\n","import {\r\n computed,\r\n Directive,\r\n inject,\r\n linkedSignal,\r\n OnDestroy,\r\n WritableSignal,\r\n} from '@angular/core';\r\nimport { FieldTree } from '@angular/forms/signals';\r\nimport { MatDialogRef } from '@angular/material/dialog';\r\nimport { LoaderService, NotificationService, RoleService } from '@kuzntsv/uikit';\r\nimport { Subscription } from 'rxjs';\r\nimport { ZodObject } from 'zod';\r\n\r\nimport { Action, IEditDialogData } from './base-edit-dialog-data';\r\n\r\n@Directive()\r\nexport abstract class BaseSignalEditClass<\r\n TDomain extends Record<string, any>,\r\n TForm extends Record<string, any> = TDomain, // TForm по умолчанию равен TDomain\r\n> implements OnDestroy {\r\n /** Заголовок. */\r\n public abstract title: string;\r\n /** Данные диалога. */\r\n protected abstract dialogData: WritableSignal<IEditDialogData<TDomain>>;\r\n\r\n protected formAction = computed(() => this.dialogData().action);\r\n protected formActionIsAdd = computed(\r\n () => this.dialogData().action === Action.Add,\r\n );\r\n protected formActionIsEdit = computed(\r\n () => this.dialogData().action === Action.Edit,\r\n );\r\n\r\n /** Наследник может передать чистую DTO схему для очистки (опционально). */\r\n protected domainSchema?: ZodObject<any>;\r\n\r\n protected domainModel = computed(() => this.dialogData().entity);\r\n protected formModel = linkedSignal({\r\n source: this.domainModel,\r\n computation: (domainModel) => this.domainModelToFormModel(domainModel),\r\n });\r\n /** Форма. */\r\n protected abstract form: FieldTree<TForm>;\r\n /** Ссылка на диалог. */\r\n protected abstract dialogRef?: MatDialogRef<\r\n any,\r\n IEditDialogData<TDomain> | null\r\n >;\r\n\r\n /** Сервис индикатор загрузки. */\r\n protected loaderService = inject(LoaderService);\r\n /** Сервис уведомлений. */\r\n protected notificationService = inject(NotificationService);\r\n /** Сервис ролей. */\r\n protected roleService = inject(RoleService);\r\n\r\n /** Объект для отписки (вызывается метод unsubscribe при уничтожении компонента).\r\n * @deprecated\r\n */\r\n protected subscription = new Subscription();\r\n\r\n /**\r\n * Маппинг: Домен -> Форма.\r\n * Реализация по умолчанию делает поверхностную копию. Наследник может её переопределить.\r\n */\r\n protected domainModelToFormModel(domainModel: TDomain): TForm {\r\n return { ...domainModel } as unknown as TForm;\r\n }\r\n\r\n /**\r\n * Маппинг: Форма -> Домен.\r\n * Если передана схема домена (domainSchema), Zod сам удалит лишние поля и вернет чистый DTO\r\n * Реализация по умолчанию объединяет старый домен и новые поля формы.\r\n */\r\n protected formModelToDomainModel(\r\n formModel: TForm,\r\n originalDomain?: TDomain,\r\n ): TDomain {\r\n // 1. Если передана схема домена, Zod сам удалит лишние и вернет чистый DTO\r\n if (this.domainSchema) {\r\n return this.domainSchema.parse(formModel) as TDomain;\r\n }\r\n\r\n // 2. Фолбэк на стандартное поведение, если схемы нет\r\n return {\r\n ...originalDomain,\r\n ...(formModel as unknown as Partial<TDomain>),\r\n } as TDomain;\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.subscription.unsubscribe();\r\n }\r\n\r\n onNoClick(event: MouseEvent): void {\r\n this.dialogRef?.close(null);\r\n event.preventDefault(); // иначе сработает onSubmit\r\n }\r\n\r\n onSubmit(): void {\r\n if (this.form().valid()) {\r\n const updatedDomainEntity = this.formModelToDomainModel(this.formModel());\r\n this.dialogData.update(\r\n (currentData) =>\r\n ({\r\n ...currentData,\r\n entity: updatedDomainEntity,\r\n }) as IEditDialogData<TDomain>,\r\n );\r\n this.dialogRef?.close(this.dialogData());\r\n } else {\r\n this.form().markAsTouched();\r\n }\r\n }\r\n\r\n /**\r\n * Определяет видимость элемента на основе ЧЕРНОГО списка ролей.\r\n * По умолчанию элемент ВИДИМ. Скрывается (возвращает false), если у пользователя\r\n * есть запрещенная роль или если передан маркер скрытия фичи HIDE_ROLE_MARKER.\r\n */\r\n protected isVisibleForForbiddenRoles(forbiddenRoles: string[]): boolean {\r\n // Если роль запрещена, метод roleService вернет true.\r\n // Мы инвертируем (!), чтобы видимость (isMenuVisible) стала false.\r\n return !this.roleService.hasForbiddenRole(forbiddenRoles);\r\n }\r\n\r\n /**\r\n * Определяет видимость элемента на основе БЕЛОГО списка ролей.\r\n * По умолчанию элемент СКРЫТ. Показывается (возвращает true), только если у пользователя\r\n * есть хотя бы одна из разрешенных ролей. Администратор (ADMIN) всегда видит элемент.\r\n */\r\n protected isVisibleForAllowedRoles(allowedRoles: string[]): boolean {\r\n // Проверяем, есть ли у пользователя хотя бы одна роль из разрешенного списка.\r\n // (Предполагается, что у вашего roleService есть соответствующий метод, например, hasAnyRole)\r\n return this.roleService.hasAnyRole(allowedRoles);\r\n }\r\n}\r\n","import {\r\n Directive,\r\n effect,\r\n inject,\r\n input,\r\n model,\r\n signal\r\n} from '@angular/core';\r\nimport { NotificationService, LoaderService } from '@kuzntsv/uikit';\r\n\r\nimport { SafeFilterState } from './base-filter.model';\r\n\r\n@Directive()\r\nexport abstract class BaseSignalFilterClass<F extends SafeFilterState> {\r\n /** Сервис индикатор загрузки. */\r\n protected loaderService = inject(LoaderService);\r\n\r\n /** Сервис уведомлений. */\r\n protected notificationService = inject(NotificationService);\r\n\r\n /** Время на успокоение значения фильтра. */\r\n // eslint-disable-next-line no-magic-numbers\r\n defaultDebounceTime = 500;\r\n\r\n /**\r\n * writable-сигнал, Принимаем текущее реактивное состояние фильтров с родительской страницы.\r\n * Родитель передает значение через [(filters)]=\"pageFilters()\".\r\n * При любом изменении полей ввода обновляйте сигнал целиком через метод update.\r\n *\r\n * @example\r\n * updateCategory(newCategory: string) {\r\n * this.filters.update(prev => ({ ...prev, category: newCategory }));\r\n * }\r\n */\r\n\r\n /** Двусторонняя модель теперь строго типизирована вашим SafeFilterState. */\r\n filters = model<F>({} as F);\r\n\r\n /** Входной сигнал для сброса состояния формы. */\r\n clearFilter = input<any>(null);\r\n\r\n protected isUseInternalFilterSignal = 0;\r\n\r\n /** \r\n * Локальный сигнал формы, чтобы изолировать ввод пользователя \r\n * от родительской двусторонней модели filters. \r\n * \r\n * ### ВАЖНО: \r\n * * При использовании для создания формы и в шаблоне, необходимо задать \r\n * isUseInternalFilterSignal = 1, чтобы при clearFilter чистилась правильная модель.\r\n * \r\n * @example\r\n * protected isUseInternalFilterSignal = 1;\r\n * protected form = form(this.internalFilterSignal, (schemaPath) => {\r\n * // Дебаунсим только текстовые инпут dept. Остальные обновятся мгновенно.\r\n * debounce(schemaPath.dept, this.defaultDebounceTime);\r\n * });\r\n *\r\n * */\r\n // Передаем начальное значение из родительского filters()\r\n protected internalFilterSignal = signal<F>({ ...this.filters() });\r\n\r\n protected abstract DEFAULT_FILTER: F;\r\n\r\n /**\r\n * Объект для отписки от внутренних подписок (например, valueChanges у FormControl).\r\n * Метод unsubscribe вызывается при уничтожении компонента.\r\n */\r\n // В сигнальных формах текущее значение поля — это обычный Signal (а точнее, ModelSignal),\r\n // который синхронизирует состояние UI и вашей модели. Чтобы реагировать на его изменения,\r\n // вместо .valueChanges.subscribe(...) используются стандартные инструменты работы с сигналами:\r\n // 1. computed() — если вам нужно создать производное (зависимое) значение на основе измененных данных формы.\r\n // 2. effect() — если при изменении значения формы нужно выполнить побочный эффект\r\n // (например, отправить запрос на бэкенд или вызвать метод сервиса)\r\n // subscription = new Subscription();\r\n\r\n // ngOnDestroy(): void {\r\n // this.subscription.unsubscribe();\r\n // }\r\n\r\n constructor() {\r\n // 3. Синхронизация: когда ЛОКАЛЬНЫЙ сигнал стабилизировался (учел все дебаунсы),\r\n // мы пушим его в родительскую model. Теперь в [(filters)] данные уходят с задержкой!\r\n effect(() => {\r\n if (this.isUseInternalFilterSignal) {\r\n const stableLocalValue = this.internalFilterSignal();\r\n\r\n // Чтобы избежать зацикливания, обновляем родителя только если данные реально отличаются\r\n if (\r\n JSON.stringify(stableLocalValue) !== JSON.stringify(this.filters())\r\n ) {\r\n this.filters.set(stableLocalValue);\r\n }\r\n }\r\n });\r\n\r\n // очистка фильтра\r\n // 4. Слушаем сброс фильтра от родителя: сбрасываем локальное состояние\r\n effect(() => {\r\n const clearFilter = this.clearFilter();\r\n if (this.isUseInternalFilterSignal)\r\n this.internalFilterSignal.set({ ...this.DEFAULT_FILTER });\r\n else this.filters.set({ ...this.DEFAULT_FILTER });\r\n });\r\n }\r\n\r\n /** Мгновенная очистка конкретного поля по крестику у двусторонней модели filters. */\r\n clearField(fieldName: keyof F, defaultValue: any) {\r\n this.filters.update((prev) => ({\r\n ...prev,\r\n [fieldName]: defaultValue,\r\n }));\r\n }\r\n\r\n /** Мгновенная очистка конкретного поля по крестику. */\r\n clearFieldInternal(fieldName: keyof F, defaultValue: any) {\r\n this.internalFilterSignal.update((prev) => ({\r\n ...prev,\r\n [fieldName]: defaultValue,\r\n }));\r\n }\r\n}\r\n","// Ограничиваем типы значений, которые могут быть в фильтрах\r\n// 1. Исходные типы (то, что может прийти на вход функции)\r\nexport type FilterValue = \r\n | string \r\n | number \r\n | boolean \r\n | readonly string[] \r\n | readonly number[] \r\n | null \r\n | undefined;\r\n\r\nexport type SafeFilterState = Readonly<Record<string, FilterValue>>;\r\n\r\n// 2. Типы результата (строго БЕЗ null и undefined)\r\nexport type CleanFilterValue = Exclude<FilterValue, null | undefined>;\r\n\r\n// Конечный тип для результата работы функции\r\nexport type CleanFilterState = Readonly<Record<string, CleanFilterValue>>;\r\n\r\n// 2. Типы результата (строго БЕЗ null и undefined)\r\nexport function cleanFilterParams(filters: SafeFilterState): CleanFilterState {\r\n // Внутренний объект делаем мутабельным для удобства сборки\r\n const cleanParams: Record<string, CleanFilterValue> = {};\r\n\r\n Object.keys(filters).forEach((key) => {\r\n const value = filters[key];\r\n\r\n // 1. Удаляем null, undefined и пустые строки, пустые массивы\r\n if (isEmptyFilterValue(value)) {\r\n return;\r\n }\r\n\r\n // TS теперь уверен, что здесь value не является null или undefined\r\n cleanParams[key] = value as CleanFilterValue;\r\n });\r\n\r\n // Возвращаем объект, который автоматически приводится к типу CleanFilterState (Readonly)\r\n return cleanParams;\r\n}\r\n\r\n/**\r\n * Проверяет, является ли значение фильтра пустым (мусорным),\r\n * которое нужно удалить из URL/LocalStorage, чтобы не спамить бэкенд.\r\n */\r\nexport function isEmptyFilterValue(value: unknown): boolean {\r\n if (value === null || value === undefined || value === '' || value === '-1' || value === 0) {\r\n return true;\r\n }\r\n \r\n if (Array.isArray(value) && value.length === 0) {\r\n return true;\r\n }\r\n \r\n // Дополнительно можно добавить (при необходимости в будущем):\r\n // if (typeof value === 'string' && value.trim() === '') return true;\r\n\r\n return false;\r\n}\r\n","import { HttpResourceRef } from '@angular/common/http';\r\nimport {\r\n Directive,\r\n OnDestroy,\r\n computed,\r\n effect,\r\n inject,\r\n signal,\r\n} from '@angular/core';\r\nimport {\r\n MatDialog,\r\n MatDialogConfig,\r\n MatDialogRef,\r\n} from '@angular/material/dialog';\r\nimport { MatMenuTrigger } from '@angular/material/menu';\r\nimport { Router } from '@angular/router';\r\nimport {\r\n formatZodError,\r\n HIDE_ROLE_MARKER,\r\n LoaderService,\r\n UIKIT_NOTIFICATION_TOKEN,\r\n} from '@kuzntsv/uikit';\r\nimport { Subscription, forkJoin } from 'rxjs';\r\nimport z from 'zod';\r\n\r\nimport { LocalStorageService } from '../../services/local-storage-service';\r\nimport { DialogComponent } from '../../shared/dialog/dialog.component';\r\nimport {\r\n IContextMenuOptions,\r\n PageState,\r\n SortState,\r\n TableState,\r\n} from '../../shared/table';\r\nimport {\r\n ObjectKeys,\r\n SortDirection,\r\n fnCbType,\r\n fnMapEntityType,\r\n fnType,\r\n} from '../../types/types';\r\nimport { BaseSchemaClass } from './base-class';\r\nimport { Action, IEditDialogData } from './base-edit-dialog-data';\r\nimport { SafeFilterState, isEmptyFilterValue } from './base-filter.model';\r\n\r\n@Directive()\r\nexport abstract class BaseSignalPageClass<\r\n TDomain extends BaseSchemaClass,\r\n TForm extends BaseSchemaClass = TDomain,\r\n TFilter extends SafeFilterState = Record<string, never>,\r\n> implements OnDestroy {\r\n protected dialog = inject(MatDialog);\r\n // Для перехода при открытии новых вкладок (щелчок средней кнопкой мыши).\r\n protected router = inject(Router);\r\n /** Сервис для работы с LocalStorage. */\r\n protected localStorageService = inject(LocalStorageService);\r\n /** Сервис индикатор загрузки. */\r\n protected loaderService = inject(LoaderService);\r\n /** Сервис уведомлений. */\r\n protected notificationService = inject(UIKIT_NOTIFICATION_TOKEN);\r\n\r\n protected entityService: any;\r\n protected entityEditComponent?: any;\r\n protected extraData?: any;\r\n\r\n // Гарантирует, что переданная схема валидирует объект, содержащий как минимум { id: number }\r\n protected abstract readonly schemaDTO: z.ZodType<TDomain>;\r\n\r\n protected readonly filterSchema?: z.ZodType<TFilter>;\r\n protected readonly defaultFilters?: TFilter;\r\n\r\n private get storagePrefix(): string {\r\n return `${this.constructor.name}_Filter_`;\r\n }\r\n\r\n // eslint-disable-next-line no-magic-numbers\r\n defaultPageIndex = 0;\r\n // eslint-disable-next-line no-magic-numbers\r\n defaultPageSize = 10;\r\n\r\n dialogEditWidth = 'auto';\r\n dialogRemoveWidth = '400px';\r\n\r\n /** Сообщение при удалении записи(й). */\r\n removalMessage: string = '';\r\n /** Заголовок страницы. */\r\n pageTitle: string = '';\r\n\r\n /**\r\n * Создание записи: вызывается перед открытием диалога.\r\n */\r\n beforeOpenDialogOnNewEvent: fnType<TDomain>;\r\n /**\r\n * Редактирование записи: вызывается перед открытием диалога.\r\n */\r\n beforeOpenDialogOnEditEvent: fnType<TDomain>;\r\n /**\r\n * Создание записи: вызывается перед сохранением объекта.\r\n */\r\n beforeSaveOnNewEvent: fnType<TDomain>;\r\n /**\r\n * Редактирование записи: вызывается перед сохранением объекта.\r\n */\r\n beforeSaveOnEditEvent: fnType<TDomain>;\r\n /**\r\n * Создание записи: вызывается после сохранения объекта.\r\n */\r\n afterSaveOnNewEvent: fnCbType<TDomain>;\r\n /**\r\n * Редактирование записи: вызывается после сохранения объекта.\r\n */\r\n afterSaveOnEditEvent: fnCbType<TDomain>;\r\n\r\n editorRoles: string[] = [];\r\n executeRoles: string[] = [];\r\n /** Список ролей, для которых скрыть элемент. */\r\n hideRoles: string[] = [HIDE_ROLE_MARKER];\r\n\r\n /** Разрешен выбор нескольких строк. */\r\n allowMultiSelect = false;\r\n /** Разрешено ли отправлять событие rowDoubleClicked при двойном щелчке мышью. */\r\n dblClickedEventEnable = true;\r\n /** Выбранные строки в таблице. */\r\n selected = signal<TForm[]>([]);\r\n\r\n /** Доступность кнопки \"Изменить\". */\r\n protected editBtnDisabled = computed(\r\n () => !(this.selected() && this.selected().length === 1),\r\n );\r\n /** Доступность кнопки \"Удалить\". */\r\n protected removeBtnDisabled = computed(\r\n () => !(this.selected() && this.selected().length > 0),\r\n );\r\n\r\n /** Маппинг TDomain в TForm */\r\n protected fnMapEntity: fnMapEntityType<TForm> | undefined;\r\n\r\n /** Ссылка на ресурс получения данных, определяет потомок. */\r\n protected dataResource!: HttpResourceRef<TForm[]>;\r\n /** Ссылка на ресурс получения количества записей, определяет потомок. */\r\n protected countResource!: HttpResourceRef<number>;\r\n\r\n /** Данные для табличного компонента. */\r\n data = computed<TForm[]>(() => {\r\n // Защита на момент старта super()\r\n if (!this.dataResource) return [];\r\n\r\n // ЗАЩИТА: Если ресурс упал (например, 401 или 500),\r\n // возвращаем пустой массив, НЕ вызывая .value(), чтобы не спамить в консоль\r\n if (this.dataResource.error()) {\r\n return [];\r\n }\r\n\r\n const rawData = this.dataResource?.value() || [];\r\n return this.fnMapEntity && Array.isArray(rawData)\r\n ? rawData.map(this.fnMapEntity())\r\n : rawData;\r\n });\r\n\r\n /** Количество записей по фильтру. */\r\n length = computed<number>(() => {\r\n // Защита на момент старта super()\r\n if (!this.countResource) return 0;\r\n\r\n // Защита от спама при ошибке подсчета количества\r\n if (this.countResource.error()) {\r\n return 0;\r\n }\r\n\r\n return this.countResource?.value() || 0;\r\n });\r\n\r\n /** Глобальный индикатор загрузки (для спиннера на странице) */\r\n isLoading = computed<boolean>(() => {\r\n if (!this.dataResource || !this.countResource) return false;\r\n\r\n // Если ресурсы уже в состоянии ошибки, значит загрузка завершена\r\n if (this.dataResource.error() || this.countResource.error()) {\r\n return false;\r\n }\r\n\r\n return this.dataResource.isLoading() || this.countResource.isLoading();\r\n });\r\n\r\n /** Список элементов контекстного меню. */\r\n opt: IContextMenuOptions<TForm>[] = [];\r\n\r\n /** Объект для отписки (вызывается метод unsubscribe при уничтожении компонента). */\r\n subscription = new Subscription();\r\n\r\n /** Единое реактивное хранилище для ВСЕХ фильтров текущей страницы. */\r\n filters = signal<TFilter>({} as TFilter);\r\n\r\n /** Очистка фильтра. (для очистки присвоить пустой объект '{}'). */\r\n clearFilters = signal<any>(null);\r\n\r\n /** Состояние сортировки, пагинации. */\r\n tableState = signal<TableState>({\r\n sortActive: '',\r\n sortDirection: '' as SortDirection,\r\n pageIndex: this.defaultPageIndex,\r\n pageSize: this.defaultPageSize,\r\n });\r\n\r\n constructor() {\r\n this.tableState.set({\r\n sortActive:\r\n this.localStorageService.getData(\r\n this.constructor.name + 'SortActive',\r\n ) || '',\r\n sortDirection: (this.localStorageService.getData(\r\n this.constructor.name + 'SortDirection',\r\n ) || '') as SortDirection,\r\n pageIndex:\r\n Number(\r\n this.localStorageService.getData(this.constructor.name + 'PageIndex'),\r\n ) || this.defaultPageIndex,\r\n pageSize:\r\n Number(\r\n this.localStorageService.getData(this.constructor.name + 'PageSize'),\r\n ) || this.defaultPageSize,\r\n });\r\n\r\n // 3. Эффект для отслеживания изменений фильтров (бывший trackFilterChanges)\r\n let previousFilters = { ...this.filters() };\r\n\r\n effect(() => {\r\n console.log(\"previousFilters=\", previousFilters);\r\n const currentFilters = this.filters();\r\n console.log(\"currentFilters=\", currentFilters);\r\n \r\n let filterChanged = false;\r\n\r\n (Object.keys(currentFilters) as Array<keyof TFilter>).forEach((key) => {\r\n const prevVal = previousFilters[key];\r\n const currVal = currentFilters[key];\r\n\r\n console.log(\r\n 'loop by key=',key,\r\n 'prevVal=',\r\n prevVal,\r\n 'currVal=',\r\n currVal,\r\n );\r\n if (prevVal !== currVal) {\r\n filterChanged = true;\r\n const storageKey = `${this.storagePrefix}${String(key)}`;\r\n\r\n // Интегрируем логику вашей функции очистки для LocalStorage!\r\n // Если значение превратилось в то, что cleanFilterParams считает мусором,\r\n // удаляем ключ из localStorage, чтобы не копить пустые значения.\r\n const isValueEmpty = isEmptyFilterValue(currVal);\r\n if (isValueEmpty) {\r\n this.localStorageService.removeData(storageKey);\r\n console.log(\r\n 'removeData',\r\n storageKey,\r\n 'prevVal=',\r\n prevVal,\r\n 'currVal=',\r\n currVal,\r\n );\r\n } else {\r\n this.localStorageService.saveData(\r\n storageKey,\r\n JSON.stringify(currVal),\r\n );\r\n }\r\n }\r\n });\r\n\r\n if (filterChanged) {\r\n // Сброс пагинации:\r\n this.tableState.update((prev) => ({ ...prev, pageIndex: 0 }));\r\n }\r\n previousFilters = { ...currentFilters };\r\n });\r\n\r\n // Перехватываем ошибку Zod из safeParseData прямо в эффекте\r\n effect(() => {\r\n const dataError = this.dataResource?.error();\r\n\r\n if (dataError) {\r\n // Так как safeParseData выбрасывает инстанс Error,\r\n // достаем из него понятный текстовый лог через .message\r\n const errorMessage =\r\n dataError instanceof Error ? dataError.message : String(dataError);\r\n\r\n console.log(\r\n `[Валидация данных] Ошибка структуры JSON от сервера:\\n${errorMessage}`,\r\n );\r\n\r\n this.notificationService.error(\r\n 'Произошла ошибка при чтении/парсинге данных с сервера.',\r\n 0,\r\n );\r\n }\r\n });\r\n\r\n // Отдельный эффект для счетчика пагинации\r\n effect(() => {\r\n const countError = this.countResource?.error();\r\n if (countError) {\r\n const errorMessage =\r\n countError instanceof Error ? countError.message : String(countError);\r\n\r\n console.log(`[Валидация пагинации] ${errorMessage}`);\r\n\r\n this.notificationService.error(\r\n 'Произошла ошибка при чтении/парсинге данных с сервера.',\r\n 0,\r\n );\r\n }\r\n });\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.subscription.unsubscribe();\r\n }\r\n\r\n /** Разово прочитать сохраненные значения из localStorage при старте страницы,\r\n * провалидировать их через Zod-схему и записать в сигнал filters */\r\n protected initFilters(): void {\r\n if (!this.filterSchema || !this.defaultFilters) return;\r\n\r\n const initial: Record<string, any> = { ...this.defaultFilters };\r\n\r\n Object.keys(this.defaultFilters).forEach((key) => {\r\n const storageKey = `${this.storagePrefix}${key}`;\r\n const rawValue = this.localStorageService.getData(storageKey);\r\n console.log(\r\n 'initFilters, storageKey=',\r\n storageKey,\r\n 'rawValue=',\r\n rawValue,\r\n );\r\n\r\n if (rawValue !== null && rawValue !== undefined) {\r\n try {\r\n initial[key] = JSON.parse(rawValue);\r\n } catch {\r\n initial[key] = rawValue;\r\n }\r\n }\r\n });\r\n\r\n // Валидируем собранный объект через Zod-схему\r\n const validation = this.filterSchema.safeParse(initial);\r\n console.log(\r\n 'initFilters, validation=',\r\n validation,\r\n 'validation.success=',\r\n validation.success,\r\n 'validation.data=',\r\n validation.data,\r\n 'validation.error=',\r\n validation.error ? formatZodError(validation.error ,this.constructor.name) : \r\n 'empty',\r\n );\r\n // Записываем финальные данные в сигнал.\r\n // Как только этот сигнал заполнится, автоматически среагирует и effect() в конструкторе,\r\n // и ресурс dataResource для загрузки данных.\r\n this.filters.set(\r\n validation.success ? validation.data : this.defaultFilters,\r\n );\r\n }\r\n\r\n /** Событие очистки фильтра. */\r\n protected clearEvent() {\r\n if (!this.defaultFilters) return;\r\n\r\n Object.keys(this.defaultFilters).forEach((key) => {\r\n this.localStorageService.removeData(`${this.storagePrefix}${key}`);\r\n });\r\n this.tableState.update((prev) => ({ ...prev, pageIndex: 0 }));\r\n this.filters.set({ ...this.defaultFilters });\r\n this.clearFilters.set({});\r\n }\r\n\r\n /** Установка значение фильтра.\r\n * @param key - имя фильтра.\r\n * @param value - значение.\r\n */\r\n protected setFilter<K extends keyof TFilter>(key: K, value: TFilter[K]) {\r\n const storageKey = `${this.storagePrefix}${String(key)}`;\r\n\r\n // При любом изменении фильтра сбрасываем пагинацию на первую страницу\r\n this.tableState.update((prev) => ({ ...prev, pageIndex: 0 }));\r\n\r\n const isValueEmpty = isEmptyFilterValue(value);\r\n\r\n // Сайд-эффекты для LocalStorage\r\n if (isValueEmpty) {\r\n this.localStorageService.removeData(storageKey);\r\n } else {\r\n this.localStorageService.saveData(storageKey, JSON.stringify(value));\r\n }\r\n\r\n // Обновление сигнала\r\n this.filters.update((prev) => {\r\n if (isValueEmpty) {\r\n const next = { ...prev };\r\n delete next[key];\r\n return next;\r\n }\r\n return { ...prev, [key]: value };\r\n });\r\n }\r\n\r\n /**\r\n * Обновление нескольких фильтров одновременно (пачкой)\r\n * @param fields Пачка фильтров в виде объекта { имяПоля: значение }\r\n */\r\n protected setFilters(fields: Partial<TFilter>) {\r\n // 1. При изменении пачки фильтров сбрасываем пагинацию на первую страницу ОДИН раз\r\n this.tableState.update((prev) => ({ ...prev, pageIndex: 0 }));\r\n\r\n // 2. Обновляем сигнал фильтров атомарно\r\n this.filters.update((prev) => {\r\n // Создаем копию текущего состояния фильтров\r\n const next = { ...prev };\r\n\r\n // Проходим по каждому переданному ключу в пачке\r\n (Object.keys(fields) as Array<keyof TFilter>).forEach((key) => {\r\n const value = fields[key];\r\n const storageKey = `${this.constructor.name}_Filter_${String(key)}`;\r\n\r\n // Проверяем значение на \"пустоту\"\r\n const isValueEmpty = isEmptyFilterValue(value);\r\n\r\n if (isValueEmpty) {\r\n // Сайд-эффект для LocalStorage: удаляем\r\n this.localStorageService.removeData(storageKey);\r\n // Удаляем ключ из нового состояния фильтров\r\n delete next[key];\r\n } else {\r\n // Сайд-эффект для LocalStorage: сохраняем\r\n this.localStorageService.saveData(storageKey, JSON.stringify(value));\r\n // Записываем значение в новое состояние фильтров\r\n next[key] = value as any;\r\n }\r\n });\r\n\r\n // Возвращаем новый объект. Изменение ссылки триггерит ОДИН HTTP-запрос в httpResource\r\n return next;\r\n });\r\n }\r\n\r\n onPageChange(pageState: PageState) {\r\n this.localStorageService.saveData(\r\n this.constructor.name + 'PageIndex',\r\n pageState.pageIndex.toString(),\r\n );\r\n this.localStorageService.saveData(\r\n this.constructor.name + 'PageSize',\r\n pageState.pageSize.toString(),\r\n );\r\n\r\n this.tableState.update((prev) => ({\r\n ...prev,\r\n pageIndex: pageState.pageIndex,\r\n pageSize: pageState.pageSize,\r\n }));\r\n }\r\n\r\n onSortChange(sortState: SortState) {\r\n this.localStorageService.saveData(\r\n this.constructor.name + 'SortActive',\r\n sortState.sortActive,\r\n );\r\n this.localStorageService.saveData(\r\n this.constructor.name + 'SortDirection',\r\n sortState.sortDirection,\r\n );\r\n\r\n this.tableState.update((prev) => ({\r\n ...prev,\r\n sortActive: sortState.sortActive,\r\n sortDirection: sortState.sortDirection,\r\n }));\r\n }\r\n\r\n /** Событие изменение выбранных записей. */\r\n onSelectionChange(selected: TForm[]) {\r\n this.selected.set(selected);\r\n }\r\n\r\n /** Событие двойной клик. */\r\n onRowDoubleClicked() {\r\n if (this.dblClickedEventEnable) this.editEvent();\r\n }\r\n\r\n /** Событие создание. */\r\n newEvent() {\r\n if (this.entityEditComponent) {\r\n // Zod создаст дефолтный объект, пропустив пустой объект {} через парсер\r\n const defaultEntity = this.schemaDTO.parse({});\r\n\r\n const data: IEditDialogData<TDomain> = {\r\n action: Action.Add,\r\n entity: defaultEntity,\r\n };\r\n\r\n // Назначить значения полей объекта перед открытием диалога.\r\n if (this.beforeOpenDialogOnNewEvent) {\r\n this.beforeOpenDialogOnNewEvent(data.entity, data.extraData);\r\n }\r\n\r\n // Открытие окна\r\n const dialogRef = this.openDialog(\r\n this.entityEditComponent,\r\n data,\r\n this.dialog,\r\n );\r\n\r\n // Обработка закрытия окна\r\n const subs = dialogRef\r\n .afterClosed()\r\n .subscribe((result: IEditDialogData<TDomain>) => {\r\n // Проверка результата\r\n if (\r\n result &&\r\n result.entity &&\r\n Object.keys(result.entity).length !== 0\r\n ) {\r\n // Дополнительные действия перед сохранением объекта.\r\n if (this.beforeSaveOnNewEvent)\r\n this.beforeSaveOnNewEvent(result.entity, result.extraData);\r\n\r\n const subs = this.entityService.newObject(result.entity).subscribe({\r\n next: (obj: any) => {\r\n // Дополнительные действия после сохранения объекта.\r\n if (this.afterSaveOnNewEvent) {\r\n const callback = () => {\r\n this.refreshEvent();\r\n this.notificationService.success('Запись добавлена.');\r\n };\r\n this.afterSaveOnNewEvent(\r\n callback.bind(this),\r\n obj,\r\n result.extraData,\r\n );\r\n } else {\r\n this.refreshEvent();\r\n this.notificationService?.success('Запись добавлена.');\r\n }\r\n },\r\n error: (error: any) => {\r\n console.log('error', error);\r\n this.notificationService.error(\r\n 'Произошла ошибка при добавлении записи: ' + error,\r\n 0,\r\n );\r\n },\r\n });\r\n this.subscription.add(subs);\r\n }\r\n });\r\n this.subscription.add(subs);\r\n\r\n // Закрытие окна по нажатию Escape\r\n const subs2 = dialogRef.keydownEvents().subscribe((event: any) => {\r\n if (event.key === 'Escape') {\r\n dialogRef.close(null);\r\n }\r\n });\r\n this.subscription.add(subs2);\r\n } else {\r\n this.notificationService.warning('Действие не доступно.');\r\n }\r\n }\r\n\r\n /** Событие редактирование. */\r\n editEvent() {\r\n if (this.selected() && this.selected().length === 1) {\r\n if (this.entityEditComponent) {\r\n const data: IEditDialogData<TDomain> = {\r\n action: Action.Edit,\r\n entity: this.formModelToDomainModel(this.selected()[0]),\r\n };\r\n\r\n // Назначить значения полей объекта перед открытием диалога.\r\n if (this.beforeOpenDialogOnEditEvent) {\r\n this.beforeOpenDialogOnEditEvent(data.entity, data.extraData);\r\n }\r\n\r\n // Открытие окна\r\n const dialogRef = this.openDialog(\r\n this.entityEditComponent,\r\n data,\r\n this.dialog,\r\n );\r\n\r\n // Обработка закрытия окна\r\n const subs = dialogRef\r\n .afterClosed()\r\n .subscribe((result: IEditDialogData<TDomain>) => {\r\n // Проверка результата\r\n if (\r\n result &&\r\n result.entity &&\r\n Object.keys(result.entity).length !== 0\r\n ) {\r\n // Дополнительные действия перед сохранением объекта.\r\n if (this.beforeSaveOnEditEvent)\r\n this.beforeSaveOnEditEvent(result.entity, result.extraData);\r\n\r\n const subs = this.entityService\r\n .editObject(result.entity)\r\n .subscribe({\r\n next: () => {\r\n // Дополнительные действия после сохранения объекта.\r\n if (this.afterSaveOnEditEvent) {\r\n const callback = () => {\r\n this.refreshEvent();\r\n this.notificationService.success('Запись изменена.');\r\n };\r\n this.afterSaveOnEditEvent(\r\n callback.bind(this),\r\n result.entity,\r\n result.extraData,\r\n );\r\n } else {\r\n this.refreshEvent();\r\n this.notificationService.success('Запись изменена.');\r\n }\r\n },\r\n error: (error: any) => {\r\n console.log('error', error);\r\n this.notificationService.error(\r\n 'Произошла ошибка при изменении записи: ' + error,\r\n 0,\r\n );\r\n },\r\n });\r\n this.subscription.add(subs);\r\n }\r\n });\r\n this.subscription.add(subs);\r\n\r\n // Закрытие окна по нажатию Escape\r\n const subs2 = dialogRef.keydownEvents().subscribe((event: any) => {\r\n if (event.key === 'Escape') {\r\n dialogRef.close(null);\r\n }\r\n });\r\n this.subscription.add(subs2);\r\n } else {\r\n this.notificationService.warning('Действие не доступно.');\r\n }\r\n }\r\n }\r\n\r\n /** Событие удаление. */\r\n removeEvent() {\r\n // если выбрана запись(и)\r\n if (this.selected() && this.selected().length > 0) {\r\n const dialogRef = this.openDialogRemoveConfirm(this.removalMessage);\r\n if (dialogRef) {\r\n const subs = dialogRef.afterClosed().subscribe((result: any) => {\r\n // при подтверждении возвращается 'delete'\r\n if (result === 'delete') {\r\n // готовим объект с запросами на удаление\r\n const sourcesObject: ObjectKeys = {};\r\n this.selected().forEach(\r\n (item, index) =>\r\n (sourcesObject['obj' + index] =\r\n this.entityService.deleteObject(item)),\r\n );\r\n // ждем, когда выполнятся все запросы\r\n const subs = forkJoin(sourcesObject).subscribe({\r\n next: () => {\r\n this.refreshEvent();\r\n this.notificationService.success('Выбранные записи удалены.');\r\n },\r\n error: (error: any) => {\r\n console.log('error', error);\r\n this.notificationService?.error(\r\n 'Произошла ошибка при удалении записи: ' + error,\r\n 0,\r\n );\r\n },\r\n });\r\n this.subscription.add(subs);\r\n }\r\n });\r\n this.subscription.add(subs);\r\n\r\n // Закрытие окна по нажатию Escape\r\n const subs2 = dialogRef.keydownEvents().subscribe((event: any) => {\r\n if (event.key === 'Escape') {\r\n dialogRef.close(null);\r\n }\r\n });\r\n this.subscription.add(subs2);\r\n }\r\n }\r\n }\r\n\r\n /** Событие обновления данных. */\r\n refreshEvent() {\r\n this.dataResource?.reload();\r\n this.countResource?.reload();\r\n }\r\n\r\n /** Изменение сообщения об удалении. */\r\n onRemovalMessageChange(message: string) {\r\n this.removalMessage = message;\r\n }\r\n\r\n /** Изменение заголовка страницы. */\r\n onPageTitleChange(title: string) {\r\n this.pageTitle = title;\r\n }\r\n\r\n openDialog(\r\n entityComponent: any,\r\n data: IEditDialogData<TDomain>,\r\n dialog: any,\r\n ) {\r\n // create dialog config\r\n const dialogConfig = new MatDialogConfig();\r\n dialogConfig.disableClose = true;\r\n dialogConfig.autoFocus = true;\r\n dialogConfig.width = this.dialogEditWidth;\r\n dialogConfig.data = data;\r\n dialogConfig.panelClass = this.constructor.name + '-edit-dialog';\r\n // return dialog\r\n return dialog.open(entityComponent, dialogConfig);\r\n }\r\n\r\n openDialogRemoveConfirm(\r\n removalMessage: string,\r\n ): MatDialogRef<DialogComponent> | undefined {\r\n let message = 'Вы хотите удалить ';\r\n message += removalMessage\r\n ? removalMessage\r\n : this.allowMultiSelect\r\n ? `выбранные записи (${this.selected().length})?`\r\n : 'выбранную запись?';\r\n return this.dialog.open(DialogComponent, {\r\n width: this.dialogRemoveWidth,\r\n data: {\r\n id: 'delete',\r\n title: 'Подтверждение',\r\n message: message,\r\n btnNoTitle: 'Отмена',\r\n btnYesTitle: 'Удалить',\r\n },\r\n });\r\n }\r\n\r\n // contextMenu: При щелчке ПКМ открыть в новой вкладке.\r\n protected onMiddleButton(\r\n baseUrl: string,\r\n queryParamName?: string,\r\n queryParamValue?: string,\r\n ) {\r\n return (\r\n $event: MouseEvent,\r\n item: TForm | undefined,\r\n contextMenu: MatMenuTrigger,\r\n ) => {\r\n // Нажата средняя кнопка (в новой вкладке).\r\n // 1 -\tAuxiliary button pressed (usually the middle button)\r\n if ($event.button === 1 && item) {\r\n //$event.preventDefault();\r\n contextMenu.closeMenu();\r\n // Converts the route into a string that can be used\r\n // with the window.open() function\r\n const url = this.router.serializeUrl(\r\n queryParamName && queryParamValue\r\n ? this.router.createUrlTree([baseUrl], {\r\n queryParams: {\r\n [queryParamName]: item[queryParamValue as keyof TForm],\r\n },\r\n })\r\n : this.router.createUrlTree([baseUrl]),\r\n );\r\n window.open(url, '_blank');\r\n }\r\n };\r\n }\r\n\r\n // Action в таблице: При щелчке ПКМ открыть в новой вкладке.\r\n protected onActionMiddleButton(\r\n baseUrl: string,\r\n queryParamName?: string,\r\n queryParamValue?: string,\r\n ) {\r\n return ($event: MouseEvent, item: TForm | undefined) => {\r\n // Нажата средняя кнопка (в новой вкладке).\r\n // 1 -\tAuxiliary button pressed (usually the middle button)\r\n if ($event.button === 1 && item) {\r\n //$event.preventDefault();\r\n // Converts the route into a string that can be used\r\n // with the window.open() function\r\n const url = this.router.serializeUrl(\r\n queryParamName && queryParamValue\r\n ? this.router.createUrlTree([baseUrl], {\r\n queryParams: {\r\n [queryParamName]: item[queryParamValue as keyof TForm],\r\n },\r\n })\r\n : this.router.createUrlTree([baseUrl]),\r\n );\r\n window.open(url, '_blank');\r\n }\r\n };\r\n }\r\n\r\n /**\r\n * Маппинг: Форма -> Домен.\r\n * Реализация по умолчанию объединяет старый домен и новые поля формы.\r\n */\r\n protected formModelToDomainModel(\r\n formModel: TForm,\r\n originalDomain?: TDomain,\r\n ): TDomain {\r\n return {\r\n ...originalDomain,\r\n ...(formModel as unknown as Partial<TDomain>),\r\n } as TDomain;\r\n }\r\n}\r\n","import {\r\n HttpClient,\r\n HttpContext,\r\n HttpParams,\r\n httpResource,\r\n HttpResourceRef,\r\n} from '@angular/common/http';\r\nimport { inject, Injectable, signal } from '@angular/core';\r\nimport { API_NAME, formatZodError } from '@kuzntsv/uikit';\r\nimport { tap } from 'rxjs';\r\nimport z from 'zod';\r\n\r\nimport { TableState } from '../../shared';\r\nimport { BaseSchemaClass } from './base-class';\r\nimport { cleanFilterParams, SafeFilterState } from './base-filter.model';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport abstract class BaseSignalServiceClass<T extends BaseSchemaClass> {\r\n abstract baseRoute: string;\r\n\r\n // Гарантирует, что переданная схема валидирует объект, содержащий как минимум { id: number }\r\n protected abstract readonly schema: z.ZodType<T>;\r\n\r\n // Схема для валидации и очистки при ЗАПИСИ\r\n protected schemaDTO?: z.ZodType<any>;\r\n\r\n protected countRoute = 'count';\r\n\r\n protected pageIndexParam = 'page';\r\n protected pageSizeParam = 'limit';\r\n protected sortColumnParam = 'column';\r\n protected directionParam = 'direction';\r\n\r\n // По умолчанию используем дефолтное API (пустая строка)\r\n protected apiContextName = '';\r\n\r\n protected http = inject(HttpClient);\r\n\r\n // Реактивный триггер для перезапуска списков\r\n protected readonly _refreshTrigger = signal(0);\r\n\r\n // Вспомогательный метод для ручного или автоматического пинка триггера\r\n public refresh(): void {\r\n this._refreshTrigger.update((v) => v + 1);\r\n }\r\n\r\n // 1. Возвращает ResourceRef, который сразу можно использовать в шаблонах или других ресурсах\r\n getObjects(): HttpResourceRef<T[]> {\r\n return httpResource<T[]>(\r\n () => {\r\n // Читаем триггер обновления, чтобы ресурс перезапустился автоматически\r\n this._refreshTrigger();\r\n return { url: this.baseRoute };\r\n },\r\n {\r\n ...this.getHttpContext(),\r\n defaultValue: [],\r\n // Ключевое улучшение v22: трансформация данных прямо на уровне ресурса\r\n parse: (data: unknown) => {\r\n if (!data) return [];\r\n // Валидация через Zod вернет строго тип T, у которого точно есть id\r\n // Было: return z.array(this.schema).parse(data);\r\n return this.safeParseData(z.array(this.schema), data, true); // Стало\r\n },\r\n },\r\n );\r\n }\r\n\r\n getObject(\r\n id: number | (() => number | null | undefined),\r\n ): HttpResourceRef<T | null> {\r\n // Приводим id к функции-сигналу для обеспечения реактивности httpResource\r\n const idSignal = typeof id === 'function' ? id : () => id;\r\n\r\n return httpResource<T | null>(\r\n () => {\r\n // Читаем триггер обновления, чтобы ресурс перезапустился автоматически\r\n this._refreshTrigger();\r\n\r\n const currentId = idSignal();\r\n // Защита: если ID еще нет, не делаем запрос и переводим ресурс в состояние Idle\r\n if (currentId === null || currentId === undefined) {\r\n return undefined;\r\n }\r\n\r\n return { url: `${this.baseRoute}${currentId}` };\r\n },\r\n {\r\n ...this.getHttpContext(),\r\n defaultValue: null,\r\n parse: (data: unknown) => {\r\n if (!data) return null;\r\n // Было: return this.schema.parse(data);\r\n return this.safeParseData(this.schema, data); // Стало\r\n },\r\n },\r\n );\r\n }\r\n\r\n getCount(): HttpResourceRef<number> {\r\n return httpResource<number>(\r\n () => {\r\n // Читаем триггер обновления, чтобы ресурс перезапустился автоматически\r\n this._refreshTrigger();\r\n return {\r\n url: `${this.baseRoute}${this.countRoute}`,\r\n };\r\n },\r\n {\r\n ...this.getHttpContext(),\r\n defaultValue: 0,\r\n parse: (data: unknown) => z.coerce.number().parse(data),\r\n },\r\n );\r\n }\r\n\r\n getObjectsByPaging(tableStateGetter: () => TableState): HttpResourceRef<T[]> {\r\n return httpResource<T[]>(\r\n () => {\r\n // Читаем триггер, чтобы httpResource реагировал на вызов .refresh()\r\n this._refreshTrigger();\r\n\r\n const tableState = tableStateGetter(); \r\n\r\n return {\r\n url: this.baseRoute,\r\n params: this.buildTableParams(tableState),\r\n };\r\n },\r\n {\r\n ...this.getHttpContext(),\r\n defaultValue: [],\r\n parse: (data) => {\r\n if (!data) return [];\r\n // Валидация через Zod вернет строго тип T, у которого точно есть id\r\n return this.safeParseData(z.array(this.schema), data, true); // Стало\r\n },\r\n },\r\n );\r\n }\r\n\r\n /**\r\n * Универсальный метод получения пагинированных данных с фильтрацией.\r\n * Автоматически очищает фильтры от null/undefined/пустых значений с помощью cleanFilterParams.\r\n */\r\n getObjectsByFilterPaging<F extends SafeFilterState>(\r\n tableStateGetter: () => TableState,\r\n filtersGetter: () => F\r\n ): HttpResourceRef<T[]> {\r\n return httpResource<T[]>(\r\n () => {\r\n this._refreshTrigger();\r\n\r\n const tableState = tableStateGetter(); // Читаем сигнал состояния таблицы стороннего компонента\r\n const filters = filtersGetter(); // Читаем сигнал фильтров стороннего компонента\r\n\r\n // 1. Очищаем переданные фильтры вашей функцией\r\n const cleanFields = cleanFilterParams(filters);\r\n // 2. Формируем базовые параметры пагинации\r\n const tableParams = this.buildTableParams(tableState);\r\n\r\n return {\r\n url: this.baseRoute,\r\n params: { ...cleanFields, ...tableParams },\r\n };\r\n },\r\n {\r\n ...this.getHttpContext(),\r\n defaultValue: [],\r\n parse: (data) => {\r\n if (!data) return [];\r\n return this.safeParseData(z.array(this.schema), data, true); // Стало\r\n },\r\n },\r\n );\r\n }\r\n\r\n /**\r\n * Универсальный метод получения КОЛИЧЕСТВА записей с фильтрацией.\r\n * Автоматически очищает фильтры перед отправкой.\r\n */\r\n getObjectsCountByFilter<F extends SafeFilterState>(\r\n filtersGetter: () => F\r\n ): HttpResourceRef<number> {\r\n return httpResource<number>(\r\n () => {\r\n this._refreshTrigger();\r\n\r\n const filters = filtersGetter();\r\n\r\n // Очищаем объект от пустых полей\r\n const cleanFields = cleanFilterParams(filters);\r\n\r\n return {\r\n url: `${this.baseRoute}${this.countRoute}`,\r\n params: { ...cleanFields }, // Отправляем на бэкенд только заполненные ключи\r\n };\r\n },\r\n {\r\n ...this.getHttpContext(),\r\n defaultValue: 0,\r\n parse: (data: unknown) => z.coerce.number().parse(data),\r\n },\r\n );\r\n }\r\n\r\n // Вспомогательный метод для сборки параметров таблицы в плоский объект\r\n protected buildTableParams(\r\n tableState: TableState,\r\n ): Record<string, string | number> {\r\n const queryParams: Record<string, string | number> = {};\r\n const { pageIndex, pageSize, sortActive, sortDirection } = tableState;\r\n\r\n if (pageIndex + 1) queryParams[this.pageIndexParam] = pageIndex + 1;\r\n if (pageSize) queryParams[this.pageSizeParam] = pageSize;\r\n if (sortActive) queryParams[this.sortColumnParam] = sortActive;\r\n if (sortDirection) queryParams[this.directionParam] = sortDirection;\r\n\r\n return queryParams;\r\n }\r\n\r\n /**\r\n * МЕТОД СОЗДАНИЯ (POST)\r\n * Принимает данные БЕЗ id. Тип формируется автоматически через Zod.\r\n */\r\n newObject(entity: Omit<T, 'id'>): any {\r\n // Если задана DTO-схема, очищаем объект от расчетных UI-полей перед отправкой\r\n const payload = this.schemaDTO ? this.schemaDTO.parse(entity) : entity;\r\n return this.http.post(this.baseRoute, payload, this.getHttpContext());\r\n }\r\n\r\n /**\r\n * Метод для СОЗДАНИЯ объекта (POST)\r\n * Тип аргумента генерируется автоматически: это ваш тип T, но БЕЗ поля id.\r\n */\r\n // create(dto: Omit<T, 'id'>): HttpResourceRef<T | undefined> {\r\n // return httpResource<T>(\r\n // () => ({\r\n // url: this.baseRoute,\r\n // method: 'POST',\r\n // body: dto, // Отправляем данные без id\r\n // }),\r\n // {\r\n // ...this.getHttpContext(),\r\n // // Сервер вернет созданный объект уже С присвоенным id, валидируем его полной схемой\r\n // parse: (data: unknown) => this.schema.parse(data),\r\n // },\r\n // );\r\n // }\r\n\r\n editObject(entity: T): any {\r\n // Если задана DTO-схема, очищаем объект от расчетных UI-полей перед отправкой\r\n const payload = this.schemaDTO ? this.schemaDTO.parse(entity) : entity;\r\n return this.http.put(\r\n this.baseRoute + entity.id,\r\n payload,\r\n this.getHttpContext(),\r\n );\r\n }\r\n\r\n /**\r\n * Метод для ОБНОВЛЕНИЯ объекта (PUT / PATCH)\r\n * Принимает id и частичный объект (все свойства T становятся необязательными, кроме id)\r\n */\r\n // update(\r\n // id: number,\r\n // dto: Partial<Omit<T, 'id'>>,\r\n // ): HttpResourceRef<T | undefined> {\r\n // return httpResource<T>(\r\n // () => ({\r\n // url: `${this.baseRoute}/${id}`,\r\n // method: 'PUT',\r\n // body: dto,\r\n // }),\r\n // {\r\n // ...this.getHttpContext(),\r\n // parse: (data: unknown) => this.schema.parse(data),\r\n // },\r\n // );\r\n // }\r\n\r\n /**\r\n * Метод DELETE (Переписанный под новую архитектуру)\r\n * Возвращает Observable. При подписке делает DELETE запрос,\r\n * а оператор 'tap' автоматически обновляет список getObjects() при успехе.\r\n */\r\n deleteObject(entity: T): any {\r\n return this.http\r\n .delete(this.baseRoute + entity.id, this.getHttpContext())\r\n .pipe(\r\n // Как только бэкенд ответит успехом, дергаем триггер обновления\r\n tap(() => this.refresh()),\r\n );\r\n }\r\n\r\n protected getParams(\r\n pageIndex: number,\r\n pageSize: number,\r\n sortColumn: string,\r\n direction: string,\r\n ): HttpParams {\r\n let params = new HttpParams();\r\n if (pageIndex + 1)\r\n // переход от индекса к номеру страницы\r\n params = params.append(this.pageIndexParam, pageIndex + 1);\r\n if (pageSize) params = params.append(this.pageSizeParam, pageSize);\r\n if (sortColumn) params = params.append(this.sortColumnParam, sortColumn);\r\n if (direction) params = params.append(this.directionParam, direction);\r\n return params;\r\n }\r\n\r\n // Вспомогательный метод для сборки опций HttpClient\r\n protected getHttpContext(): { context?: HttpContext } {\r\n // Если имя не задано (пустая строка, null или undefined), возвращаем пустой объект\r\n if (!this.apiContextName) {\r\n return {};\r\n }\r\n\r\n // Если имя задано, создаем и возвращаем контекст\r\n return {\r\n context: new HttpContext().set(API_NAME, this.apiContextName),\r\n };\r\n }\r\n\r\n /**\r\n * Безопасно валидирует данные с помощью Zod схемы.\r\n * Автоматически добавляет имя сервиса и эндпоинт в лог ошибки.\r\n */\r\n protected safeParseData<R>(schema: z.ZodType<R>, data: unknown, isArray = false): R {\r\n const result = schema.safeParse(data);\r\n\r\n if (!result.success) {\r\n // Собираем понятное имя контекста.\r\n // Например: \"UserService (Тип: Array<Schema>, Route: /api/human/)\"\r\n const serviceName = this.constructor.name;\r\n const typeInfo = isArray ? `Array<${serviceName.replace('Service', '')}>` : serviceName.replace('Service', '');\r\n const contextName = `${serviceName} [Ожидаемый тип: ${typeInfo}] (Route: \"${this.baseRoute}\")`;\r\n\r\n const formattedErrorMessage = formatZodError(result.error, contextName);\r\n \r\n throw new Error(formattedErrorMessage);\r\n }\r\n\r\n return result.data;\r\n }\r\n}\r\n","import { Directive, effect, ElementRef, inject, input } from '@angular/core';\r\nimport { RoleService } from '@kuzntsv/uikit';\r\n\r\n@Directive({\r\n selector: '[ngxUikDisableIfRole]',\r\n})\r\nexport class DisableIfRoleDirective {\r\n readonly forbiddenRoles = input<string[]>([], { alias: 'ngxUikDisableIfRole' });\r\n\r\n private readonly el = inject(ElementRef);\r\n private readonly roleService = inject(RoleService);\r\n\r\n constructor() {\r\n effect(() => {\r\n // Спрашиваем у сервиса, заблокирована ли данная конфигурация ролей\r\n const shouldDisable = this.roleService.hasForbiddenRole(this.forbiddenRoles());\r\n\r\n\r\n // 2. Безопасное управление атрибутом для любых элементов\r\n const nativeEl = this.el.nativeElement;\r\n \r\n if ('disabled' in nativeEl) {\r\n nativeEl.disabled = shouldDisable;\r\n } else {\r\n // Для элементов вроде <a>, у которых нет свойства disabled в DOM API\r\n if (shouldDisable) {\r\n nativeEl.setAttribute('disabled', 'true');\r\n } else {\r\n nativeEl.removeAttribute('disabled');\r\n }\r\n }\r\n });\r\n }\r\n}\r\n","import { Directive, ElementRef, effect, inject, input } from '@angular/core';\r\nimport { RoleService } from '@kuzntsv/uikit';\r\n\r\n@Directive({\r\n selector: '[ngxUikHideIfForbiddenRole]',\r\n})\r\nexport class HideIfForbiddenRoleDirective {\r\n readonly forbiddenRoles = input<string[]>([], {\r\n alias: 'ngxUikHideIfForbiddenRole',\r\n });\r\n\r\n private readonly el = inject(ElementRef);\r\n private readonly roleService = inject(RoleService);\r\n\r\n constructor() {\r\n effect(() => {\r\n // Элемент скрывается, если у пользователя есть запрещенная роль или передан маркер HIDE_ROLE_MARKER\r\n const shouldHide = this.roleService.hasForbiddenRole(\r\n this.forbiddenRoles(),\r\n );\r\n\r\n // Управляем отображением. Пустая строка возвращает дефолтный CSS-стиль элемента.\r\n this.el.nativeElement.style.display = shouldHide ? 'none' : '';\r\n });\r\n }\r\n}\r\n","import { Directive, effect, inject, input } from '@angular/core';\r\nimport { NgControl } from '@angular/forms';\r\n\r\n@Directive({\r\n selector: '[setValue]',\r\n})\r\nexport class SetValueDirective {\r\n readonly value = input<any>(null, { alias: 'setValue' });\r\n\r\n // 3. Используем опциональный inject, чтобы директива не падала, если формы нет\r\n private readonly ngControl = inject(NgControl, { optional: true });\r\n\r\n constructor() {\r\n effect(() => {\r\n // Эффект автоматически отслеживает изменение входного значения\r\n const val = this.value();\r\n\r\n // Безопасное приведение undefined к null для стандартизации значений в формах\r\n const normalizedValue = val === undefined ? null : val;\r\n\r\n // Используем проверку, так как на старте ngControl.control может быть еще не создан Angular-ом\r\n if (this.ngControl && this.ngControl.control) {\r\n this.ngControl.control.setValue(normalizedValue, { emitEvent: false });\r\n }\r\n });\r\n }\r\n}\r\n","import { inject } from '@angular/core';\r\nimport { CanActivateFn, Router } from '@angular/router';\r\nimport { AuthService } from '@kuzntsv/uikit';\r\n\r\nexport const authGuard = (allowedRoles: string[]): CanActivateFn => {\r\n return (route, state) => {\r\n const authService = inject(AuthService);\r\n const router = inject(Router);\r\n\r\n const isLogin = authService.loggedIn();\r\n if (!isLogin) {\r\n console.log('state.url =', state.url);\r\n\r\n // Если не зарегистрирован вернуть в форму авторизации\r\n return router.createUrlTree(['/login'], { queryParams: { returnUrl: state.url } });\r\n }\r\n\r\n return isLogin;\r\n };\r\n};","import { ActivatedRouteSnapshot, CanActivateFn } from '@angular/router';\r\n\r\nexport const redirectGuard: CanActivateFn = (route: ActivatedRouteSnapshot) => {\r\n const externalUrl = route.data?.['externalUrl'];\r\n \r\n if (externalUrl) {\r\n // Редирект в текущей вкладке через метод open, \r\n // который легко и легитимно мокается в любых тестах\r\n window.open(externalUrl, '_self');\r\n }\r\n \r\n return true;\r\n};\r\n","import { inject } from '@angular/core';\r\nimport { CanActivateFn } from '@angular/router';\r\nimport { RoleService } from '@kuzntsv/uikit';\r\n\r\n/**\r\n * Пускает на роут только тех пользователей, у которых есть роли из списка allowedRoles.\r\n * ADMIN всегда имеет доступ.\r\n */\r\nexport const roleGuard = (allowedRoles: string[]): CanActivateFn => {\r\n return (route, state) => {\r\n const roleService = inject(RoleService);\r\n\r\n // Проверяем доступ на основе аргумента allowedRoles\r\n return roleService.hasAnyRole(allowedRoles);\r\n };\r\n};","import { InjectionToken } from '@angular/core';\r\n\r\nexport interface LoggerConfig {\r\n isProduction: boolean;\r\n logLevel?: 'debug' | 'info' | 'warn' | 'error';\r\n}\r\n\r\nexport const LOGGER_CONFIG = new InjectionToken<LoggerConfig>('LOGGER_CONFIG');\r\n","import { inject, Service } from '@angular/core';\r\nimport { LOGGER_CONFIG } from './logger.config';\r\n\r\n\r\n@Service()\r\nexport class LoggerService {\r\n public logPrefix: string = '';\r\n private isProduction: boolean;\r\n private readonly config = inject(LOGGER_CONFIG);\r\n\r\n constructor() {\r\n this.isProduction = this.config.isProduction;\r\n }\r\n\r\n log(message: string, ...args: any[]) {\r\n if (!this.isProduction) {\r\n // Prepend log prefix log string\r\n args.unshift(this.logPrefix + ' ');\r\n console.log(`[DEV LOG]: ${message}`, ...args);\r\n }else {\r\n console.log(`[PROD LOG]: ${message}`, ...args);\r\n }\r\n }\r\n\r\n error(message: string, ...args: any[]): void {\r\n console.error(`[ERROR]: ${message}`, ...args);\r\n }\r\n}\r\n\r\n\r\n\r\n","import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\r\nimport { LOGGER_CONFIG, LoggerConfig } from './logger.config';\r\nimport { LoggerService } from './logger.service';\r\n\r\n\r\nexport function provideLogger(config: LoggerConfig): EnvironmentProviders {\r\n return makeEnvironmentProviders([\r\n { provide: LOGGER_CONFIG, useValue: config },\r\n LoggerService\r\n ]);\r\n};\r\n","import z from 'zod';\r\n\r\n// 1. Схема и тип для SecUserView\r\nexport const secUserViewSchema = z.object({\r\n id: z.number().default(0),\r\n idHuman: z.number().default(0).nullable(),\r\n loginAD: z\r\n .string()\r\n .nullable()\r\n .default('')\r\n .transform((val) => (val === null ? '' : val))\r\n .pipe(z.string()),\r\n dept: z.number().default(0).nullable(),\r\n tabnum: z.number().default(0).nullable(),\r\n lastname: z\r\n .string()\r\n .nullable()\r\n .default('')\r\n .transform((val) => (val === null ? '' : val))\r\n .pipe(z.string()),\r\n firstname: z\r\n .string()\r\n .nullable()\r\n .default('')\r\n .transform((val) => (val === null ? '' : val))\r\n .pipe(z.string()),\r\n middlename: z\r\n .string()\r\n .nullable()\r\n .default('')\r\n .transform((val) => (val === null ? '' : val))\r\n .pipe(z.string()),\r\n fio: z\r\n .string()\r\n .nullable()\r\n .default('')\r\n .transform((val) => (val === null ? '' : val))\r\n .pipe(z.string()),\r\n dateHuman: z.coerce.date().optional().nullable(), // Поле dateHuman?: Date\r\n profession: z\r\n .string()\r\n .nullable()\r\n .default('')\r\n .transform((val) => (val === null ? '' : val))\r\n .pipe(z.string()),\r\n});\r\n\r\nexport type SecUserView = z.infer<typeof secUserViewSchema>;\r\n","import z from \"zod\";\r\nimport { secUserViewSchema } from \"./sec-user-view.model\";\r\n\r\n// 2. Схема и тип для SecUser\r\nexport const secUserSchema = z.object({\r\n id: z.number().default(0),\r\n login: z.string().nullable().default('').transform((val) => (val === null ? \"\" : val)).pipe(z.string()),\r\n fio: z.string().nullable().default('').transform((val) => (val === null ? \"\" : val)).pipe(z.string()),\r\n dept: z.number().default(0).nullable(),\r\n tabnum: z.number().default(0).nullable(),\r\n userView: secUserViewSchema.optional().nullable(), // Вложенная схема\r\n});\r\n\r\nexport type SecUser = z.infer<typeof secUserSchema>;","import { inject, Pipe, PipeTransform } from '@angular/core';\r\nimport { DomSanitizer, SafeHtml, SafeResourceUrl, SafeScript, SafeStyle, SafeUrl } from '@angular/platform-browser';\r\n\r\n// Создаем тип для всех возможных безопасных значений Angular\r\nexport type SafeAny = SafeHtml | SafeStyle | SafeScript | SafeUrl | SafeResourceUrl;\r\n\r\n@Pipe({\r\n name: 'safe'\r\n})\r\nexport class SafePipe implements PipeTransform {\r\n\r\n private readonly sanitizer = inject(DomSanitizer);\r\n\r\n transform(url: string | SafeAny | null | undefined, type: 'html' | 'style' | 'script' | 'url' | 'resourceUrl' = 'url'): string | SafeAny {\r\n if (!url) {\r\n return '';\r\n }\r\n\r\n // Проверяем, является ли значение уже объектом SafeUrl.\r\n // Объекты SafeUrl от DomSanitizer имеют скрытые свойства или метод toString(), \r\n // но самый надежный способ в Angular — проверить, что это не обычная строка.\r\n if (typeof url !== 'string') {\r\n return url; // Возвращаем как есть, так как это уже SafeUrl\r\n }\r\n // Расширяем пайп универсальностью с помощью switch-case\r\n switch (type) {\r\n case 'html': return this.sanitizer.bypassSecurityTrustHtml(url);\r\n case 'style': return this.sanitizer.bypassSecurityTrustStyle(url);\r\n case 'script': return this.sanitizer.bypassSecurityTrustScript(url);\r\n case 'url': return this.sanitizer.bypassSecurityTrustUrl(url);\r\n case 'resourceUrl': return this.sanitizer.bypassSecurityTrustResourceUrl(url);\r\n default: throw new Error(`SafePipe: Неизвестный тип безопасности ${type}`);\r\n }\r\n }\r\n}\r\n","import { Pipe, PipeTransform } from '@angular/core';\r\n\r\n@Pipe({\r\n name: 'time'\r\n})\r\nexport class TimePipe implements PipeTransform {\r\n\r\n transform(value: number): string {\r\n // const hour = Math.abs(value) >= 60 ? Math.round(value / 60) + 'ч.' : '';\r\n // const minute = ' ' + Math.abs(value % 60) + 'м.';\r\n // return value === 0 ? '0' : hour + ' ' + minute;\r\n\r\n const hour = Math.abs(value) >= 60 ? Math.floor(Math.abs(value) / 60).toString().padStart(2,'0') : '00';\r\n const minute = Math.abs(value % 60).toString().padStart(2,'0');\r\n const time = hour + ':' + minute;\r\n return value < 0 ? '-' + time : time;\r\n }\r\n\r\n}\r\n","import { Pipe, PipeTransform } from '@angular/core';\r\n\r\n@Pipe({\r\n name: 'truncate'\r\n})\r\nexport class TruncatePipe implements PipeTransform {\r\n // Usage:\r\n // {{ str | truncate:[20] }} // or\r\n // {{ str | truncate:[20, '...'] }} // or|\r\n transform(value: string, args: any[]): string {\r\n const limit = args.length > 0 ? parseInt(args[0], 10) : 20;\r\n const trail = args.length > 1 ? args[1] : '...';\r\n return value.length > limit ? value.substring(0, limit) + trail : value;\r\n }\r\n\r\n}\r\n","import { COMMA, ENTER } from '@angular/cdk/keycodes';\nimport {\n Component,\n computed,\n inject,\n input,\n linkedSignal,\n model,\n} from '@angular/core';\nimport {\n MatAutocompleteModule,\n MatAutocompleteSelectedEvent,\n MatOption,\n} from '@angular/material/autocomplete';\nimport { MatChipsModule } from '@angular/material/chips';\nimport { MatError, MatFormField, MatLabel } from '@angular/material/form-field';\nimport { MatIcon } from '@angular/material/icon';\n\nimport { FormField, FormValueControl } from '@angular/forms/signals';\nimport { ChipItem } from './models';\n\n@Component({\n selector: 'ngx-uik-chip-input-autocomplete',\n templateUrl: './chip-input-autocomplete.component.html',\n styleUrl: './chip-input-autocomplete.component.css',\n imports: [\n MatFormField,\n MatAutocompleteModule,\n MatIcon,\n MatOption,\n MatChipsModule,\n MatLabel,\n MatError\n ],\n})\nexport class ChipInputAutocompleteComponent implements FormValueControl<\n string[]\n> {\n // Инжектируем внешнее поле формы для получения статусов (disabled, invalid)\n private readonly formFieldDirective = inject(FormField, {\n host: true,\n optional: true,\n });\n\n /** Все элементы. */\n items = input<ChipItem[]>([]);\n /** Заголовок. */\n title = input<string>('');\n\n // Реализация контракта FormValueControl через model().\n // Значением контрола является массив строк (ключей). Инициализируем пустым массивом.\n readonly value = model<string[]>([]);\n\n // Сигнал для управления текстом в поисковой строке (инпуте)\n readonly filterQuery = model<string>('');\n\n separatorKeysCodes: number[] = [ENTER, COMMA];\n\n // Синхронизируем массив объектов ChipItem на основе массива ключей value()\n readonly selectedItems = linkedSignal<string[], ChipItem[]>({\n source: () => this.value(),\n computation: (inputKeys) =>\n this.items().filter((item) => inputKeys.includes(item.value)),\n });\n\n // Декларативный computed-сигнал для фильтрации опций в выпадающем списке\n readonly filteredItems = computed<ChipItem[]>(() => {\n const allItems = this.items();\n const search = this.filterQuery().toLowerCase().trim();\n\n if (!search) {\n return allItems;\n }\n\n return allItems.filter((item) =>\n item.viewValue.toLowerCase().includes(search),\n );\n });\n\n // Считываем состояние блокировки напрямую из Signal Forms\n readonly isDisabled = computed(() => {\n return this.formFieldDirective?.state?.().disabled() ?? false;\n });\n\n // Считываем состояние валидности напрямую из Signal Forms\n readonly isInvalid = computed(() => {\n return this.formFieldDirective?.state()?.invalid() ?? false;\n });\n\n remove(value: string): void {\n if (this.isDisabled()) return;\n // Просто обновляем стейт нашей модели, Angular сделает всё остальное реактивно\n this.value.update((keys) => keys.filter((key) => key !== value));\n }\n\n selected(event: MatAutocompleteSelectedEvent): void {\n const selectedValue = event.option.value;\n\n this.value.update((keys) => {\n // Предотвращаем дубликаты в массиве ключей\n return keys.includes(selectedValue) ? keys : [...keys, selectedValue];\n });\n\n // Очищаем строку ввода после выбора элемента\n this.filterQuery.set('');\n }\n\n onCloseClick($event: MouseEvent) {\n $event.stopPropagation();\n if (this.isDisabled()) return;\n\n this.value.set([]);\n this.filterQuery.set('');\n }\n}\n","<mat-form-field class=\"chip-list\" appearance=\"fill\">\n <mat-label>{{ title() }}</mat-label>\n <mat-chip-grid #chipList aria-label=\"'Выбор '+title()\">\n @for (item of selectedItems(); track item.value) {\n <mat-chip-row color=\"primary\" (removed)=\"remove(item.value)\">\n {{ item.viewValue }}\n <button matChipRemove>\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n </mat-chip-grid>\n <input\n #input\n [value]=\"filterQuery()\"\n (input)=\"filterQuery.set($any($event.target).value)\"\n [placeholder]=\"'Введите ' + title() + '...'\"\n [matAutocomplete]=\"auto\"\n [matChipInputFor]=\"chipList\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n [disabled]=\"isDisabled()\"\n />\n <mat-autocomplete #auto=\"matAutocomplete\" (optionSelected)=\"selected($event)\">\n @for (item of filteredItems(); track item.value) {\n <mat-option\n [value]=\"item.value\"\n [disabled]=\"selectedItems().includes(item)\"\n >\n {{ item.viewValue }}\n </mat-option>\n }\n </mat-autocomplete>\n @if (!isDisabled() && value().length > 0) {\n <button\n matSuffix\n mat-icon-button\n aria-label=\"Clear\"\n (click)=\"onCloseClick($event)\"\n >\n <mat-icon>close</mat-icon>\n </button>\n }\n <!-- Блок вывода ошибки валидации родительской формы -->\n @if (isInvalid()) {\n <mat-error>Поле \"{{ title() }}\" заполнено некорректно</mat-error>\n }\n</mat-form-field>\n","import { Injectable } from '@angular/core';\r\nimport { NativeDateAdapter } from '@angular/material/core';\r\n\r\n@Injectable()\r\nexport class CustomDateAdapter extends NativeDateAdapter {\r\n \r\n // 1. Как дата ПАРСИТСЯ, когда пользователь вводит её руками в инпут\r\n override parse(value: any): Date | null {\r\n if (typeof value === 'string' && value.indexOf('.') > -1) {\r\n const str = value.split('.');\r\n const year = Number(str[2]);\r\n const month = Number(str[1]) - 1;\r\n const day = Number(str[0]);\r\n return new Date(year, month, day);\r\n }\r\n const timestamp = typeof value === 'number' ? value : Date.parse(value);\r\n return isNaN(timestamp) ? null : new Date(timestamp);\r\n }\r\n\r\n // 2. Как дата ОТОБРАЖАЕТСЯ в самом инпуте\r\n override format(date: Date, displayFormat: Object): string {\r\n if (displayFormat === 'input') {\r\n const day = String(date.getDate()).padStart(2, '0');\r\n const month = String(date.getMonth() + 1).padStart(2, '0');\r\n const year = date.getFullYear();\r\n return `${day}.${month}.${year}`; // Наш строгий DD.MM.YYYY\r\n }\r\n // Для всех остальных элементов (выбор месяца, года) оставляем стандартное поведение локали\r\n return super.format(date, displayFormat);\r\n }\r\n}\r\n\r\n// Объект форматов для NativeDateAdapter\r\nexport const MY_NATIVE_FORMATS = {\r\n parse: {\r\n dateInput: 'input',\r\n },\r\n display: {\r\n dateInput: 'input', // Маркер 'input' будет перехвачен нашим методом format() выше\r\n monthYearLabel: { year: 'numeric', month: 'short' },\r\n dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },\r\n monthYearA11yLabel: { year: 'numeric', month: 'long' },\r\n },\r\n};","import { z } from 'zod';\r\n\r\n// Безопасная функция перевода Date в ISO-строку \"YYYY-MM-DD\"\r\nconst toIsoString = (date: Date | null): string => {\r\n if (!date) return '';\r\n // .toISOString() всегда возвращает формат \"2026-10-28T06:00:00.000Z\"\r\n // .split('T')[0] срезает всё после времени, оставляя чистое \"2026-10-28\"\r\n return date.toISOString().split('T')[0];\r\n};\r\n\r\nexport const dateRangeFormSchema = z.object({\r\n begin: z\r\n .instanceof(Date)\r\n .nullable(),\r\n end: z\r\n .instanceof(Date)\r\n .nullable(),\r\n });\r\n\r\n// Тип вывода { begin: Date | null; end: Date | null; }\r\nexport type DateRangeForm = z.output<typeof dateRangeFormSchema>;\r\n\r\n// Создаем динамическую схему валидации\r\nexport const dateRangeSchema = dateRangeFormSchema.transform((data) => ({\r\n begin: toIsoString(data.begin),\r\n end: toIsoString(data.end),\r\n }));\r\n\r\n// Тип вывода { begin: string; end: string; }\r\nexport type DateRange = z.output<typeof dateRangeSchema>;\r\n","import {\n Component,\n effect,\n input,\n output,\n signal,\n untracked\n} from '@angular/core';\nimport { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';\nimport {\n MatDatepickerToggle,\n MatDateRangeInput,\n MatDateRangePicker,\n MatEndDate,\n MatStartDate,\n} from '@angular/material/datepicker';\nimport {\n MatError,\n MatFormField,\n MatLabel,\n MatSuffix,\n} from '@angular/material/form-field';\n\nimport { debounce, form, FormField, required, validateStandardSchema } from '@angular/forms/signals';\nimport { DateRange, DateRangeForm, dateRangeFormSchema, dateRangeSchema } from './models';\nimport {\n CustomDateAdapter,\n MY_NATIVE_FORMATS,\n} from './models/custom-date-adapter';\n\n@Component({\n selector: 'ngx-uik-date-range-input',\n templateUrl: './date-range-input.component.html',\n styleUrls: ['./date-range-input.component.scss'],\n imports: [\n FormField,\n MatFormField,\n MatLabel,\n MatDateRangeInput,\n MatStartDate,\n MatEndDate,\n MatDatepickerToggle,\n MatSuffix,\n MatDateRangePicker,\n MatError,\n ],\n providers: [\n { provide: DateAdapter, useClass: CustomDateAdapter },\n { provide: MAT_DATE_FORMATS, useValue: MY_NATIVE_FORMATS },\n ],\n})\nexport class DateRangeInputComponent {\n readonly DEFAULT_MIN_DATE = new Date(2020, 0, 1);\n\n label = input<string>('');\n dateRange = input<DateRange>(<DateRange>{ begin: '', end: '' });\n minDate = input<Date>(this.DEFAULT_MIN_DATE);\n clearInput = input<any>(null);\n required = input<boolean>(false);\n dateRangeChange = output<DateRange>();\n\n formModel = signal<DateRangeForm>({ begin: null, end: null });\n\n form = form(this.formModel, (schemaPath) => {\n validateStandardSchema(schemaPath, dateRangeFormSchema);\n required(schemaPath.begin, {message: \"Укажите период\", when: () => this.required()});\n required(schemaPath.end, {message: \"Укажите период\", when: () => this.required()});\n debounce(schemaPath.begin, 500);\n debounce(schemaPath.end, 500);\n });\n\n constructor() {\n effect(() => {\n this.clearInput();\n \n untracked(() => this.form().reset());\n });\n\n effect(() => {\n const value = this.dateRange();\n\n untracked(() => {\n this.form.begin().value.set(value.begin ? new Date(value.begin) : null);\n this.form.end().value.set(value.end ? new Date(value.end) : null);\n });\n });\n\n effect(() => {\n const currentValues = this.form().value();\n\n if (this.form().valid()) {\n const formattedRange = dateRangeSchema.safeParse(currentValues);\n if (formattedRange.success) {\n this.dateRangeChange.emit(formattedRange.data);\n }\n }\n });\n }\n\n}\n","<mat-form-field appearance=\"fill\">\r\n <mat-label>{{ label() }}</mat-label>\r\n <mat-date-range-input\r\n [rangePicker]=\"picker\"\r\n [min]=\"minDate()\"\r\n >\r\n <input matStartDate [formField]=\"form.begin\" placeholder=\"Дата начала\" />\r\n <input matEndDate [formField]=\"form.end\" placeholder=\"Дата окончания\" />\r\n </mat-date-range-input>\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-date-range-picker #picker></mat-date-range-picker>\r\n @if (form.begin().touched() && form.begin().invalid()) {\r\n <ng-container ngProjectAs=\"mat-error\">\r\n <mat-error>{{ form.begin().errors()[0]?.message }}</mat-error>\r\n </ng-container>\r\n }\r\n @if (form.end().touched() && form.end().invalid()) {\r\n <ng-container ngProjectAs=\"mat-error\">\r\n <mat-error>{{ form.end().errors()[0]?.message }}</mat-error>\r\n </ng-container>\r\n }\r\n</mat-form-field>\r\n","export enum DialogAction {\r\n Add = 'Добавить',\r\n Edit = 'Изменить',\r\n Delete = 'Удалить',\r\n None = ''\r\n }","import { Component } from '@angular/core';\n\n@Component({\n selector: 'ngx-uik-empty-route-guard-holder',\n template: '', // пустой шаблон, так как гуард сразу уводит пользователя со страницы\n})\nexport class EmptyComponent {}\n","import { z } from 'zod';\r\n\r\n// 1. Создаем Zod-схему авторизации\r\nexport const loginSchema = z.object({\r\n username: z\r\n .string()\r\n .min(1, { message: 'Пожалуйста, заполните это поле' })\r\n .regex(/^[A-Za-z]{1,}\\.[A-Za-z]{1,}\\.[A-Za-z]*$/, {\r\n message: 'Пожалуйста, используйте формат \"a.p.petrov\"',\r\n }),\r\n password: z.string().min(1, { message: 'Пожалуйста, заполните это поле' }),\r\n});\r\n\r\n// 2. Автоматически генерируем тип Authenticate из созданной схемы\r\n// Больше никакой ручной поддержки интерфейса — изменения в схеме обновят тип сами!\r\nexport type Authenticate = z.infer<typeof loginSchema>;\r\n","import { Component, input, output, signal } from '@angular/core';\nimport { MatButton } from '@angular/material/button';\nimport {\n MatCard,\n MatCardContent,\n MatCardHeader,\n MatCardTitle,\n} from '@angular/material/card';\nimport {\n MatError,\n MatFormField,\n MatLabel,\n MatSuffix,\n} from '@angular/material/form-field';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatInput } from '@angular/material/input';\n\nimport {\n disabled,\n form,\n FormField,\n FormRoot,\n validateStandardSchema,\n} from '@angular/forms/signals';\nimport { Authenticate, loginSchema } from '../../models/authenticate';\n\n@Component({\n selector: 'ngx-uik-login-form',\n templateUrl: 'login-form.component.html',\n styleUrls: ['login-form.component.scss'],\n imports: [\n FormRoot,\n FormField,\n MatCard,\n MatCardHeader,\n MatCardTitle,\n MatCardContent,\n MatFormField,\n MatLabel,\n MatInput,\n MatError,\n MatIcon,\n MatSuffix,\n MatButton,\n ],\n})\nexport class LoginFormComponent {\n pending = input<boolean>(false);\n submitted = output<Authenticate>();\n\n readonly isHidePassword = signal(true);\n\n formModel = signal<Authenticate>({ username: '', password: '' });\n\n form = form(\n this.formModel,\n (schemaPath) => {\n validateStandardSchema(schemaPath, loginSchema);\n disabled(schemaPath.username, { when: () => this.pending() });\n disabled(schemaPath.password, { when: () => this.pending() });\n },\n {\n submission: {\n action: async (field) => {\n this.submitted.emit(field().value());\n return;\n },\n },\n },\n );\n\n // Метод для показа пароля (вызывается при нажатии)\n showPassword(): void {\n this.isHidePassword.set(false);\n }\n\n // Метод для скрытия пароля (вызывается при отпускании)\n hidePassword(): void {\n this.isHidePassword.set(true);\n }\n}\n","<mat-card appearance=\"outlined\">\r\n <mat-card-header>\r\n <mat-card-title> Авторизация </mat-card-title>\r\n </mat-card-header>\r\n <mat-card-content>\r\n <form [formRoot]=\"form\">\r\n <mat-form-field class=\"login-field\">\r\n <mat-label>Имя пользователя</mat-label>\r\n <input\r\n type=\"text\"\r\n matInput\r\n autocomplete=\"on\"\r\n placeholder=\"Имя пользователя\"\r\n [formField]=\"form.username\"\r\n />\r\n @if (form.username().touched() && form.username().invalid()) {\r\n <ng-container ngProjectAs=\"mat-error\">\r\n <mat-error>{{ form.username().errors()[0]?.message }}</mat-error>\r\n </ng-container>\r\n }\r\n </mat-form-field>\r\n\r\n <mat-form-field class=\"login-field\">\r\n <mat-label>Пароль</mat-label>\r\n <input\r\n [type]=\"isHidePassword() ? 'password' : 'text'\"\r\n matInput\r\n placeholder=\"Пароль\"\r\n [formField]=\"form.password\"\r\n />\r\n <mat-icon\r\n class=\"watcher\"\r\n matSuffix\r\n (mousedown)=\"showPassword()\"\r\n (mouseup)=\"hidePassword()\"\r\n >{{ isHidePassword() ? \"visibility_off\" : \"visibility\" }}</mat-icon\r\n >\r\n @if (form.password().touched() && form.password().invalid()) {\r\n <ng-container ngProjectAs=\"mat-error\">\r\n <mat-error>{{ form.password().errors()[0]?.message }}</mat-error>\r\n </ng-container>\r\n }\r\n </mat-form-field>\r\n\r\n <div class=\"loginButtons\">\r\n <button\r\n type=\"submit\"\r\n mat-button\r\n mat-stroked-button\r\n color=\"primary\"\r\n [disabled]=\"!form().valid() || pending()\"\r\n >\r\n Войти\r\n </button>\r\n </div>\r\n </form>\r\n </mat-card-content>\r\n</mat-card>\r\n","import {\n Component,\n effect,\n ElementRef,\n HostListener,\n output,\n viewChild\n} from '@angular/core';\nimport {\n MatCard,\n MatCardContent,\n MatCardHeader,\n MatCardTitle,\n} from '@angular/material/card';\n\n@Component({\n selector: 'ngx-uik-permit-form',\n templateUrl: 'permit-form.component.html',\n styleUrls: ['permit-form.component.scss'],\n imports: [MatCard, MatCardHeader, MatCardTitle, MatCardContent],\n})\nexport class PermitFormComponent {\n readonly hidy = viewChild<ElementRef<HTMLInputElement>>('hidy');\n submitted = output<string>();\n\n constructor() {\n // Эффект сработает автоматически, как только элемент появится в DOM\n effect(() => {\n // Обнуляем значение Input\n const inputEl = this.hidy()?.nativeElement;\n if (inputEl) {\n inputEl.focus();\n }\n });\n }\n\n /**\n * Метод для возврата фокуса в инпут\n */\n @HostListener('document:mouseup') \n focusInput(): void {\n this.hidy()?.nativeElement.focus();\n }\n\n /**\n * Обработка ввода с клавиатуры/сканера\n */\n onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Enter') {\n const inputEl = this.hidy()?.nativeElement;\n if (inputEl?.value && inputEl.value.trim()) {\n this.submitted.emit(inputEl.value);\n inputEl.value = '';\n }\n }\n }\n}\n","<mat-card appearance=\"outlined\">\r\n <mat-card-header>\r\n <mat-card-title>\r\n Приложите пропуск\r\n </mat-card-title>\r\n </mat-card-header>\r\n <mat-card-content>\r\n <div class=\"permit\"></div>\r\n </mat-card-content>\r\n</mat-card>\r\n<input #hidy class=\"hidy\" type=\"text\" (keydown)=\"onKeydown($event)\"/>","import { Component, inject, input, signal } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { AuthService, UIKIT_NOTIFICATION_TOKEN } from '@kuzntsv/uikit';\nimport { lastValueFrom } from 'rxjs';\n\nimport { Authenticate } from '../../models/authenticate';\nimport { LoginFormComponent } from '../login-form/login-form.component';\nimport { PermitFormComponent } from '../permit-form/permit-form.component';\n\n@Component({\n selector: 'ngx-uik-login-page',\n templateUrl: 'login-page.component.html',\n styleUrls: ['login-page.component.scss'],\n imports: [LoginFormComponent, PermitFormComponent],\n})\nexport class LoginPageComponent {\n pending = signal<boolean>(false);\n isKiosk = signal<boolean>(false);\n\n /**\n * Идентификатор АС получаем автоматически из ActivatedRoute Data!\n * (Для этого в настройках роутера должен быть включен withComponentInputBinding())\n */\n idCas = input<number>(0);\n\n private readonly authService = inject(AuthService);\n private readonly router = inject(Router);\n private readonly notificationService = inject(UIKIT_NOTIFICATION_TOKEN, {\n optional: true,\n });\n\n constructor() {\n // Вместо ngOnInit проверяем localStorage сразу при инициализации класса\n if (\n localStorage.getItem('id_human') ||\n localStorage.getItem('kiosk-keyboard-layout')\n ) {\n // this.isKiosk.set(true);\n }\n }\n\n async onSubmit(event: Authenticate) {\n this.startLoading();\n\n try {\n // Превращаем Observable в Promise. Вызовется метод login, выполнится и завершится.\n await lastValueFrom(\n this.authService.login(event.username, event.password, this.idCas()),\n );\n // Срабатывает строго при успешном разрешении промиса\n this.handleSuccessLogin();\n } catch (error) {\n // Срабатывает, если сервер вернул ошибку\n this.handleError(error);\n } finally {\n // Блок finally гарантирует выполнение, заменяя оператор `finalize` из RxJS\n this.finishLoading();\n }\n }\n\n async onSubmitPermit(permit: string) {\n this.startLoading();\n\n try {\n await lastValueFrom(\n this.authService.loginByPermit(permit, this.idCas())\n );\n this.handleSuccessLogin();\n } catch (error) {\n this.handleError(error);\n } finally {\n this.finishLoading();\n }\n }\n\n private startLoading(): void {\n this.pending.set(true);\n }\n\n private finishLoading(): void {\n this.pending.set(false);\n }\n\n private handleError(error: any): void {\n const errorMsg =\n 'Ошибка при авторизации: ' +\n (error.error || error.error?.message || error.message);\n this.notificationService?.error(errorMsg, 0);\n }\n\n private handleSuccessLogin(): void {\n this.notificationService?.success('Успешная авторизация');\n\n if (!this.router) return;\n\n // ЛОГИКА ВОЗВРАТА ПОСЛЕ УСПЕШНОГО ЛОГИНА\n\n // Извлекаем returnUrl из текущего query-параметра текущего маршрута\n const currentUrlTree = this.router.parseUrl(this.router.url);\n const returnUrl = currentUrlTree.queryParamMap.get('returnUrl');\n\n if (returnUrl) {\n // Декодируем и перенаправляем пользователя туда, где он был\n this.router.navigateByUrl(decodeURIComponent(returnUrl));\n } else {\n // Если returnUrl нет, идем на главную\n this.router.navigate(['/']);\n }\n }\n}\n","@if (isKiosk()) {\r\n <ngx-uik-permit-form (submitted)=\"onSubmitPermit($event)\" />\r\n} @else {\r\n <ngx-uik-login-form (submitted)=\"onSubmit($event)\" [pending]=\"pending()\" />\r\n}\r\n","import {\n ChangeDetectionStrategy,\n Component,\n inject,\n input,\n output,\n} from '@angular/core';\nimport { MatAnchor } from '@angular/material/button';\nimport { MatDialog } from '@angular/material/dialog';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatTooltip } from '@angular/material/tooltip';\nimport { SafeUrl } from '@angular/platform-browser';\nimport { filter, take } from 'rxjs';\n\nimport { BaseNavBarMenuClass } from '../../base';\nimport { SafePipe } from '../../pipes';\nimport { DialogComponent } from '../dialog';\n\n@Component({\n selector: 'ngx-uik-navbar',\n templateUrl: 'navbar.html',\n styleUrls: ['./navbar.scss'],\n changeDetection: ChangeDetectionStrategy.Eager,\n imports: [MatAnchor, MatIcon, MatTooltip, SafePipe],\n})\nexport class NavBarComponent extends BaseNavBarMenuClass {\n /** Видимость панели, когда loggedIn === false. */\n visibleOnLogout = input<boolean>(false);\n /** Видимость аватара. */\n visibleAvatar = input<boolean>(true);\n /** Видимость кнопки \"Выйти\". */\n visibleLogoutBtn = input<boolean>(true);\n /** Признак, что пользователь авторизован. */\n loggedIn = input<boolean>(false);\n /** ФИО пользователя. */\n fioUser = input<string>('');\n /** Всплывающая подсказка о пользователе. */\n userTooltip = input<string>('');\n /** URL аватара */\n avatarURL = input<string | SafeUrl>('');\n\n /** Нажата кнопка \"Выйти\". */\n logout = output<string>();\n\n private readonly dialog = inject(MatDialog);\n\n onLogout() {\n this.logout.emit(this.router.url);\n }\n\n openDialog(): void {\n const dialogRef = this.dialog.open(DialogComponent, {\n width: '400px',\n data: {\n id: 'logout',\n title: 'Подтверждение',\n message: 'Вы хотите выйти?',\n btnNoTitle: 'Отмена',\n btnYesTitle: 'Выйти',\n },\n });\n\n dialogRef\n .afterClosed()\n .pipe(\n take(1), // Берем только одно значение (когда закрылся)\n filter((id) => !!id), // Пропускаем дальше, только если id существует (нажали \"Выйти\")\n )\n .subscribe((id: any) => {\n if (id) {\n this.onLogout();\n }\n });\n }\n}\n","@if (visibleOnLogout() || loggedIn()) {\r\n <nav class=\"ngx-uik-navbar-header\">\r\n \r\n <ng-content></ng-content>\r\n\r\n <div class=\"flex-spacer\"></div>\r\n \r\n @if (visibleAvatar() && (loggedIn() === false || !avatarURL())) {\r\n <mat-icon [matTooltip]=\"userTooltip()\">account_circle</mat-icon>\r\n }\r\n @if (visibleAvatar() && loggedIn() && !!avatarURL()) {\r\n <img\r\n class=\"user-photo\"\r\n [src]=\"avatarURL() | safe\"\r\n loading=\"lazy\"\r\n [alt]=\"fioUser()\"\r\n [matTooltip]=\"userTooltip()\">\r\n }\r\n\r\n <span class = \"user-name\" [matTooltip]=\"userTooltip()\">\r\n {{ fioUser() }}\r\n </span>\r\n\r\n @if (visibleLogoutBtn()) {\r\n <a mat-button class=\"pm-button\" (click)=\"openDialog()\">Выйти <mat-icon>logout</mat-icon></a>\r\n }\r\n </nav>\r\n}","import { Component, ChangeDetectionStrategy } from '@angular/core';\n\n@Component({\n selector: 'ngx-uik-not-found',\n templateUrl: './not-found.component.html',\n styleUrls: ['./not-found.component.css'],\n})\nexport class NotFoundComponent {}\n","<div class=\"center\">\r\n <h3 class=\"mat-display-1\">Страница не найдена</h3>\r\n</div>\r\n","import { ScrollingModule } from '@angular/cdk/scrolling';\nimport {\n Component,\n computed,\n debounced,\n effect,\n inject,\n input,\n model\n} from '@angular/core';\nimport { FormField, FormValueControl } from '@angular/forms/signals';\nimport {\n MatAutocompleteModule,\n MatAutocompleteSelectedEvent,\n MatOption,\n} from '@angular/material/autocomplete';\nimport {\n MatError,\n MatFormField,\n MatHint,\n MatLabel,\n} from '@angular/material/form-field';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatInput } from '@angular/material/input';\n\nimport { SelectItem } from './models';\n\n@Component({\n selector: 'ngx-uik-select-autocomplete-with-vs',\n templateUrl: './select-autocomplete-with-vs.component.html',\n styleUrl: './select-autocomplete-with-vs.component.css',\n\n imports: [\n MatAutocompleteModule,\n MatHint,\n MatError,\n MatOption,\n MatIcon,\n MatFormField,\n ScrollingModule,\n MatInput,\n MatLabel,\n ],\n})\nexport class SelectAutocompleteWithVsComponent\n implements FormValueControl<string | undefined>\n{\n readonly ITEM_HEIGHT_PX = 50;\n readonly MAX_VISIBLE_ITEMS = 4;\n readonly MAX_HEIGHT_PX = 200;\n\n // Инжектим директиву FormField, примененную к нашему компоненту снаружи.\n // { host: true, optional: true } гарантирует, что если компонент рендерят просто так (вне формы), приложение не упадет.\n private readonly formFieldDirective = inject(FormField, { host: true, optional: true });\n\n /** Все элементы. */\n items = input<SelectItem[]>([]); \n /** Заголовок. */\n title = input<string>('');\n /** Ширина. */\n width = input<string>('200');\n\n // Реализация FormValueControl: обязательное свойство value в виде Writable Signal / Model\n readonly value = model<string | undefined>(undefined);\n\n // Сигнал для текстового ввода пользователя, на основе которого идет фильтрация\n readonly filterQuery = model<string>('');\n\n // Декларативно получаем статус disabled напрямую из Signal Forms родителя\n readonly isDisabled = computed(() => {\n return this.formFieldDirective?.state()?.disabled() ?? false;\n });\n\n // Проверяем состояние валидности для отображения ошибки\n readonly isInvalid = computed(() => {\n return this.formFieldDirective?.state()?.invalid() ?? false;\n });\n\n // Создаем дебаунс-сигнал на 200мс от оригинальной модели\n readonly debouncedQuery = debounced(this.filterQuery, 500);\n\n // отфильтрованные (отображаемые) элементы\n // Декларативная фильтрация через computed. Срабатывает автоматически при изменении любого сигнала внутри.\n readonly filteredItems = computed<SelectItem[]>(() => {\n const allItems = this.items();\n const query = this.debouncedQuery.value().toLowerCase().trim();\n\n if (!query) {\n return allItems;\n }\n\n return allItems.filter((option) =>\n option.viewValue.toLowerCase().includes(query)\n );\n });\n\n // Автоматический расчет высоты для Virtual Scroll на основе отфильтрованных элементов\n readonly height = computed<string>(() => {\n const count = this.filteredItems().length;\n return count < this.MAX_VISIBLE_ITEMS ? `${count * this.ITEM_HEIGHT_PX}px` : `${this.MAX_HEIGHT_PX}px`;\n });\n\n constructor() {\n // Решаем проблему №1: Синхронизируем строку ввода при инициализации формы \n // или при программном изменении значения из родительского компонента\n effect(() => {\n const selected = this.selectedItemObject();\n if (selected && this.filterQuery() !== selected.viewValue) {\n this.filterQuery.set(selected.viewValue);\n }\n });\n }\n\n // constructor() {\n // effect(() => {\n // console.log('ITEMS =', this.items());\n // //this.filteredItems = this.items();\n\n // console.log('selectedItem =', this.selectedItemInput());\n // if (this.items().length > 0) {\n // console.log('filteredItems SET');\n // this.setFileredItems(this.items());\n // this.inputCtrl.setValue(this.selectedItemInput());\n // }\n // });\n // }\n\n // ngOnInit(): void {\n // // Listen for changes to the input\n // const subs = this.inputCtrl.valueChanges\n // .pipe(\n // startWith(''),\n // // eslint-disable-next-line no-magic-numbers\n // debounceTime(500),\n // distinctUntilChanged(),\n // // Note: If the option value is bound to object, after selecting the option\n // // Note: the value will change from string to {}. We want to perform search\n // // Note: only when the type is string (no match)\n // //filter(q => typeof q === 'string'),\n // //tap((v) => console.log('v=', v)),\n // map((value) => {\n // // Filter the options\n // console.log('typeof value =', typeof value);\n\n // if (typeof value === 'undefined') {\n // this.setFileredItems(this.items());\n // } else {\n // if (typeof value !== 'object') {\n // console.log('v1=', value);\n // this.setFileredItems(\n // this.items().filter((option) =>\n // option.viewValue.toLowerCase().includes(value.toLowerCase()),\n // ),\n // );\n // } else {\n // // typeof value === 'object'\n // console.log('v2=', value);\n // if (value) {\n // // this.predmet = value;\n // this.setFileredItems(\n // this.items().filter((option) =>\n // option.viewValue\n // .toLowerCase()\n // .includes(value.viewValue.toLowerCase()),\n // ),\n // );\n // console.log('v3=', value);\n // } else {\n // this.setFileredItems(this.items());\n // console.log('v4=', value);\n // }\n // }\n // }\n // }),\n // )\n // .subscribe();\n // this.subscription.add(subs);\n\n // // if (this.isDisabled()) {\n // // this.inputCtrl.disable();\n // // } else {\n // // this.inputCtrl.enable();\n // // }\n // }\n\n\n // onSelectedItemChange(item: any) {\n // console.log('onSelectedItemChange, item=', item);\n // this.selectedItem.set(item);\n // this.selectedItemChange.emit(item);\n // }\n\n // 3. Вычисляем текущий выбранный объект для отображения в шаблоне на основе строки value()\n readonly selectedItemObject = computed(() => {\n const currentKey = this.value();\n return this.items().find(item => item.value === currentKey);\n });\n\n // Срабатывает при физическом клике по опции в автокомплите\n onOptionSelected(event: MatAutocompleteSelectedEvent): void {\n const selected: SelectItem = event.option.value;\n this.value.set(selected.value);\n this.filterQuery.set(selected.viewValue); // Фиксируем текст в инпуте\n }\n\n // Обновление поискового запроса при вводе текста пользователем\n onInputChanges(event: Event): void {\n const inputElement = event.target as HTMLInputElement;\n const currentText = inputElement.value;\n\n this.filterQuery.set(currentText);\n \n // Сбрасываем только если поле полностью пустое!\n if (!currentText) {\n this.value.set(undefined);\n }\n }\n\n // Новая логика: проверка валидности введенного текста строго при потере фокуса\n onBlur(): void {\n const currentText = this.filterQuery().trim();\n const currentSelected = this.selectedItemObject();\n\n // Если текст в инпуте не пустой, но он не совпадает с viewValue выбранного объекта,\n // значит пользователь ввёл случайный набор букв и ушёл из поля. Сбрасываем всё.\n if (currentText && currentText !== currentSelected?.viewValue) {\n this.value.set(undefined);\n this.filterQuery.set('');\n }\n }\n\n onClearClick($event: MouseEvent) {\n $event.stopPropagation();\n this.value.set(undefined);\n this.filterQuery.set('');\n }\n\n displayWithFn(item: SelectItem | null | undefined): string {\n return item ? item.viewValue : '';\n }\n\n // private setFileredItems(items: SelectItem[]) {\n // this.filteredItems = items;\n // // Recompute how big the viewport should be.\n // // eslint-disable-next-line no-magic-numbers\n // if (items.length < 4) {\n // // eslint-disable-next-line no-magic-numbers\n // this.height = items.length * 50 + 'px';\n // } else {\n // this.height = '200px';\n // }\n // console.log('update filteredItems =', this.filteredItems);\n // }\n}\n","<mat-form-field [style.width.px]=\"width()\">\r\n <mat-label>{{ title() }}</mat-label>\r\n <input type=\"text\" matInput [matAutocomplete]=\"auto\" aria-label=\"Number\"\r\n [placeholder]=title() \r\n [value]=\"filterQuery()\"\r\n (input)=\"onInputChanges($event)\"\r\n (blur)=\"onBlur()\"\r\n [disabled]=\"isDisabled()\"\r\n >\r\n @if (!isDisabled() && value()) {\r\n <button mat-button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"onClearClick($event)\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n <mat-autocomplete #auto=\"matAutocomplete\" [displayWith]=\"displayWithFn\" showPanel=\"true\" (optionSelected)=\"onOptionSelected($event)\">\r\n <cdk-virtual-scroll-viewport class=\"autocomplete-test-viewport\" [style.height]=\"height()\" itemSize=\"25\">\r\n <mat-option *cdkVirtualFor=\"let option of filteredItems()\" [value]=\"option.value\" class=\"autocomplete-item\">\r\n {{option.viewValue}}\r\n </mat-option>\r\n </cdk-virtual-scroll-viewport>\r\n </mat-autocomplete>\r\n\r\n <!-- Показываем ошибку, если Signal Forms сообщил, что поле invalid -->\r\n @if (isInvalid()) {\r\n <mat-error>Заполните поле \"{{ title() }}\"</mat-error>\r\n }\r\n\r\n @if (!filterQuery() && !value()) {\r\n <mat-hint>Начните вводить ...</mat-hint>\r\n }\r\n</mat-form-field>\r\n","import { COMMA, ENTER } from '@angular/cdk/keycodes';\n\nimport { Component, input, model } from '@angular/core';\nimport { MatOptgroup, MatOption } from '@angular/material/core';\nimport { MatIcon } from '@angular/material/icon';\nimport {\n MatFormField,\n MatLabel,\n MatSelect,\n MatSelectChange,\n} from '@angular/material/select';\n\nimport { SelectGroup } from './models';\nimport { FormValueControl } from '@angular/forms/signals';\n\n@Component({\n selector: 'ngx-uik-select-with-group',\n templateUrl: './select-with-group.component.html',\n styleUrls: ['./select-with-group.component.css'],\n imports: [MatIcon, MatOption, MatOptgroup, MatSelect, MatFormField, MatLabel],\n})\nexport class SelectWithGroupComponent implements FormValueControl<string[]> {\n /** Все группы. */\n groups = input<SelectGroup[]>([]);\n /** Заголовок. */\n title = input<string>('');\n // FormValueControl требует обязательное свойство value в виде модели/сигнала\n // Инициализируем пустым массивом, так как undefined запрещен в Signal Forms\n /** Выбранные элементы, ключи (BaseSelectItem.value). */\n readonly value = model<string[]>([]);\n\n readonly separatorKeysCodes = [ENTER, COMMA];\n\n onSelectionChange(event: MatSelectChange): void {\n this.value.set(event.value ?? []);\n }\n\n onClearClick($event: MouseEvent) {\n $event.stopPropagation();\n this.value.set([]);\n }\n}\n","<mat-form-field class=\"select-with-group\" appearance=\"fill\">\r\n <mat-label>{{ title() }}</mat-label>\r\n <mat-select [value]=\"value()\" (selectionChange)=\"onSelectionChange($event)\" multiple>\r\n @for (group of groups(); track group.name) {\r\n <mat-optgroup [label]=\"group.name\">\r\n @for (item of group.items; track item.value) {\r\n <mat-option [value]=\"item.value\" >\r\n {{item.viewValue}}\r\n </mat-option>\r\n }\r\n </mat-optgroup>\r\n }\r\n\r\n </mat-select>\r\n @if (value().length > 0) {\r\n <button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"onClearClick($event)\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n</mat-form-field>\r\n","import z from \"zod\";\r\nimport { SortDirection } from \"../../../types/types\";\r\n\r\nexport const SortDirectionSchema = z.custom<SortDirection>(\r\n (val) => val === 'asc' || val === 'desc' || val === '',\r\n { message: \"Допустимы только значения 'asc', 'desc' или ''\" }\r\n);\r\n\r\n// Схема состояния сортировки\r\nexport const SortStateSchema = z.object({\r\n sortActive: z.string(),\r\n sortDirection: SortDirectionSchema,\r\n});\r\n\r\n// Схема состояния пагинации\r\nexport const PageStateSchema = z.object({\r\n pageIndex: z.number().int().min(0),\r\n pageSize: z.number().int().positive(),\r\n});\r\n\r\n// Объединенная схема для состояния таблицы\r\nexport const TableStateSchema = SortStateSchema.merge(PageStateSchema);\r\n\r\n// Автоматически выведенные TypeScript-типы из Zod-схем\r\nexport type SortState = z.infer<typeof SortStateSchema>;\r\nexport type PageState = z.infer<typeof PageStateSchema>;\r\nexport type TableState = z.infer<typeof TableStateSchema>;\r\n","import { MatPaginatorIntl } from '@angular/material/paginator';\r\n\r\nexport function getRuPaginatorIntl() {\r\n const intl = new MatPaginatorIntl();\r\n intl.itemsPerPageLabel = 'Записей на странице';\r\n intl.firstPageLabel = 'Первая страница';\r\n intl.previousPageLabel = 'Предыдущая страница';\r\n intl.nextPageLabel = 'Следующая страница';\r\n intl.lastPageLabel = 'Последняя страница';\r\n return intl;\r\n}\r\n","import {\n Component,\n computed,\n effect,\n input,\n linkedSignal,\n output,\n untracked,\n viewChild,\n} from '@angular/core';\nimport { MatIconButton } from '@angular/material/button';\nimport { MatCheckbox } from '@angular/material/checkbox';\nimport { MatDivider } from '@angular/material/divider';\nimport { MatIcon } from '@angular/material/icon';\nimport {\n MatMenu,\n MatMenuContent,\n MatMenuItem,\n MatMenuTrigger,\n} from '@angular/material/menu';\nimport {\n MatPaginator,\n MatPaginatorIntl,\n MatPaginatorModule,\n PageEvent,\n} from '@angular/material/paginator';\nimport { MatSort, MatSortModule, Sort } from '@angular/material/sort';\nimport { MatTableDataSource, MatTableModule } from '@angular/material/table';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { RouterLink } from '@angular/router';\n\nimport { SignalSelectionModel } from '@kuzntsv/uikit';\nimport { BaseSchemaClass } from '../../base';\nimport { IColumnOptions } from './models/column-options.interface';\nimport { IContextMenuOptions } from './models/context-menu-options.interface';\nimport { PageState, SortState, TableState } from './models/table-state';\nimport { getRuPaginatorIntl } from './ru-paginator.intl';\n\n@Component({\n selector: 'ngx-uik-table',\n templateUrl: './table.component.html',\n styleUrls: ['./table.component.css'],\n imports: [\n MatTableModule, // Оптимизировано: импортируем модуль целиком вместо поштучных директив\n MatSortModule,\n MatPaginatorModule,\n MatCheckbox,\n MatIcon,\n RouterLink,\n MatMenuTrigger,\n MatMenu,\n MatMenuContent,\n MatDivider,\n MatMenuItem,\n MatTooltipModule,\n MatIconButton,\n ],\n providers: [{ provide: MatPaginatorIntl, useFactory: getRuPaginatorIntl }],\n})\nexport class TableComponent<T extends BaseSchemaClass> {\n /** Отображаемые данные. */\n data = input<T[]>([]);\n /** Количество записей. */\n length = input<number>(0);\n /** Настройки колонок. */\n columnOptions = input<IColumnOptions<T>[]>([]);\n /** Состояние сортировки, пагинации. */\n tableState = input.required<TableState>();\n /** Разрешен выбор нескольких строк. */\n allowMultiSelect = input<boolean>(false);\n /** Список элементов контекстного меню. */\n opt = input<IContextMenuOptions<T>[]>([]);\n /** Отправка события rowDoubleClicked (при двойном щелчке мышью) отключена. */\n rowDblClickedDisable = input<boolean>(false);\n /** Отображать строку с итогом. */\n footer = input<boolean>(false);\n\n /** Изменение страницы. */\n pageStateChange = output<PageState>();\n /** Изменение сортировки. */\n sortStateChange = output<SortState>();\n /** Изменение выбранных записей. */\n selectionChange = output<T[]>();\n /** Двойной щелчек ЛКМ*/\n rowDoubleClicked = output<T>();\n\n readonly sort = viewChild(MatSort);\n readonly paginator = viewChild(MatPaginator);\n readonly contextMenu = viewChild(MatMenuTrigger);\n\n pageState = linkedSignal<PageState>(() => {\n return {\n pageIndex: this.tableState().pageIndex,\n pageSize: this.tableState().pageSize,\n };\n });\n\n sortState = linkedSignal<SortState>(() => {\n return {\n sortActive: this.tableState().sortActive,\n sortDirection: this.tableState().sortDirection,\n };\n });\n\n /** Выбранная строка, для которого будет показываться меню при нажатии правой кнопки мыши. */\n itemForMenu?: T;\n /** Позиция в которой отображается контекстное меню. */\n contextMenuPosition = { x: '0px', y: '0px' };\n\n // eslint-disable-next-line no-magic-numbers\n readonly defaultPageIndex = 0;\n // eslint-disable-next-line no-magic-numbers\n readonly defaultPageSize = 10;\n\n /** Источник данных для отображения. */\n dataSource = new MatTableDataSource<T>();\n\n /** Выбранные записи. */\n // Инициализируем нашу кастомную модель выбора.\n // Использование computed позволяет пересоздавать модель только при изменении allowMultiSelect.\n selection = computed(() => {\n return new SignalSelectionModel<T>(\n this.allowMultiSelect(),\n [],\n (a, b) => a?.id === b?.id, // Сравнение по бизнес-ключу (id) для защиты при смене страниц\n );\n });\n\n /** Список отображаемых колонок (формируется из @columnOptions). */\n // 3. Вычисляемые сигналы (computed) для автоматического расчета колонок\n displayedColumns = computed<string[]>(() => {\n const cols =\n this.columnOptions()\n ?.filter((c) => !c.hide)\n .map((item) => item.name) || [];\n return ['select', ...cols];\n });\n\n // Оптимизированный подсчет итогов через computed\n totals = computed<Record<string, number | string>>(() => {\n const currentData = this.data();\n const options = this.columnOptions();\n const result: Record<string, number | string> = {};\n\n options.forEach((col) => {\n if (!col.footer) return;\n const values = currentData\n .map((t) => t[col.name as keyof T] as unknown)\n .filter((v): v is number => typeof v === 'number');\n\n result[col.name] = values.length\n ? values.reduce((acc, v) => acc + v, 0)\n : '';\n });\n\n return result;\n });\n\n constructor() {\n // 4. Декларативное связывание данных бэкенда с таблицей Angular Material\n effect(() => {\n // Ключевой момент: [...arr] создает новую ссылку, что заставляет MatTable перерисоваться при OnPush\n this.dataSource.data = [...this.data()];\n\n // Автоматическое сохранение выделения по ссылке (или по ID)\n const currentData = this.data();\n const model = this.selection();\n\n untracked(() => {\n // Находим элементы на новой странице, которые соответствуют ранее выбранным ID\n const nextSelected = currentData.filter((item) =>\n model.isSelected(item),\n );\n\n // Синхронизируем состояние модели без зацикливания эффекта\n if (nextSelected.length > 0) {\n model.select(...nextSelected);\n }\n });\n });\n\n // Эффект для уведомления родительского компонента об изменении выделения\n effect(() => {\n const selectedArray = this.selection().selected();\n untracked(() => this.selectionChange.emit(selectedArray));\n });\n }\n\n onPageEvent(event: PageEvent) {\n const newState = { pageIndex: event.pageIndex, pageSize: event.pageSize };\n this.pageState.set(newState);\n this.pageStateChange.emit(newState);\n }\n\n onSortEvent(sort: Sort) {\n const newState = { sortActive: sort.active, sortDirection: sort.direction };\n this.sortState.set(newState);\n this.sortStateChange.emit(newState);\n }\n\n /** Whether the number of selected elements matches the total number of rows. */\n isAllSelected() {\n const pageRows = this.dataSource.data;\n if (pageRows.length === 0) return false;\n return pageRows.every((row) => this.selection().isSelected(row));\n }\n\n /** Selects all rows if they are not all selected; otherwise clear selection. */\n masterToggle() {\n if (this.isAllSelected()) {\n this.selection().clear();\n } else {\n this.selection().select(...this.dataSource.data);\n }\n }\n\n /** При щелчке по строке. */\n onRowClicked(row: T) {\n this.selection().toggle(row);\n }\n\n /** При двойном щелчке по строке. */\n onRowDblClicked(row: T) {\n // выделение строки при двойном щелчке по строке\n this.selection().clear();\n this.selection().select(row);\n if (!this.rowDblClickedDisable()) this.rowDoubleClicked.emit(row);\n }\n\n /** При вызове контекстного меню. */\n onContextMenu(event: MouseEvent, itemForMenu: T | undefined) {\n if (this.opt() && this.opt().length === 0) {\n // если нет пунктов меню, то не показываем меню\n return;\n }\n event.preventDefault();\n this.itemForMenu = itemForMenu;\n this.contextMenuPosition.x = event.clientX + 'px';\n this.contextMenuPosition.y = event.clientY + 'px';\n // как это (menuData) использовать в шаблоне не понятно, поэтому использую this.itemForMenu\n // https://www.concretepage.com/angular-material/passing-data-to-mat-menu-angular-material\n const contextMenu = this.contextMenu();\n if (contextMenu) {\n contextMenu.menuData = { itemForMenu };\n contextMenu.menu?.focusFirstItem('mouse');\n contextMenu.openMenu();\n }\n }\n}\n","<div class=\"component-container\">\r\n <div class=\"table-container\">\r\n <table\r\n mat-table\r\n [dataSource]=\"dataSource\"\r\n matSort\r\n [matSortActive]=\"sortState().sortActive\"\r\n [matSortDirection]=\"sortState().sortDirection\"\r\n (matSortChange)=\"onSortEvent($event)\"\r\n matSortDisableClear\r\n >\r\n <!-- Выбор строки Column -->\r\n <ng-container matColumnDef=\"select\">\r\n <th mat-header-cell *matHeaderCellDef>\r\n @if (allowMultiSelect()) {\r\n <mat-checkbox\r\n (change)=\"$event ? masterToggle() : null\"\r\n [checked]=\"selection().hasValue() && isAllSelected()\"\r\n [indeterminate]=\"selection().hasValue() && !isAllSelected()\"\r\n >\r\n </mat-checkbox>\r\n }\r\n </th>\r\n <td mat-cell *matCellDef=\"let row\">\r\n <mat-checkbox\r\n (click)=\"$event.stopPropagation()\"\r\n (change)=\"$event ? onRowClicked(row) : null\"\r\n [checked]=\"selection().isSelected(row)\"\r\n >\r\n </mat-checkbox>\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n }\r\n </ng-container>\r\n\r\n @for (item of columnOptions(); track item.name) {\r\n <ng-container [matColumnDef]=\"item.name\">\r\n <th\r\n mat-header-cell\r\n *matHeaderCellDef\r\n mat-sort-header\r\n [disabled]=\"item.titleSortDisable\"\r\n >\r\n {{ item.title }}\r\n </th>\r\n\r\n <td\r\n mat-cell\r\n *matCellDef=\"let element\"\r\n (contextmenu)=\"onContextMenu($event, element)\"\r\n [matTooltip]=\"item.tooltip ?? ''\"\r\n >\r\n @switch (item.format) {\r\n @case (\"pre-wrap\") {\r\n {{ element[item.name] }}\r\n }\r\n @case (\"link\") {\r\n <a [href]=\"element[item.name]\" target=\"_blank\">{{\r\n element[item.name]\r\n }}</a>\r\n }\r\n @case (\"linkIcon\") {\r\n @if (element[item.name]) {\r\n <a [href]=\"element[item.name]\" target=\"_blank\">\r\n @if (item.icon) {\r\n <mat-icon\r\n [class]=\"item.classList ? item.classList : ''\"\r\n >{{ item.icon }}</mat-icon\r\n >\r\n }\r\n @if (item.symbol) {\r\n <span [class]=\"item.classList ? item.classList : ''\">{{\r\n item.symbol\r\n }}</span>\r\n }\r\n </a>\r\n }\r\n }\r\n @case (\"routerLink\") {\r\n <a [routerLink]=\"[element[item.name]]\">{{\r\n element[item.name]\r\n }}</a>\r\n }\r\n @case (\"routerLinkIcon\") {\r\n @if (element[item.name]) {\r\n <a [routerLink]=\"[element[item.name]]\">\r\n @if (item.icon) {\r\n <mat-icon\r\n [class]=\"item.classList ? item.classList : ''\"\r\n >{{ item.icon }}</mat-icon\r\n >\r\n }\r\n @if (item.symbol) {\r\n <span [class]=\"item.classList ? item.classList : ''\">{{\r\n item.symbol\r\n }}</span>\r\n }\r\n </a>\r\n }\r\n }\r\n @case (\"checkbox\") {\r\n <mat-checkbox\r\n [checked]=\"element[item.name] === 1\"\r\n [disabled]=\"true\"\r\n ></mat-checkbox>\r\n }\r\n @case (\"icon\") {\r\n @if (item.icon) {\r\n <mat-icon [class]=\"item.classList ? item.classList : ''\">{{\r\n item.icon\r\n }}</mat-icon>\r\n }\r\n @if (item.symbol) {\r\n <span [class]=\"item.classList ? item.classList : ''\">{{\r\n item.symbol\r\n }}</span>\r\n }\r\n }\r\n @case (\"icons\") {\r\n @if (item.icons) {\r\n <mat-icon\r\n [class]=\"\r\n item.classList ? item.classList[element[item.name]] : ''\r\n \"\r\n [matTooltip]=\"\r\n item.tooltips ? item.tooltips[element[item.name]] : ''\r\n \"\r\n >{{ item.icons[element[item.name]] }}</mat-icon\r\n >\r\n }\r\n @if (item.symbols) {\r\n <span\r\n [class]=\"\r\n item.classList ? item.classList[element[item.name]] : ''\r\n \"\r\n >{{ item.symbols[element[item.name]] }}</span\r\n >\r\n }\r\n }\r\n @case (\"actions\") {\r\n @if (item.actions) {\r\n <div class=\"actions-container\">\r\n @for (action of item.actions; track action) {\r\n @if (\r\n !(action.hideFn ? action.hideFn(element) : action.hide)\r\n ) {\r\n <button\r\n mat-icon-button\r\n (click)=\"\r\n action.onClickFn ? action.onClickFn(element) : ''\r\n \"\r\n (mousedown)=\"\r\n action.onClickMiddleFn\r\n ? action.onClickMiddleFn($event, element)\r\n : ''\r\n \"\r\n [disabled]=\"\r\n action.disabledFn\r\n ? action.disabledFn(element)\r\n : action.disabled\r\n \"\r\n [matTooltip]=\"action.tooltip ? action.tooltip : ''\"\r\n >\r\n @if (action.icon) {\r\n <mat-icon\r\n [class]=\"action.classList ? action.classList : ''\"\r\n >{{ action.icon }}</mat-icon\r\n >\r\n }\r\n @if (action.symbol) {\r\n <span\r\n [class]=\"action.classList ? action.classList : ''\"\r\n >{{ action.symbol }}</span\r\n >\r\n }\r\n {{ action.title }}\r\n </button>\r\n }\r\n }\r\n </div>\r\n }\r\n }\r\n @case (\"image\") {\r\n @if (element[item.name]) {\r\n <img\r\n [src]=\"element[item.name]\"\r\n [alt]=\"\r\n item.imageAlt && element[item.imageAlt]\r\n ? element[item.imageAlt]\r\n : ''\r\n \"\r\n [class]=\"item.classList ? item.classList : ''\"\r\n />\r\n }\r\n }\r\n @default {\r\n {{ element[item.name] }}\r\n }\r\n }\r\n </td>\r\n\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (footer()) {\r\n @if (!item.format && item.footer) {\r\n <strong>{{ totals()[item.name] }}</strong>\r\n }\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n\r\n <tr class=\"mat-row\" *matNoDataRow>\r\n <td class=\"mat-cell\" colspan=\"9999\">Нет данных для отображения</td>\r\n </tr>\r\n\r\n <tr\r\n mat-header-row\r\n *matHeaderRowDef=\"displayedColumns(); sticky: true\"\r\n ></tr>\r\n <tr\r\n mat-row\r\n *matRowDef=\"let row; columns: displayedColumns()\"\r\n (click)=\"onRowClicked(row)\"\r\n (dblclick)=\"onRowDblClicked(row)\"\r\n class=\"element-row\"\r\n [class.selected-row]=\"selection().isSelected(row)\"\r\n ></tr>\r\n @if (footer()) {\r\n <tr\r\n mat-footer-row\r\n *matFooterRowDef=\"displayedColumns(); sticky: true\"\r\n ></tr>\r\n }\r\n </table>\r\n <div\r\n style=\"visibility: hidden; position: fixed\"\r\n [style.left]=\"contextMenuPosition.x\"\r\n [style.top]=\"contextMenuPosition.y\"\r\n [matMenuTriggerFor]=\"contextMenu\"\r\n #menuTrigger=\"matMenuTrigger\"\r\n ></div>\r\n <mat-menu #contextMenu=\"matMenu\">\r\n <ng-template matMenuContent let-id=\"id\">\r\n @for (menuItem of opt(); track menuItem) {\r\n @if (\r\n menuItem.title === \"-\" &&\r\n !(menuItem.hideFn ? menuItem.hideFn(itemForMenu) : menuItem.hide)\r\n ) {\r\n <mat-divider></mat-divider>\r\n }\r\n @if (\r\n menuItem.title !== \"-\" &&\r\n !(menuItem.hideFn ? menuItem.hideFn(itemForMenu) : menuItem.hide)\r\n ) {\r\n <button\r\n mat-menu-item\r\n (click)=\"\r\n menuItem.onClickFn ? menuItem.onClickFn(itemForMenu) : ''\r\n \"\r\n (mousedown)=\"\r\n menuItem.onClickMiddleFn\r\n ? menuItem.onClickMiddleFn($event, itemForMenu, menuTrigger)\r\n : ''\r\n \"\r\n [disabled]=\"\r\n menuItem.disabledFn\r\n ? menuItem.disabledFn(itemForMenu)\r\n : menuItem.disabled\r\n \"\r\n >\r\n @if (menuItem.icon) {\r\n <mat-icon\r\n [class]=\"menuItem.classList ? menuItem.classList : ''\"\r\n >{{ menuItem.icon }}</mat-icon\r\n >\r\n }\r\n @if (menuItem.symbol) {\r\n <span [class]=\"menuItem.classList ? menuItem.classList : ''\">{{\r\n menuItem.symbol\r\n }}</span>\r\n }\r\n {{ menuItem.title }}\r\n </button>\r\n }\r\n }\r\n </ng-template>\r\n </mat-menu>\r\n </div>\r\n\r\n <mat-paginator\r\n [length]=\"length()\"\r\n [pageIndex]=\"pageState().pageIndex || defaultPageIndex\"\r\n [pageSizeOptions]=\"[5, 10, 20, 50, 100]\"\r\n [pageSize]=\"pageState().pageSize || defaultPageSize\"\r\n (page)=\"onPageEvent($event)\"\r\n showFirstLastButtons\r\n itemsPerPageLabel=\"\"\r\n ></mat-paginator>\r\n</div>\r\n","import { HttpErrorResponse, HttpHeaders } from '@angular/common/http';\r\nimport { SchemaPath, validateHttp } from '@angular/forms/signals';\r\nimport { X_SKIP_LOADER, X_SKIP_NOTIFICATION } from '@kuzntsv/uikit';\r\n\r\ninterface UniqueCodeOptions {\r\n endpoint: string;\r\n errorMessage: string;\r\n useEquals?: boolean;\r\n}\r\n\r\nexport function uniqueCodeValidator(\r\n field: SchemaPath<number | null>,\r\n formSchema: any,\r\n options: UniqueCodeOptions,\r\n) {\r\n validateHttp(field, {\r\n debounce: 500,\r\n\r\n // Конфигурируем запрос через объект\r\n request: ({ value }) => {\r\n const code = value();\r\n if (code === null || code === undefined) return undefined;\r\n\r\n const divider = options.useEquals ? '=' : '/';\r\n return {\r\n url: `${options.endpoint}${divider}${encodeURIComponent(code)}`,\r\n method: 'GET',\r\n headers: new HttpHeaders({\r\n [X_SKIP_NOTIFICATION]: 'true',\r\n [X_SKIP_LOADER]: 'true'\r\n }),\r\n };\r\n },\r\n onSuccess: (\r\n foundEntity: { id: number; code: number } | null,\r\n { value, valueOf },\r\n ) => {\r\n // Объект с таким кодом не найден — имя уникально\r\n if (!foundEntity) return null;\r\n\r\n const currentId = valueOf(formSchema.id);\r\n const currentCode = value() || 0;\r\n\r\n // Если код совпал, но это та же самая запись, которую мы редактируем — всё ок.\r\n // Если ID разные — код занят.\r\n const isUnique =\r\n currentId === foundEntity.id ||\r\n (currentId !== foundEntity.id && currentCode !== foundEntity.code);\r\n return isUnique\r\n ? null\r\n : { kind: 'uniqueCode', message: options.errorMessage };\r\n },\r\n onError: (error: unknown) => {\r\n // Если прилетел 404 статус — это наш \"успех\" (записи нет, имя уникально)\r\n if (error instanceof HttpErrorResponse && error.status === 404)\r\n return null;\r\n console.error(`Ошибка валидации кода на ${options.endpoint}:`, error);\r\n return {\r\n kind: 'serverError',\r\n message: 'Не удалось проверить код на сервере',\r\n };\r\n },\r\n });\r\n}\r\n","import { HttpErrorResponse, HttpHeaders } from '@angular/common/http';\r\nimport { SchemaPath, validateHttp } from '@angular/forms/signals';\r\nimport { X_SKIP_LOADER, X_SKIP_NOTIFICATION } from '@kuzntsv/uikit';\r\n\r\ninterface UniqueNameOptions {\r\n endpoint: string;\r\n errorMessage: string;\r\n useEquals?: boolean;\r\n}\r\n\r\nexport function uniqueNameValidator(\r\n field: SchemaPath<string>,\r\n formSchema: any,\r\n options: UniqueNameOptions,\r\n) {\r\n validateHttp(field, {\r\n debounce: 500,\r\n\r\n // Конфигурируем запрос через объект\r\n request: ({ value }) => {\r\n const name = (value() || '').trim();\r\n if (!name) return undefined;\r\n\r\n const divider = options.useEquals ? '=' : '/';\r\n return {\r\n url: `${options.endpoint}${divider}${encodeURIComponent(name)}`,\r\n method: 'GET',\r\n headers: new HttpHeaders({\r\n [X_SKIP_NOTIFICATION]: 'true',\r\n [X_SKIP_LOADER]: 'true'\r\n }),\r\n };\r\n },\r\n onSuccess: (\r\n foundEntity: { id: number; name: string } | null,\r\n { value, valueOf },\r\n ) => {\r\n // Объект с таким именем не найден — имя уникально\r\n if (!foundEntity) return null;\r\n\r\n const currentId = valueOf(formSchema.id);\r\n const currentName = (value() || '').trim();\r\n\r\n // Если имя совпало, но это та же самая запись, которую мы редактируем — всё ок.\r\n // Если ID разные — имя занято.\r\n const isUnique =\r\n currentId === foundEntity.id ||\r\n (currentId !== foundEntity.id &&\r\n currentName.toUpperCase() !== foundEntity.name.toUpperCase());\r\n return isUnique\r\n ? null\r\n : { kind: 'uniqueName', message: options.errorMessage };\r\n },\r\n onError: (error: unknown) => {\r\n // Если прилетел 404 статус — это наш \"успех\" (записи нет, имя уникально)\r\n if (error instanceof HttpErrorResponse && error.status === 404)\r\n return null;\r\n console.error(`Ошибка валидации имени на ${options.endpoint}:`, error);\r\n return {\r\n kind: 'serverError',\r\n message: 'Не удалось проверить имя на сервере',\r\n };\r\n },\r\n });\r\n}\r\n"],"mappings":"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"}