@kuzntsv/uikit 0.21.37 → 1.0.2

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,153 +1,79 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, ChangeDetectorRef, ChangeDetectionStrategy, Component, Injectable, input, output, effect, viewChild, HostListener, ElementRef, Directive, signal, NgZone, Input, Pipe, linkedSignal } from '@angular/core';
3
- import { Router, DefaultUrlSerializer, ActivatedRoute, RouterLink } from '@angular/router';
4
- import { Overlay } from '@angular/cdk/overlay';
5
- import { ComponentPortal } from '@angular/cdk/portal';
6
- import { MatProgressSpinner } from '@angular/material/progress-spinner';
7
- import { HttpHeaders, HttpClient, HttpParams } from '@angular/common/http';
8
- import { BehaviorSubject, Subscription, ReplaySubject, Subject, tap, switchMap, map as map$1, forkJoin, startWith } from 'rxjs';
2
+ import { InjectionToken, Injectable, inject, signal, DestroyRef } from '@angular/core';
3
+ import { HttpContextToken, HttpHeaders, HttpClient } from '@angular/common/http';
4
+ import { Subject } from 'rxjs';
5
+ import { UIKIT_CONFIG as UIKIT_CONFIG$1 } from 'src/config';
6
+ import { Router } from '@angular/router';
7
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
8
+ import { UIKIT_NOTIFICATION_TOKEN as UIKIT_NOTIFICATION_TOKEN$1 } from 'src/models';
9
9
  import { MatSnackBar } from '@angular/material/snack-bar';
10
- import * as i1 from '@angular/forms';
11
- import { FormGroup, FormControl, Validators, FormsModule, ReactiveFormsModule, NgControl } from '@angular/forms';
12
- import { MatButton, MatIconButton, MatAnchor } from '@angular/material/button';
13
- import { MatCard, MatCardHeader, MatCardTitle, MatCardContent } from '@angular/material/card';
14
- import { MatFormField, MatLabel, MatError, MatSuffix, MatHint } from '@angular/material/form-field';
15
- import { MatIcon } from '@angular/material/icon';
16
- import { MatInput } from '@angular/material/input';
17
- import { map, debounceTime, distinctUntilChanged, startWith as startWith$1 } from 'rxjs/operators';
18
- import { MatDivider } from '@angular/material/divider';
19
- import { MatMenu, MatMenuTrigger, MatMenuItem, MatMenuContent } from '@angular/material/menu';
20
- import { MatToolbar } from '@angular/material/toolbar';
21
- import * as i1$1 from '@angular/material/tooltip';
22
- import { MatTooltip, MatTooltipModule } from '@angular/material/tooltip';
23
- import { MAT_DIALOG_DATA, MatDialogRef, MatDialogTitle, MatDialogContent, MatDialogActions, MatDialogClose, MatDialog, MatDialogConfig } from '@angular/material/dialog';
24
- import { DomSanitizer } from '@angular/platform-browser';
25
- import { ENTER, COMMA } from '@angular/cdk/keycodes';
26
- import { AsyncPipe } from '@angular/common';
27
- import * as i2 from '@angular/material/autocomplete';
28
- import { MatAutocompleteModule, MatOption } from '@angular/material/autocomplete';
29
- import * as i3 from '@angular/material/chips';
30
- import { MatChipsModule } from '@angular/material/chips';
31
- import { MAT_DATE_LOCALE, MAT_DATE_FORMATS, MatOption as MatOption$1, MatOptgroup } from '@angular/material/core';
32
- import { MatDateRangeInput, MatStartDate, MatEndDate, MatDatepickerToggle, MatDateRangePicker } from '@angular/material/datepicker';
33
- import 'moment/locale/ru';
34
- import moment from 'moment';
35
- import * as i3$1 from '@angular/cdk/scrolling';
36
- import { ScrollingModule } from '@angular/cdk/scrolling';
37
- import { MatSelect, MatFormField as MatFormField$1, MatLabel as MatLabel$1 } from '@angular/material/select';
38
- import { SelectionModel } from '@angular/cdk/collections';
39
- import { MatCheckbox } from '@angular/material/checkbox';
40
- import { MatPaginator } from '@angular/material/paginator';
41
- import { MatSort, MatSortHeader } from '@angular/material/sort';
42
- import { MatTableDataSource, MatTable, MatColumnDef, MatHeaderCellDef, MatHeaderCell, MatCellDef, MatCell, MatNoDataRow, MatHeaderRowDef, MatHeaderRow, MatRowDef, MatRow, MatFooterRowDef, MatFooterRow, MatFooterCellDef, MatFooterCell, MatTableModule } from '@angular/material/table';
43
10
 
44
- class ProgressSpinnerComponent {
45
- cdRef = inject(ChangeDetectorRef);
46
- ngAfterViewInit() {
47
- this.cdRef.detectChanges();
48
- }
49
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ProgressSpinnerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
50
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.0", type: ProgressSpinnerComponent, isStandalone: true, selector: "ngx-uik-loader", ngImport: i0, template: `
51
- <div class="loading-indicator" mat-dialog-content>
52
- <mat-progress-spinner mode="indeterminate">
53
- </mat-progress-spinner>
54
- </div>
55
- `, isInline: true, styles: [".loading-indicator{position:fixed;z-index:999;height:2em;width:2em;overflow:initial;margin:auto;inset:0}.loading-indicator:before{content:\"\";display:block;position:fixed;top:0;left:0;width:100%;height:100%;background-color:#0000004d}\n"], dependencies: [{ kind: "component", type: MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
56
- }
57
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ProgressSpinnerComponent, decorators: [{
58
- type: Component,
59
- args: [{ selector: 'ngx-uik-loader', template: `
60
- <div class="loading-indicator" mat-dialog-content>
61
- <mat-progress-spinner mode="indeterminate">
62
- </mat-progress-spinner>
63
- </div>
64
- `, changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatProgressSpinner], styles: [".loading-indicator{position:fixed;z-index:999;height:2em;width:2em;overflow:initial;margin:auto;inset:0}.loading-indicator:before{content:\"\";display:block;position:fixed;top:0;left:0;width:100%;height:100%;background-color:#0000004d}\n"] }]
65
- }] });
11
+ const UIKIT_CONFIG = new InjectionToken('UIKIT_CONFIG');
66
12
 
67
- class LoaderService {
68
- overlayRef = null;
69
- overlay = inject(Overlay);
70
- show() {
71
- if (!this.overlayRef) {
72
- this.overlayRef = this.overlay.create();
73
- }
74
- const spinnerOverlayPortal = new ComponentPortal(ProgressSpinnerComponent);
75
- // Иправление ошибки Expression has changed after it was checked
76
- setTimeout(() => {
77
- if (!this.overlayRef?.hasAttached()) {
78
- this.overlayRef?.attach(spinnerOverlayPortal);
79
- }
80
- });
81
- }
82
- hide() {
83
- if (this.overlayRef) {
84
- this.overlayRef.detach();
85
- }
86
- }
87
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: LoaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
88
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: LoaderService, providedIn: 'root' });
89
- }
90
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: LoaderService, decorators: [{
91
- type: Injectable,
92
- args: [{
93
- providedIn: 'root'
94
- }]
95
- }] });
13
+ // Токен, в который мы будем передавать строку-идентификатор нужного API
14
+ // По умолчанию пустая строка означает "использовать дефолтное (основное) API"
15
+ const API_NAME = new HttpContextToken(() => '');
16
+ // Иногда внутри сервиса нужно сделать один специфический запрос (например, стянуть публичный JSON-файл конфигурации), не добавляя его глобально в publicUrls.
17
+ // Используя подход с HttpContext, мы можем добавить в библиотеку маркер пропуска авторизации:
18
+ // А в коде приложения вызывать так:
19
+ // this.http.get('/assets/config.json', {
20
+ // context: new HttpContext().set(BYPASS_AUTH, true)
21
+ // });
22
+ const BYPASS_AUTH = new HttpContextToken(() => false);
96
23
 
97
- // Сервис для вывода сообщений(ошибки, успеха)
98
- class AlertService {
99
- // eslint-disable-next-line no-magic-numbers
100
- duration = 5000;
101
- _snackBar = inject(MatSnackBar);
102
- openSnackBar(message, action, duration = this.duration) {
103
- this._snackBar.open(message, action, {
104
- duration,
105
- panelClass: ['red-snackbar'],
106
- });
107
- }
108
- success(message, duration = this.duration) {
109
- this.openSnackBar(message, 'Закрыть', duration);
110
- }
111
- info(message, duration = this.duration) {
112
- this.openSnackBar(message, 'Закрыть', duration);
113
- }
114
- helper(message, duration = this.duration) {
115
- this.openSnackBar(message, 'Закрыть', duration);
116
- }
117
- warning(message, duration = this.duration) {
118
- this.openSnackBar(message, 'Закрыть', duration);
119
- }
120
- error(message, duration = this.duration) {
121
- this.openSnackBar(message, 'Закрыть', duration);
24
+ ;
25
+
26
+ const UIKIT_NOTIFICATION_TOKEN = new InjectionToken('UikitNotificationToken');
27
+
28
+ class AuthEventService {
29
+ authErrorSource = new Subject();
30
+ // Стрим для прослушивания ошибок (экспортируется наружу)
31
+ authError$ = this.authErrorSource.asObservable();
32
+ // Метод для генерации события (вызовется в интерцепторе)
33
+ notify401() {
34
+ this.authErrorSource.next();
122
35
  }
123
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: AlertService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
124
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: AlertService, providedIn: 'root' });
36
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: AuthEventService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
37
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: AuthEventService, providedIn: 'root' });
125
38
  }
126
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: AlertService, decorators: [{
39
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: AuthEventService, decorators: [{
127
40
  type: Injectable,
128
- args: [{
129
- providedIn: 'root'
130
- }]
41
+ args: [{ providedIn: 'root' }]
131
42
  }] });
132
43
 
133
- class Environment {
134
- }
135
-
136
- class LogService {
137
- logPrefix = '';
138
- env = inject(Environment);
139
- log(...args) {
140
- if (!this.env.production) {
141
- // Prepend log prefix log string
142
- args.unshift(this.logPrefix + ' ');
143
- // Pass along arguments to console.log
144
- console.log(args.join(' '));
44
+ class RoleService {
45
+ // Вычисление разрешений по ролям
46
+ // Роль для скрытия элементов.
47
+ hideRole = 'HIDE';
48
+ /** Проверка массива ролей */
49
+ hasRoles(roles, checkRoles) {
50
+ if (roles) {
51
+ for (const checkRole of checkRoles) {
52
+ if (roles.find(role => (role === checkRole || role === 'ADMIN'))) {
53
+ return true;
54
+ }
55
+ }
56
+ }
57
+ return false;
58
+ }
59
+ /** Элемент скрывается, если у пользователя нет ни одной роли из перереданных в "roles"
60
+ или в списке "roles" есть роль "hideRole". */
61
+ isHideElement(roles, checkRoles) {
62
+ if (!roles || roles.length === 0)
63
+ return false;
64
+ if (roles.indexOf(this.hideRole) !== -1)
65
+ return true;
66
+ for (const role of roles) {
67
+ if (role && (role.length !== 0) && this.hasRoles(checkRoles, [role])) {
68
+ return false;
69
+ }
145
70
  }
71
+ return true;
146
72
  }
147
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: LogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
148
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: LogService, providedIn: 'root' });
73
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: RoleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
74
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: RoleService, providedIn: 'root' });
149
75
  }
150
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: LogService, decorators: [{
76
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: RoleService, decorators: [{
151
77
  type: Injectable,
152
78
  args: [{
153
79
  providedIn: 'root'
@@ -181,13 +107,10 @@ class User {
181
107
  */
182
108
  class UserService {
183
109
  user;
110
+ config = inject(UIKIT_CONFIG$1);
184
111
  constructor() {
185
- if (localStorage.getItem('sed_currentUser')) {
186
- this.user = JSON.parse(localStorage.getItem('sed_currentUser') || '');
187
- }
188
- else {
189
- this.user = new User();
190
- }
112
+ const saved = localStorage.getItem(this.config.auth.userStorageKey);
113
+ this.user = saved ? JSON.parse(saved) : new User();
191
114
  }
192
115
  get dept() {
193
116
  return this.user?.depart;
@@ -198,12 +121,12 @@ class UserService {
198
121
  }
199
122
  /** Изменить данные пользователя в localStorage */
200
123
  set userData(user) {
201
- localStorage.setItem('sed_currentUser', JSON.stringify(user));
202
- this.user = JSON.parse(localStorage.getItem('sed_currentUser') || '');
124
+ this.user = user;
125
+ localStorage.setItem(this.config.auth.userStorageKey, JSON.stringify(user));
203
126
  }
204
127
  /** Удаляет данные о пользователе из localStorage. */
205
128
  removeUser() {
206
- localStorage.removeItem('sed_currentUser');
129
+ localStorage.removeItem(this.config.auth.userStorageKey);
207
130
  }
208
131
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: UserService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
209
132
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: UserService, providedIn: 'root' });
@@ -215,192 +138,117 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
215
138
  }]
216
139
  }], ctorParameters: () => [] });
217
140
 
218
- // Сервис авторизации
141
+ // interface RefreshResponse {
142
+ // accessToken: string;
143
+ // refreshToken: string;
144
+ // }
219
145
  class AuthService {
220
- // Указываем какой сервер использовать
221
- baseRoute = 'mainApi/';
222
- // Хранит доступные пользователю действия
223
- permissions = ['VIEW'];
224
- defaultRoles = [];
225
146
  // Хранит роли пользователя
226
- roles$;
227
- loggedIn$;
228
- // Роль для скрытия элементов.
229
- hideRole = 'HIDE';
230
- // Объект, хранящий статус авторизации
147
+ _roles = signal([], ...(ngDevMode ? [{ debugName: "_roles" }] : []));
148
+ // Состояние авторизации
149
+ _loggedIn = signal(false, ...(ngDevMode ? [{ debugName: "_loggedIn" }] : []));
150
+ roles = this._roles.asReadonly();
151
+ loggedIn = this._loggedIn.asReadonly();
231
152
  defaultHeader = {
232
- headers: new HttpHeaders().set('content-type', 'application/x-www-form-urlencoded')
153
+ headers: new HttpHeaders().set('content-type', 'application/x-www-form-urlencoded'),
233
154
  };
234
- idHuman;
235
- http = inject(HttpClient);
236
- router = inject(Router);
237
- console = inject(LogService);
238
- alertService = inject(AlertService);
155
+ notificationService = inject(UIKIT_NOTIFICATION_TOKEN$1);
239
156
  userService = inject(UserService);
157
+ eventService = inject(AuthEventService);
158
+ destroyRef = inject(DestroyRef);
159
+ http = inject(HttpClient);
160
+ config = inject(UIKIT_CONFIG$1);
161
+ // Внедряем роутер опционально, чтобы библиотека не падала, если роутера нет в приложении
162
+ router = inject(Router, { optional: true });
240
163
  constructor() {
241
- this.console.logPrefix = 'Auth Service';
242
- this.idHuman = localStorage.getItem('id_human');
243
- if (this.userService.userData?.roleList) {
244
- this.roles$ = new BehaviorSubject(this.userService.userData?.roleList);
245
- }
246
- else {
247
- this.roles$ = new BehaviorSubject(this.defaultRoles);
248
- }
249
- this.loggedIn$ = new BehaviorSubject((!!this.userService.userData && !!this.userService.userData.token));
250
- }
251
- /** Проверка разрешений */
252
- hasPermission(authPermission) {
253
- return !!(this.permissions &&
254
- this.permissions.find(permission => permission === authPermission));
255
- }
256
- /** Проверка ролей */
257
- hasRole(roles, checkRole) {
258
- if (roles) {
259
- return !!roles.find(role => (role === checkRole || role === 'ADMIN'));
260
- }
261
- else {
262
- return false;
263
- }
264
- }
265
- /** Проверка массива ролей */
266
- hasRoles(roles, checkRoles) {
267
- if (roles) {
268
- for (const checkRole of checkRoles) {
269
- if (roles.find(role => (role === checkRole || role === 'ADMIN'))) {
270
- return true;
271
- }
272
- }
273
- }
274
- return false;
275
- }
276
- /** Элемент скрывается, если у пользователя нет ни одной роли из перереданных в "roles"
277
- или в списке "roles" есть роль "hideRole". */
278
- isHideElement(roles, checkRoles) {
279
- if (!roles || roles.length === 0)
280
- return false;
281
- if (roles.indexOf(this.hideRole) !== -1)
282
- return true;
283
- for (const role of roles) {
284
- if (role && (role.length !== 0) && this.hasRole(checkRoles, role)) {
285
- return false;
286
- }
287
- }
288
- return true;
164
+ if (this.userService.userData?.roleList)
165
+ this._roles.set(this.userService.userData?.roleList);
166
+ this._loggedIn.set(!!this.userService.userData && !!this.userService.userData.token);
167
+ // Слушаем шину событий: если интерцептор поймал 401, сбрасываем сессию
168
+ this.eventService.authError$
169
+ .pipe(takeUntilDestroyed(this.destroyRef))
170
+ .subscribe(() => {
171
+ this.logout();
172
+ });
289
173
  }
290
- // /** Сменить роль без side эффекта */
291
- // public changeRole(role: string) {
292
- // this.roles$.next([role]);
293
- // }
294
- // /** Сменить роли без side эффекта */
295
- // public changeRoles(roles: string[]) {
296
- // this.roles$.next(roles);
297
- // }
298
174
  /** Запрос авторизации */
299
- login(username, password, idCas, returnUrl = '', onErrorFn) {
175
+ login(username, password, idCas, onErrorFn) {
300
176
  const passwordEncoded = encodeURIComponent(password);
301
177
  let body = `username=${username}&password=${passwordEncoded}`;
302
178
  if (idCas) {
303
179
  body += `&idcas=${idCas}`;
304
180
  }
305
- if (this.idHuman) {
306
- body += `&idhuman=${this.idHuman}`;
307
- }
308
- this.http.post(this.baseRoute + 'jwt', body, this.defaultHeader)
181
+ this.http
182
+ .post(this.config.auth.loginRoute + 'jwt', body, this.defaultHeader)
309
183
  .subscribe({
310
- next: data => {
311
- this.successLoginAction(data, returnUrl);
312
- this.alertService.success('Успешная авторизация');
184
+ next: (data) => {
185
+ this.successLoginAction(data);
186
+ this.notificationService.success('Успешная авторизация');
313
187
  },
314
188
  error: (error) => {
315
- this.console.log(error);
316
- this.alertService.error('Ошибка при авторизации: ' + error, 0);
189
+ console.log(error);
190
+ this.notificationService.error('Ошибка при авторизации: ' + error, 0);
317
191
  if (onErrorFn) {
318
192
  onErrorFn();
319
193
  }
320
- }
194
+ },
321
195
  });
322
196
  }
323
197
  /** Aвторизация по пропуску */
324
- loginByPermit(permit, idCas, returnUrl = '') {
198
+ loginByPermit(permit, idCas) {
325
199
  let body = `permit=${permit}`;
326
200
  if (idCas) {
327
201
  body += `&idcas=${idCas}`;
328
202
  }
329
- if (this.idHuman) {
330
- body += `&idhuman=${this.idHuman}`;
331
- }
332
- return this.http.post(this.baseRoute + 'jwt', body, this.defaultHeader)
203
+ return this.http
204
+ .post(this.config.auth.loginRoute + 'jwt', body, this.defaultHeader)
333
205
  .subscribe({
334
206
  next: (data) => {
335
- this.successLoginAction(data, returnUrl);
336
- this.alertService.success('Успешная авторизация');
207
+ this.successLoginAction(data);
208
+ this.notificationService.success('Успешная авторизация');
337
209
  },
338
210
  error: (error) => {
339
- this.console.log(error);
340
- this.alertService.error('Ошибка при авторизации: ' + error, 0);
341
- }
211
+ console.log(error);
212
+ this.notificationService.error('Ошибка при авторизации: ' + error, 0);
213
+ },
342
214
  });
343
215
  }
344
- /** Разлогиниться */
345
- logout(returnUrl = '') {
216
+ logout() {
346
217
  // Убирает(удаляет) пользователя из локального хранилища когда он разлогинивается
347
218
  this.userService.removeUser();
348
- // localStorage.removeItem('sed_currentUser');
349
- // Отправляем подписчикам события что человек вышел
350
- this.loggedIn$.next(false);
351
- // Переход на страницу авторизации
352
- if (returnUrl) {
353
- // указываем целевой маршрут в параметре
354
- this.router.navigate(['/login'], { queryParams: { returnUrl } }).then();
355
- }
356
- else {
357
- this.router.navigate(['/login']).then();
219
+ this._loggedIn.set(false);
220
+ // localStorage.removeItem(this.config.auth.userStorageKey);
221
+ // localStorage.removeItem(this.config.auth.refreshTokenStorageKey);
222
+ // ЛОГИКА СОХРАНЕНИЯ URL ПРИ РАЗЛОГИНЕ (Ваш улучшенный кусок кода)
223
+ if (this.router) {
224
+ const currentUrl = this.router.url;
225
+ // Проверяем, не находимся ли мы уже на странице логина, чтобы избежать зацикливания
226
+ if (currentUrl.includes(this.config.auth.loginRoute)) {
227
+ return;
228
+ }
229
+ // Безопасное формирование query-параметров через Router
230
+ this.router.navigate([this.config.auth.loginRoute], {
231
+ queryParams: { returnUrl: encodeURIComponent(currentUrl) },
232
+ });
358
233
  }
359
234
  }
360
- // Получить роли пользователя
361
- getRoles() {
362
- return this.http.get(this.baseRoute + 'jwt/webroles');
363
- }
364
- // /** Инициализация ролей */
365
- // private initRole() {
366
- // if (this.hasRole(this.roles$.getValue(), this.defaultRole)) {
367
- // this.roleService.getRoles().subscribe({
368
- // next: (data: string[]) => {
369
- // this.roles$.next(data['Roles']);
370
- // },
371
- // error: (error: any) => {
372
- // this.console.log(error);
373
- // this.alert.error('Ошибка при получении списка ролей пользователя: ' + error);
374
- // }
375
- // });
376
- // }
377
- // }
378
235
  /** При успешной авторизации */
379
- successLoginAction(user, returnUrl = '') {
236
+ successLoginAction(user) {
380
237
  this.userService.userData = user;
381
- this.loggedIn$.next(true);
382
- // init roles
383
- this.roles$.next(this.userService.userData.roleList);
384
- if (returnUrl) {
385
- const decodeUrl = decodeURIComponent(returnUrl);
386
- // указан целевой маршрут
387
- if (decodeUrl.includes('?')) {
388
- // есть параметры строки запроса
389
- const serializer = new DefaultUrlSerializer();
390
- // параметры строки запроса
391
- const params = serializer.parse(decodeUrl).queryParams;
392
- //console.log('successLoginAction params = ', params);
393
- // выделение маршрута
394
- const url = decodeUrl.slice(0, decodeUrl.indexOf('?'));
395
- this.router.navigate([url], { queryParams: params });
396
- }
397
- else {
398
- this.router.navigate([decodeUrl]);
399
- }
400
- }
401
- else {
402
- // не указан целевой маршрут, переход на главную
403
- this.router.navigate(['']);
238
+ this._loggedIn.set(true);
239
+ this._roles.set(this.userService.userData.roleList);
240
+ // ЛОГИКА ВОЗВРАТА ПОСЛЕ УСПЕШНОГО ЛОГИНА
241
+ if (this.router) {
242
+ // Извлекаем returnUrl из текущего query-параметра текущего маршрута
243
+ const currentUrlTree = this.router.parseUrl(this.router.url);
244
+ const returnUrl = currentUrlTree.queryParamMap.get('returnUrl');
245
+ if (returnUrl) {
246
+ // Декодируем и перенаправляем пользователя туда, где он был
247
+ this.router.navigateByUrl(decodeURIComponent(returnUrl));
248
+ return;
249
+ }
250
+ // Если returnUrl нет, идем на главную
251
+ this.router.navigate(['/']);
404
252
  }
405
253
  }
406
254
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: AuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
@@ -408,1849 +256,48 @@ class AuthService {
408
256
  }
409
257
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: AuthService, decorators: [{
410
258
  type: Injectable,
411
- args: [{
412
- providedIn: 'root'
413
- }]
414
- }], ctorParameters: () => [] });
415
-
416
- class LoginFormComponent {
417
- pending = input(false, ...(ngDevMode ? [{ debugName: "pending" }] : []));
418
- errorMessage = input('', ...(ngDevMode ? [{ debugName: "errorMessage" }] : []));
419
- submitted = output();
420
- hide = true;
421
- form = new FormGroup({
422
- username: new FormControl('', [Validators.required]),
423
- password: new FormControl('', [Validators.required]),
424
- });
425
- constructor() {
426
- effect(() => {
427
- if (this.pending()) {
428
- this.form.disable();
429
- }
430
- else {
431
- this.form.enable();
432
- }
433
- });
434
- }
435
- submit() {
436
- if (this.form.valid) {
437
- this.submitted.emit(this.form.value);
438
- }
439
- }
440
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: LoginFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
441
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: LoginFormComponent, isStandalone: true, selector: "ngx-uik-login-form", inputs: { pending: { classPropertyName: "pending", publicName: "pending", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { submitted: "submitted" }, ngImport: i0, template: "<mat-card appearance=\"outlined\">\r\n <mat-card-header>\r\n <mat-card-title>\r\n \u0410\u0432\u0442\u043E\u0440\u0438\u0437\u0430\u0446\u0438\u044F\r\n </mat-card-title>\r\n </mat-card-header>\r\n <mat-card-content>\r\n <form [formGroup]=\"form\" (ngSubmit)=\"submit()\">\r\n <p>\r\n <mat-form-field>\r\n <mat-label>\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F</mat-label>\r\n <input type=\"text\" pattern=\"[A-Za-z]{1,}.[A-Za-z]{1,}.[A-Za-z]*\"\r\n matInput\r\n autocomplete=\"on\"\r\n name=\"login-form-username\"\r\n placeholder=\"\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F\"\r\n formControlName=\"username\">\r\n @if (form.controls['username'].hasError('pattern')) {\r\n <mat-error>\r\n \u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u043C\u044B\u0439 \u0444\u043E\u0440\u043C\u0430\u0442 (\u041F\u0440\u0438\u043C\u0435\u0440: a.p.petrov)\r\n </mat-error>\r\n }\r\n @if (form.controls['username'].hasError('required')) {\r\n <mat-error>\r\n \u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u0437\u0430\u043F\u043E\u043B\u043D\u0438\u0442\u0435 \u044D\u0442\u043E \u043F\u043E\u043B\u0435\r\n </mat-error>\r\n }\r\n </mat-form-field>\r\n </p>\r\n\r\n <p>\r\n <mat-form-field>\r\n <mat-label>\u041F\u0430\u0440\u043E\u043B\u044C</mat-label>\r\n <input [type]=\"hide ? 'password' : 'text'\" matInput placeholder=\"\u041F\u0430\u0440\u043E\u043B\u044C\" formControlName=\"password\">\r\n <mat-icon class=\"watcher\" matSuffix (mousedown)=\"hide=false\" (mouseup)=\"hide=true\"\r\n >{{ hide ? 'visibility_off' : 'visibility'}}</mat-icon>\r\n @if (form.controls['password'].hasError('required')) {\r\n <mat-error>\r\n \u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u0437\u0430\u043F\u043E\u043B\u043D\u0438\u0442\u0435 \u044D\u0442\u043E \u043F\u043E\u043B\u0435\r\n </mat-error>\r\n }\r\n </mat-form-field>\r\n </p>\r\n\r\n @if (errorMessage()) {\r\n <p class=\"loginError\">\r\n {{ errorMessage() }}\r\n </p>\r\n }\r\n\r\n <p class=\"loginButtons\">\r\n <button type=\"submit\" mat-button mat-stroked-button color=\"primary\" [disabled]=\"pending()\">\u0412\u043E\u0439\u0442\u0438</button>\r\n </p>\r\n\r\n </form>\r\n </mat-card-content>\r\n </mat-card>\r\n", styles: [":host{display:flex;justify-content:center;margin:32px 0}.mat-mdc-form-field{width:100%;min-width:300px}mat-card-header{justify-content:center}mat-card-content{font-size:16px}.loginError{padding:16px;width:300px;color:#fff;background-color:red}.loginButtons{display:flex;flex-direction:row;justify-content:flex-end}.watcher{cursor:default}\n"], dependencies: [{ kind: "component", type: MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "component", type: MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "directive", type: MatCardContent, selector: "mat-card-content" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }] });
442
- }
443
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: LoginFormComponent, decorators: [{
444
- type: Component,
445
- args: [{ selector: 'ngx-uik-login-form', imports: [MatCard, MatCardHeader, MatCardTitle, MatCardContent, FormsModule, ReactiveFormsModule, MatFormField,
446
- MatLabel, MatInput, MatError, MatIcon, MatSuffix, MatButton], template: "<mat-card appearance=\"outlined\">\r\n <mat-card-header>\r\n <mat-card-title>\r\n \u0410\u0432\u0442\u043E\u0440\u0438\u0437\u0430\u0446\u0438\u044F\r\n </mat-card-title>\r\n </mat-card-header>\r\n <mat-card-content>\r\n <form [formGroup]=\"form\" (ngSubmit)=\"submit()\">\r\n <p>\r\n <mat-form-field>\r\n <mat-label>\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F</mat-label>\r\n <input type=\"text\" pattern=\"[A-Za-z]{1,}.[A-Za-z]{1,}.[A-Za-z]*\"\r\n matInput\r\n autocomplete=\"on\"\r\n name=\"login-form-username\"\r\n placeholder=\"\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F\"\r\n formControlName=\"username\">\r\n @if (form.controls['username'].hasError('pattern')) {\r\n <mat-error>\r\n \u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u043C\u044B\u0439 \u0444\u043E\u0440\u043C\u0430\u0442 (\u041F\u0440\u0438\u043C\u0435\u0440: a.p.petrov)\r\n </mat-error>\r\n }\r\n @if (form.controls['username'].hasError('required')) {\r\n <mat-error>\r\n \u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u0437\u0430\u043F\u043E\u043B\u043D\u0438\u0442\u0435 \u044D\u0442\u043E \u043F\u043E\u043B\u0435\r\n </mat-error>\r\n }\r\n </mat-form-field>\r\n </p>\r\n\r\n <p>\r\n <mat-form-field>\r\n <mat-label>\u041F\u0430\u0440\u043E\u043B\u044C</mat-label>\r\n <input [type]=\"hide ? 'password' : 'text'\" matInput placeholder=\"\u041F\u0430\u0440\u043E\u043B\u044C\" formControlName=\"password\">\r\n <mat-icon class=\"watcher\" matSuffix (mousedown)=\"hide=false\" (mouseup)=\"hide=true\"\r\n >{{ hide ? 'visibility_off' : 'visibility'}}</mat-icon>\r\n @if (form.controls['password'].hasError('required')) {\r\n <mat-error>\r\n \u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u0437\u0430\u043F\u043E\u043B\u043D\u0438\u0442\u0435 \u044D\u0442\u043E \u043F\u043E\u043B\u0435\r\n </mat-error>\r\n }\r\n </mat-form-field>\r\n </p>\r\n\r\n @if (errorMessage()) {\r\n <p class=\"loginError\">\r\n {{ errorMessage() }}\r\n </p>\r\n }\r\n\r\n <p class=\"loginButtons\">\r\n <button type=\"submit\" mat-button mat-stroked-button color=\"primary\" [disabled]=\"pending()\">\u0412\u043E\u0439\u0442\u0438</button>\r\n </p>\r\n\r\n </form>\r\n </mat-card-content>\r\n </mat-card>\r\n", styles: [":host{display:flex;justify-content:center;margin:32px 0}.mat-mdc-form-field{width:100%;min-width:300px}mat-card-header{justify-content:center}mat-card-content{font-size:16px}.loginError{padding:16px;width:300px;color:#fff;background-color:red}.loginButtons{display:flex;flex-direction:row;justify-content:flex-end}.watcher{cursor:default}\n"] }]
447
- }], ctorParameters: () => [], propDecorators: { pending: [{ type: i0.Input, args: [{ isSignal: true, alias: "pending", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], submitted: [{ type: i0.Output, args: ["submitted"] }] } });
448
-
449
- class PermitFormComponent {
450
- hidy = viewChild('hidy', ...(ngDevMode ? [{ debugName: "hidy" }] : []));
451
- submitted = output();
452
- mouseHandling(event) {
453
- this.hidy()?.nativeElement.focus();
454
- }
455
- ngOnInit() {
456
- // Обнуляем значение Input
457
- const hidy = this.hidy();
458
- if (hidy) {
459
- hidy.nativeElement.value = null;
460
- hidy.nativeElement.focus();
461
- }
462
- }
463
- /**
464
- * Поле ввода
465
- *
466
- * @param событие нажатия на клавишу
467
- */
468
- onKeydown(event) {
469
- if (event.key === 'Enter') {
470
- const permit = this.hidy()?.nativeElement.value;
471
- if (permit) {
472
- this.submitted.emit(permit);
473
- }
474
- }
475
- }
476
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: PermitFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
477
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.1.0", type: PermitFormComponent, isStandalone: true, selector: "ngx-uik-permit-form", outputs: { submitted: "submitted" }, host: { listeners: { "document:mouseup": "mouseHandling($event)" } }, viewQueries: [{ propertyName: "hidy", first: true, predicate: ["hidy"], descendants: true, isSignal: true }], ngImport: i0, template: "<mat-card appearance=\"outlined\">\r\n <mat-card-header>\r\n <mat-card-title>\r\n \u041F\u0440\u0438\u043B\u043E\u0436\u0438\u0442\u0435 \u043F\u0440\u043E\u043F\u0443\u0441\u043A\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)\"/>", styles: [":host{display:flex;justify-content:center;margin:32px 0}.mat-mdc-form-field{width:100%;min-width:300px}mat-card-title,mat-card-content{display:flex;justify-content:center}mat-card-content{font-size:16px}div.permit{border:none;width:300px;background-size:300px;height:180px}div.permit button div{margin-bottom:200px;color:#000;font-size:34px}input.hidy{opacity:0;position:absolute;left:-200px;top:-200px}\n"], dependencies: [{ kind: "component", type: MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "component", type: MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "directive", type: MatCardContent, selector: "mat-card-content" }] });
478
- }
479
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: PermitFormComponent, decorators: [{
480
- type: Component,
481
- args: [{ selector: 'ngx-uik-permit-form', imports: [MatCard, MatCardHeader, MatCardTitle, MatCardContent], template: "<mat-card appearance=\"outlined\">\r\n <mat-card-header>\r\n <mat-card-title>\r\n \u041F\u0440\u0438\u043B\u043E\u0436\u0438\u0442\u0435 \u043F\u0440\u043E\u043F\u0443\u0441\u043A\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)\"/>", styles: [":host{display:flex;justify-content:center;margin:32px 0}.mat-mdc-form-field{width:100%;min-width:300px}mat-card-title,mat-card-content{display:flex;justify-content:center}mat-card-content{font-size:16px}div.permit{border:none;width:300px;background-size:300px;height:180px}div.permit button div{margin-bottom:200px;color:#000;font-size:34px}input.hidy{opacity:0;position:absolute;left:-200px;top:-200px}\n"] }]
482
- }], propDecorators: { hidy: [{ type: i0.ViewChild, args: ['hidy', { isSignal: true }] }], submitted: [{ type: i0.Output, args: ["submitted"] }], mouseHandling: [{
483
- type: HostListener,
484
- args: ['document:mouseup', ['$event']]
485
- }] } });
486
-
487
- class LoginPageComponent {
488
- pending = false;
489
- error = '';
490
- isKiosk = false;
491
- /** Идентификатор АС */
492
- idCas = 0;
493
- /** Подписка на Идентификатор АС */
494
- sub;
495
- /** Url страницы, с которой был переход (после входа вернет на неё) */
496
- returnUrl = '';
497
- authService = inject(AuthService);
498
- route = inject(ActivatedRoute);
499
- loaderService = inject(LoaderService);
500
- constructor() {
501
- this.sub = this.route.data.subscribe(data => {
502
- this.idCas = data['idCas'];
503
- });
504
- }
505
- ngOnInit() {
506
- if (localStorage.getItem('id_human') || localStorage.getItem('kiosk-keyboard-layout')) {
507
- // this.isKiosk = true;
508
- }
509
- this.route.queryParams.subscribe(params => {
510
- this.returnUrl = params['returnUrl'];
511
- //console.log('constructor this.returnUrl = ', this.returnUrl);
512
- //this.returnUrl = this.returnUrl.slice(this.returnUrl.lastIndexOf('returnUrl=') + 'returnUrl='.length);
513
- //console.log('constructor NEW this.returnUrl = ', this.returnUrl);
514
- });
515
- }
516
- ngOnDestroy() {
517
- this.sub.unsubscribe();
518
- }
519
- onSubmitError() {
520
- return () => {
521
- this.pending = false;
522
- this.loaderService.hide();
523
- };
524
- }
525
- onSubmit($event) {
526
- this.loaderService.show();
527
- this.pending = true;
528
- this.authService.login($event.username, $event.password, this.idCas, this.returnUrl, this.onSubmitError());
529
- }
530
- onSubmitPermit($event) {
531
- const permit = $event;
532
- this.authService.loginByPermit(permit, this.idCas, this.returnUrl);
533
- }
534
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: LoginPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
535
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: LoginPageComponent, isStandalone: true, selector: "ngx-uik-login-page", ngImport: i0, template: "@if (!isKiosk) {\r\n <ngx-uik-login-form\r\n (submitted)=\"onSubmit($event)\"\r\n [pending]=\"pending\"\r\n [errorMessage]=\"error\">\r\n </ngx-uik-login-form>\r\n }\r\n @if (isKiosk) {\r\n <ngx-uik-permit-form\r\n (submitted)=\"onSubmitPermit($event)\"\r\n >\r\n </ngx-uik-permit-form>\r\n }", styles: [""], dependencies: [{ kind: "component", type: LoginFormComponent, selector: "ngx-uik-login-form", inputs: ["pending", "errorMessage"], outputs: ["submitted"] }, { kind: "component", type: PermitFormComponent, selector: "ngx-uik-permit-form", outputs: ["submitted"] }] });
536
- }
537
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: LoginPageComponent, decorators: [{
538
- type: Component,
539
- args: [{ selector: 'ngx-uik-login-page', imports: [LoginFormComponent, PermitFormComponent], template: "@if (!isKiosk) {\r\n <ngx-uik-login-form\r\n (submitted)=\"onSubmit($event)\"\r\n [pending]=\"pending\"\r\n [errorMessage]=\"error\">\r\n </ngx-uik-login-form>\r\n }\r\n @if (isKiosk) {\r\n <ngx-uik-permit-form\r\n (submitted)=\"onSubmitPermit($event)\"\r\n >\r\n </ngx-uik-permit-form>\r\n }" }]
259
+ args: [{ providedIn: 'root' }]
540
260
  }], ctorParameters: () => [] });
541
261
 
542
- class DisableIfUnauthorizedDirective {
543
- permission = input(undefined, { ...(ngDevMode ? { debugName: "permission" } : {}), alias: 'ngxUikDisableIfUnauthorized' });
544
- el = inject(ElementRef);
545
- authService = inject(AuthService);
546
- constructor() {
547
- effect(() => {
548
- if (this.permission() && !this.authService.hasPermission(this.permission())) {
549
- this.el.nativeElement.disabled = true;
550
- }
551
- });
552
- }
553
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: DisableIfUnauthorizedDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
554
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.0", type: DisableIfUnauthorizedDirective, isStandalone: true, selector: "[ngxUikDisableIfUnauthorized]", inputs: { permission: { classPropertyName: "permission", publicName: "ngxUikDisableIfUnauthorized", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
555
- }
556
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: DisableIfUnauthorizedDirective, decorators: [{
557
- type: Directive,
558
- args: [{
559
- selector: '[ngxUikDisableIfUnauthorized]',
560
- standalone: true
561
- }]
562
- }], ctorParameters: () => [], propDecorators: { permission: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngxUikDisableIfUnauthorized", required: false }] }] } });
563
-
564
- class HideIfUnauthorizedDirective {
565
- permission = input(undefined, { ...(ngDevMode ? { debugName: "permission" } : {}), alias: 'ngxUikHideIfUnauthorized' });
566
- el = inject(ElementRef);
567
- authService = inject(AuthService);
568
- ngOnInit() {
569
- if (this.permission() && !this.authService.hasPermission(this.permission())) {
570
- this.el.nativeElement.style.display = 'none';
571
- }
572
- }
573
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: HideIfUnauthorizedDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
574
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.0", type: HideIfUnauthorizedDirective, isStandalone: true, selector: "[ngxUikHideIfUnauthorized]", inputs: { permission: { classPropertyName: "permission", publicName: "ngxUikHideIfUnauthorized", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
575
- }
576
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: HideIfUnauthorizedDirective, decorators: [{
577
- type: Directive,
578
- args: [{
579
- selector: '[ngxUikHideIfUnauthorized]',
580
- standalone: true
581
- }]
582
- }], propDecorators: { permission: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngxUikHideIfUnauthorized", required: false }] }] } });
583
-
584
- class DisableIfRoleDirective {
585
- role = input('', { ...(ngDevMode ? { debugName: "role" } : {}), alias: 'ngxUikDisableIfRole' });
586
- userRoles = signal([], ...(ngDevMode ? [{ debugName: "userRoles" }] : []));
587
- el = inject(ElementRef);
588
- authService = inject(AuthService);
589
- constructor() {
590
- effect(() => {
591
- if (!this.authService.hasRole(this.userRoles(), this.role())) {
592
- this.el.nativeElement.disabled = true;
593
- }
594
- else {
595
- this.el.nativeElement.disabled = false;
596
- }
262
+ // Сервис для вывода сообщений(ошибки, успеха)
263
+ class NotificationService {
264
+ // eslint-disable-next-line no-magic-numbers
265
+ duration = 5000;
266
+ _snackBar = inject(MatSnackBar);
267
+ openSnackBar(message, action, duration = this.duration) {
268
+ this._snackBar.open(message, action, {
269
+ duration,
270
+ panelClass: ['red-snackbar'],
597
271
  });
598
272
  }
599
- ngOnInit() {
600
- if (this.role()) {
601
- this.authService.roles$.subscribe((userRoles) => {
602
- this.userRoles.set(userRoles);
603
- });
604
- }
605
- }
606
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: DisableIfRoleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
607
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.0", type: DisableIfRoleDirective, isStandalone: true, selector: "[ngxUikDisableIfRole]", inputs: { role: { classPropertyName: "role", publicName: "ngxUikDisableIfRole", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
608
- }
609
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: DisableIfRoleDirective, decorators: [{
610
- type: Directive,
611
- args: [{
612
- selector: '[ngxUikDisableIfRole]',
613
- standalone: true
614
- }]
615
- }], ctorParameters: () => [], propDecorators: { role: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngxUikDisableIfRole", required: false }] }] } });
616
-
617
- class HideIfRoleNotDirective {
618
- roles = input([], { ...(ngDevMode ? { debugName: "roles" } : {}), alias: 'ngxUikHideIfRoleNot' });
619
- userRoles = signal([], ...(ngDevMode ? [{ debugName: "userRoles" }] : []));
620
- el = inject(ElementRef);
621
- authService = inject(AuthService);
622
- constructor() {
623
- effect(() => {
624
- if (this.userRoles() && this.userRoles().length > 0) {
625
- // Элемент скрывается, если у пользователя нет ни одной роли из перереданных в "roles"
626
- // или в списке "roles" есть роль "hideRole".
627
- const isHide = this.authService.isHideElement(this.roles(), this.userRoles());
628
- if (isHide) {
629
- this.el.nativeElement.style.display = 'none';
630
- }
631
- else {
632
- this.el.nativeElement.style.display = 'inherit';
633
- }
634
- }
635
- });
273
+ success(message, duration = this.duration) {
274
+ this.openSnackBar(message, 'Закрыть', duration);
636
275
  }
637
- ngOnInit() {
638
- if (this.roles()) {
639
- this.authService.roles$.subscribe((userRoles) => {
640
- this.userRoles.set(userRoles);
641
- });
642
- }
276
+ info(message, duration = this.duration) {
277
+ this.openSnackBar(message, 'Закрыть', duration);
643
278
  }
644
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: HideIfRoleNotDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
645
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.0", type: HideIfRoleNotDirective, isStandalone: true, selector: "[ngxUikHideIfRoleNot]", inputs: { roles: { classPropertyName: "roles", publicName: "ngxUikHideIfRoleNot", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
646
- }
647
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: HideIfRoleNotDirective, decorators: [{
648
- type: Directive,
649
- args: [{
650
- selector: '[ngxUikHideIfRoleNot]',
651
- standalone: true
652
- }]
653
- }], ctorParameters: () => [], propDecorators: { roles: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngxUikHideIfRoleNot", required: false }] }] } });
654
-
655
- class AuthGuardService {
656
- auth = inject(AuthService);
657
- router = inject(Router);
658
- canActivate(route, state) {
659
- const isLogin = this.auth.loggedIn$.value;
660
- if (!isLogin) {
661
- console.log('state.url =', state.url);
662
- // Если не зарегистрирован вернуть в форму авторизации
663
- this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
664
- }
665
- return isLogin;
279
+ helper(message, duration = this.duration) {
280
+ this.openSnackBar(message, 'Закрыть', duration);
666
281
  }
667
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: AuthGuardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
668
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: AuthGuardService, providedIn: 'root' });
669
- }
670
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: AuthGuardService, decorators: [{
671
- type: Injectable,
672
- args: [{
673
- providedIn: 'root'
674
- }]
675
- }] });
676
- const authGuard = (route, state) => inject(AuthGuardService).canActivate(route, state);
677
-
678
- class RoleGuardService {
679
- roles = [];
680
- authService = inject(AuthService);
681
- router = inject(Router);
682
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
683
- canActivate(route, state) {
684
- this.roles = route.data['roles'];
685
- return this.authService.roles$.pipe(map((userRoles) => this.authService.hasRoles(userRoles, this.roles)));
282
+ warning(message, duration = this.duration) {
283
+ this.openSnackBar(message, 'Закрыть', duration);
686
284
  }
687
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: RoleGuardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
688
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: RoleGuardService, providedIn: 'root' });
689
- }
690
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: RoleGuardService, decorators: [{
691
- type: Injectable,
692
- args: [{
693
- providedIn: 'root'
694
- }]
695
- }] });
696
- const roleGuard = (route, state) => inject(RoleGuardService).canActivate(route, state);
697
-
698
- // Вычисление разрешений на модули по ролям
699
- class RoleService {
700
- // Указываем какой сервер использовать
701
- baseRoute = 'mainApi/';
702
- http = inject(HttpClient);
703
- // Получить роли пользователя
704
- getRoles() {
705
- return this.http.get(this.baseRoute + 'jwt/webroles');
285
+ error(message, duration = this.duration) {
286
+ this.openSnackBar(message, 'Закрыть', duration);
706
287
  }
707
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: RoleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
708
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: RoleService, providedIn: 'root' });
288
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NotificationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
289
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NotificationService, providedIn: 'root' });
709
290
  }
710
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: RoleService, decorators: [{
291
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NotificationService, decorators: [{
711
292
  type: Injectable,
712
293
  args: [{
713
294
  providedIn: 'root'
714
295
  }]
715
296
  }] });
716
297
 
717
- class BaseToolbarService {
718
- baseRoute = 'BaseToolbar';
719
- constructor() { }
720
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseToolbarService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
721
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseToolbarService, providedIn: 'root' });
722
- }
723
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseToolbarService, decorators: [{
724
- type: Injectable,
725
- args: [{
726
- providedIn: 'root'
727
- }]
728
- }], ctorParameters: () => [] });
729
-
730
- class BaseToolbarComponent {
731
- rolesNewBtn = input([], ...(ngDevMode ? [{ debugName: "rolesNewBtn" }] : []));
732
- rolesEditBtn = input([], ...(ngDevMode ? [{ debugName: "rolesEditBtn" }] : []));
733
- rolesRemoveBtn = input([], ...(ngDevMode ? [{ debugName: "rolesRemoveBtn" }] : []));
734
- rolesCopyBtn = input([], ...(ngDevMode ? [{ debugName: "rolesCopyBtn" }] : []));
735
- rolesExcelBtn = input([], ...(ngDevMode ? [{ debugName: "rolesExcelBtn" }] : []));
736
- rolesCsvBtn = input([], ...(ngDevMode ? [{ debugName: "rolesCsvBtn" }] : []));
737
- rolesPdfBtn = input([], ...(ngDevMode ? [{ debugName: "rolesPdfBtn" }] : []));
738
- rolesPrintBtn = input([], ...(ngDevMode ? [{ debugName: "rolesPrintBtn" }] : []));
739
- rolesRefreshBtn = input([], ...(ngDevMode ? [{ debugName: "rolesRefreshBtn" }] : []));
740
- rolesClearBtn = input([], ...(ngDevMode ? [{ debugName: "rolesClearBtn" }] : []));
741
- newBtnDisabled = input(false, ...(ngDevMode ? [{ debugName: "newBtnDisabled" }] : []));
742
- editBtnDisabled = input(false, ...(ngDevMode ? [{ debugName: "editBtnDisabled" }] : []));
743
- removeBtnDisabled = input(false, ...(ngDevMode ? [{ debugName: "removeBtnDisabled" }] : []));
744
- copyBtnDisabled = input(false, ...(ngDevMode ? [{ debugName: "copyBtnDisabled" }] : []));
745
- excelBtnDisabled = input(false, ...(ngDevMode ? [{ debugName: "excelBtnDisabled" }] : []));
746
- csvBtnDisabled = input(false, ...(ngDevMode ? [{ debugName: "csvBtnDisabled" }] : []));
747
- pdfBtnDisabled = input(false, ...(ngDevMode ? [{ debugName: "pdfBtnDisabled" }] : []));
748
- printBtnDisabled = input(false, ...(ngDevMode ? [{ debugName: "printBtnDisabled" }] : []));
749
- refreshBtnDisabled = input(false, ...(ngDevMode ? [{ debugName: "refreshBtnDisabled" }] : []));
750
- clearBtnDisabled = input(false, ...(ngDevMode ? [{ debugName: "clearBtnDisabled" }] : []));
751
- newBtnTooltip = input('Добавить', ...(ngDevMode ? [{ debugName: "newBtnTooltip" }] : []));
752
- editBtnTooltip = input('Изменить', ...(ngDevMode ? [{ debugName: "editBtnTooltip" }] : []));
753
- removeBtnTooltip = input('Удалить', ...(ngDevMode ? [{ debugName: "removeBtnTooltip" }] : []));
754
- copyBtnTooltip = input('Скопировать', ...(ngDevMode ? [{ debugName: "copyBtnTooltip" }] : []));
755
- excelBtnTooltip = input('Экспортировать в Excel', ...(ngDevMode ? [{ debugName: "excelBtnTooltip" }] : []));
756
- csvBtnTooltip = input('Экспортировать в Csv', ...(ngDevMode ? [{ debugName: "csvBtnTooltip" }] : []));
757
- pdfBtnTooltip = input('Экспортировать в Pdf', ...(ngDevMode ? [{ debugName: "pdfBtnTooltip" }] : []));
758
- printBtnTooltip = input('Печатать', ...(ngDevMode ? [{ debugName: "printBtnTooltip" }] : []));
759
- refreshBtnTooltip = input('Обновить данные', ...(ngDevMode ? [{ debugName: "refreshBtnTooltip" }] : []));
760
- clearBtnTooltip = input('Очистить фильтр', ...(ngDevMode ? [{ debugName: "clearBtnTooltip" }] : []));
761
- /** Список элементов контекстного меню. */
762
- newBtnOpt = input([], ...(ngDevMode ? [{ debugName: "newBtnOpt" }] : []));
763
- clickedNewBtn = output();
764
- clickedEditBtn = output();
765
- clickedRemoveBtn = output();
766
- clickedCopyBtn = output();
767
- clickedExcelBtn = output();
768
- clickedCsvBtn = output();
769
- clickedPdfBtn = output();
770
- clickedPrintBtn = output();
771
- clickedRefreshBtn = output();
772
- clickedClearBtn = output();
773
- // DI
774
- authService = inject(AuthService);
775
- userRoles = [];
776
- subscription = new Subscription();
777
- ngOnInit() {
778
- // получить права пользователя
779
- const subs = this.authService.roles$.subscribe((userRoles) => {
780
- this.userRoles = userRoles;
781
- });
782
- this.subscription.add(subs);
783
- }
784
- ngOnDestroy() {
785
- if (this.subscription)
786
- this.subscription.unsubscribe();
787
- }
788
- isShow(roles) {
789
- //console.log(roles, this.userRoles);
790
- return !this.authService.isHideElement(roles, this.userRoles);
791
- }
792
- onNewClick() {
793
- this.clickedNewBtn.emit();
794
- }
795
- onEditClick() {
796
- this.clickedEditBtn.emit();
797
- }
798
- onRemoveClick() {
799
- this.clickedRemoveBtn.emit();
800
- }
801
- onCopyClick() {
802
- this.clickedCopyBtn.emit();
803
- }
804
- onExcelClick() {
805
- this.clickedExcelBtn.emit();
806
- }
807
- onCsvClick() {
808
- this.clickedCsvBtn.emit();
809
- }
810
- onPdfClick() {
811
- this.clickedPdfBtn.emit();
812
- }
813
- onPrintClick() {
814
- this.clickedPrintBtn.emit();
815
- }
816
- onRefreshGridClick() {
817
- this.clickedRefreshBtn.emit();
818
- }
819
- onClearClick() {
820
- this.clickedClearBtn.emit();
821
- }
822
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
823
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: BaseToolbarComponent, isStandalone: true, selector: "ngx-uik-base-toolbar", inputs: { rolesNewBtn: { classPropertyName: "rolesNewBtn", publicName: "rolesNewBtn", isSignal: true, isRequired: false, transformFunction: null }, rolesEditBtn: { classPropertyName: "rolesEditBtn", publicName: "rolesEditBtn", isSignal: true, isRequired: false, transformFunction: null }, rolesRemoveBtn: { classPropertyName: "rolesRemoveBtn", publicName: "rolesRemoveBtn", isSignal: true, isRequired: false, transformFunction: null }, rolesCopyBtn: { classPropertyName: "rolesCopyBtn", publicName: "rolesCopyBtn", isSignal: true, isRequired: false, transformFunction: null }, rolesExcelBtn: { classPropertyName: "rolesExcelBtn", publicName: "rolesExcelBtn", isSignal: true, isRequired: false, transformFunction: null }, rolesCsvBtn: { classPropertyName: "rolesCsvBtn", publicName: "rolesCsvBtn", isSignal: true, isRequired: false, transformFunction: null }, rolesPdfBtn: { classPropertyName: "rolesPdfBtn", publicName: "rolesPdfBtn", isSignal: true, isRequired: false, transformFunction: null }, rolesPrintBtn: { classPropertyName: "rolesPrintBtn", publicName: "rolesPrintBtn", isSignal: true, isRequired: false, transformFunction: null }, rolesRefreshBtn: { classPropertyName: "rolesRefreshBtn", publicName: "rolesRefreshBtn", isSignal: true, isRequired: false, transformFunction: null }, rolesClearBtn: { classPropertyName: "rolesClearBtn", publicName: "rolesClearBtn", isSignal: true, isRequired: false, transformFunction: null }, newBtnDisabled: { classPropertyName: "newBtnDisabled", publicName: "newBtnDisabled", isSignal: true, isRequired: false, transformFunction: null }, editBtnDisabled: { classPropertyName: "editBtnDisabled", publicName: "editBtnDisabled", isSignal: true, isRequired: false, transformFunction: null }, removeBtnDisabled: { classPropertyName: "removeBtnDisabled", publicName: "removeBtnDisabled", isSignal: true, isRequired: false, transformFunction: null }, copyBtnDisabled: { classPropertyName: "copyBtnDisabled", publicName: "copyBtnDisabled", isSignal: true, isRequired: false, transformFunction: null }, excelBtnDisabled: { classPropertyName: "excelBtnDisabled", publicName: "excelBtnDisabled", isSignal: true, isRequired: false, transformFunction: null }, csvBtnDisabled: { classPropertyName: "csvBtnDisabled", publicName: "csvBtnDisabled", isSignal: true, isRequired: false, transformFunction: null }, pdfBtnDisabled: { classPropertyName: "pdfBtnDisabled", publicName: "pdfBtnDisabled", isSignal: true, isRequired: false, transformFunction: null }, printBtnDisabled: { classPropertyName: "printBtnDisabled", publicName: "printBtnDisabled", isSignal: true, isRequired: false, transformFunction: null }, refreshBtnDisabled: { classPropertyName: "refreshBtnDisabled", publicName: "refreshBtnDisabled", isSignal: true, isRequired: false, transformFunction: null }, clearBtnDisabled: { classPropertyName: "clearBtnDisabled", publicName: "clearBtnDisabled", isSignal: true, isRequired: false, transformFunction: null }, newBtnTooltip: { classPropertyName: "newBtnTooltip", publicName: "newBtnTooltip", isSignal: true, isRequired: false, transformFunction: null }, editBtnTooltip: { classPropertyName: "editBtnTooltip", publicName: "editBtnTooltip", isSignal: true, isRequired: false, transformFunction: null }, removeBtnTooltip: { classPropertyName: "removeBtnTooltip", publicName: "removeBtnTooltip", isSignal: true, isRequired: false, transformFunction: null }, copyBtnTooltip: { classPropertyName: "copyBtnTooltip", publicName: "copyBtnTooltip", isSignal: true, isRequired: false, transformFunction: null }, excelBtnTooltip: { classPropertyName: "excelBtnTooltip", publicName: "excelBtnTooltip", isSignal: true, isRequired: false, transformFunction: null }, csvBtnTooltip: { classPropertyName: "csvBtnTooltip", publicName: "csvBtnTooltip", isSignal: true, isRequired: false, transformFunction: null }, pdfBtnTooltip: { classPropertyName: "pdfBtnTooltip", publicName: "pdfBtnTooltip", isSignal: true, isRequired: false, transformFunction: null }, printBtnTooltip: { classPropertyName: "printBtnTooltip", publicName: "printBtnTooltip", isSignal: true, isRequired: false, transformFunction: null }, refreshBtnTooltip: { classPropertyName: "refreshBtnTooltip", publicName: "refreshBtnTooltip", isSignal: true, isRequired: false, transformFunction: null }, clearBtnTooltip: { classPropertyName: "clearBtnTooltip", publicName: "clearBtnTooltip", isSignal: true, isRequired: false, transformFunction: null }, newBtnOpt: { classPropertyName: "newBtnOpt", publicName: "newBtnOpt", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clickedNewBtn: "clickedNewBtn", clickedEditBtn: "clickedEditBtn", clickedRemoveBtn: "clickedRemoveBtn", clickedCopyBtn: "clickedCopyBtn", clickedExcelBtn: "clickedExcelBtn", clickedCsvBtn: "clickedCsvBtn", clickedPdfBtn: "clickedPdfBtn", clickedPrintBtn: "clickedPrintBtn", clickedRefreshBtn: "clickedRefreshBtn", clickedClearBtn: "clickedClearBtn" }, providers: [
824
- BaseToolbarService
825
- ], ngImport: i0, template: "<mat-toolbar>\r\n @if (isShow(rolesNewBtn())) {\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 (isShow(rolesEditBtn())) {\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 (isShow(rolesRemoveBtn())) {\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 (isShow(rolesCopyBtn())) {\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 (isShow(rolesExcelBtn())) {\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 (isShow(rolesCsvBtn())) {\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 (isShow(rolesPdfBtn())) {\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 (isShow(rolesPrintBtn())) {\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 (isShow(rolesRefreshBtn())) {\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 (isShow(rolesClearBtn())) {\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", styles: [""], dependencies: [{ kind: "component", type: MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }] });
826
- }
827
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseToolbarComponent, decorators: [{
828
- type: Component,
829
- args: [{ selector: 'ngx-uik-base-toolbar', imports: [MatToolbar, MatIconButton, MatTooltip, MatIcon, MatMenu, MatDivider, MatMenuTrigger, MatMenuItem], providers: [
830
- BaseToolbarService
831
- ], template: "<mat-toolbar>\r\n @if (isShow(rolesNewBtn())) {\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 (isShow(rolesEditBtn())) {\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 (isShow(rolesRemoveBtn())) {\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 (isShow(rolesCopyBtn())) {\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 (isShow(rolesExcelBtn())) {\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 (isShow(rolesCsvBtn())) {\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 (isShow(rolesPdfBtn())) {\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 (isShow(rolesPrintBtn())) {\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 (isShow(rolesRefreshBtn())) {\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 (isShow(rolesClearBtn())) {\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" }]
832
- }], propDecorators: { rolesNewBtn: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesNewBtn", required: false }] }], rolesEditBtn: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesEditBtn", required: false }] }], rolesRemoveBtn: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesRemoveBtn", required: false }] }], rolesCopyBtn: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesCopyBtn", required: false }] }], rolesExcelBtn: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesExcelBtn", required: false }] }], rolesCsvBtn: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesCsvBtn", required: false }] }], rolesPdfBtn: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesPdfBtn", required: false }] }], rolesPrintBtn: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesPrintBtn", required: false }] }], rolesRefreshBtn: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesRefreshBtn", required: false }] }], rolesClearBtn: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesClearBtn", required: false }] }], newBtnDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "newBtnDisabled", required: false }] }], editBtnDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "editBtnDisabled", required: false }] }], removeBtnDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeBtnDisabled", required: false }] }], copyBtnDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "copyBtnDisabled", required: false }] }], excelBtnDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "excelBtnDisabled", required: false }] }], csvBtnDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "csvBtnDisabled", required: false }] }], pdfBtnDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "pdfBtnDisabled", required: false }] }], printBtnDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "printBtnDisabled", required: false }] }], refreshBtnDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "refreshBtnDisabled", required: false }] }], clearBtnDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearBtnDisabled", required: false }] }], newBtnTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "newBtnTooltip", required: false }] }], editBtnTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "editBtnTooltip", required: false }] }], removeBtnTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeBtnTooltip", required: false }] }], copyBtnTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "copyBtnTooltip", required: false }] }], excelBtnTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "excelBtnTooltip", required: false }] }], csvBtnTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "csvBtnTooltip", required: false }] }], pdfBtnTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "pdfBtnTooltip", required: false }] }], printBtnTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "printBtnTooltip", required: false }] }], refreshBtnTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "refreshBtnTooltip", required: false }] }], clearBtnTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearBtnTooltip", required: false }] }], newBtnOpt: [{ type: i0.Input, args: [{ isSignal: true, alias: "newBtnOpt", required: false }] }], clickedNewBtn: [{ type: i0.Output, args: ["clickedNewBtn"] }], clickedEditBtn: [{ type: i0.Output, args: ["clickedEditBtn"] }], clickedRemoveBtn: [{ type: i0.Output, args: ["clickedRemoveBtn"] }], clickedCopyBtn: [{ type: i0.Output, args: ["clickedCopyBtn"] }], clickedExcelBtn: [{ type: i0.Output, args: ["clickedExcelBtn"] }], clickedCsvBtn: [{ type: i0.Output, args: ["clickedCsvBtn"] }], clickedPdfBtn: [{ type: i0.Output, args: ["clickedPdfBtn"] }], clickedPrintBtn: [{ type: i0.Output, args: ["clickedPrintBtn"] }], clickedRefreshBtn: [{ type: i0.Output, args: ["clickedRefreshBtn"] }], clickedClearBtn: [{ type: i0.Output, args: ["clickedClearBtn"] }] } });
833
-
834
- var Action;
835
- (function (Action) {
836
- Action["Add"] = "\u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u0438\u0435";
837
- Action["Edit"] = "\u0418\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0435";
838
- })(Action || (Action = {}));
839
-
840
- class AvatarService {
841
- baseRoute = 'common/human/';
842
- http = inject(HttpClient);
843
- getAvatarById(idHuman) {
844
- return this.http.get(this.baseRoute + idHuman + '/avatar', { responseType: 'arraybuffer' });
845
- }
846
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: AvatarService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
847
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: AvatarService, providedIn: 'root' });
848
- }
849
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: AvatarService, decorators: [{
850
- type: Injectable,
851
- args: [{
852
- providedIn: 'root'
853
- }]
854
- }] });
855
-
856
- class LocalStorageService {
857
- constructor() { }
858
- saveData(key, value) {
859
- localStorage.setItem(key, value);
860
- }
861
- getData(key) {
862
- return localStorage.getItem(key);
863
- }
864
- removeData(key) {
865
- localStorage.removeItem(key);
866
- }
867
- clearData() {
868
- localStorage.clear();
869
- }
870
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: LocalStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
871
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: LocalStorageService, providedIn: 'root' });
872
- }
873
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: LocalStorageService, decorators: [{
874
- type: Injectable,
875
- args: [{
876
- providedIn: 'root'
877
- }]
878
- }], ctorParameters: () => [] });
879
-
880
- class ExportService {
881
- // Экспорт в CSV
882
- exportCSV(data, filename = 'data', arrHeader, newHeaders) {
883
- const csvData = this.convertToCSV(data, arrHeader, newHeaders);
884
- console.log(csvData);
885
- const blob = new Blob(['\ufeff' + csvData], { type: 'text/csv;charset=utf-8;' });
886
- const dwldLink = document.createElement('a');
887
- const url = URL.createObjectURL(blob);
888
- const isSafariBrowser = navigator.userAgent.indexOf('Safari') !== -1 && navigator.userAgent.indexOf('Chrome') === -1;
889
- if (isSafariBrowser) { //if Safari open in new window to save file with random filename.
890
- dwldLink.setAttribute('target', '_blank');
891
- }
892
- dwldLink.setAttribute('href', url);
893
- dwldLink.setAttribute('download', filename + '.csv');
894
- dwldLink.style.visibility = 'hidden';
895
- document.body.appendChild(dwldLink);
896
- dwldLink.click();
897
- document.body.removeChild(dwldLink);
898
- }
899
- convertToCSV(objArray, headerList, newHeaders) {
900
- const array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
901
- let str = '';
902
- let row = 'S.No,';
903
- for (const index in newHeaders) {
904
- if (Object.prototype.hasOwnProperty.call(newHeaders, index)) {
905
- row += newHeaders[index] + ',';
906
- }
907
- }
908
- row = row.slice(0, -1);
909
- str += row + '\r\n';
910
- for (let i = 0; i < array.length; i++) {
911
- let line = (i + 1) + '';
912
- for (const index in headerList) {
913
- if (Object.prototype.hasOwnProperty.call(newHeaders, index)) {
914
- const head = headerList[index];
915
- line += ',' + array[i][head];
916
- }
917
- }
918
- str += line + '\r\n';
919
- }
920
- return str;
921
- }
922
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ExportService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
923
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ExportService, providedIn: 'root' });
924
- }
925
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ExportService, decorators: [{
926
- type: Injectable,
927
- args: [{
928
- providedIn: 'root'
929
- }]
930
- }] });
931
-
932
- class SseService {
933
- zone = inject(NgZone);
934
- eventSource = null;
935
- isConnected = false;
936
- constructor() { }
937
- createSseEventSource(baseUrl, user, topic) {
938
- const subject = new ReplaySubject(1);
939
- // Close any existing connection
940
- this.closeSseEventSource();
941
- const topicUri = topic.getTopic(baseUrl, user);
942
- // environment.sse_url
943
- this.eventSource = new EventSource(topicUri
944
- //, {withCredentials: true}
945
- );
946
- if (this.eventSource) {
947
- this.isConnected = true;
948
- // Listen for messages
949
- this.eventSource.onmessage = (event) => {
950
- console.log(event);
951
- const messageData = JSON.parse(event.data);
952
- this.zone.run(() => {
953
- subject.next(messageData);
954
- });
955
- };
956
- this.eventSource.onopen = () => {
957
- console.log('SSE connection opened.');
958
- };
959
- // Process error
960
- this.eventSource.onerror = (error) => {
961
- console.error('SSE error:', error);
962
- this.reconnectOnError(baseUrl, user, topic, subject);
963
- };
964
- }
965
- return subject.asObservable();
966
- }
967
- reconnectOnError(baseUrl, user, topic, subject) {
968
- this.closeSseEventSource();
969
- if (this.isConnected)
970
- return; // Prevent duplicate connections
971
- console.log('Reconnecting to SSE in 1 second...');
972
- setTimeout(() => {
973
- this.zone.run(() => {
974
- this.createSseEventSource(baseUrl, user, topic).subscribe(subject);
975
- });
976
- }, 1000);
977
- }
978
- closeSseEventSource() {
979
- if (this.eventSource) {
980
- this.eventSource.close();
981
- this.eventSource = null;
982
- this.isConnected = false;
983
- console.log('SSE Connection closed');
984
- }
985
- }
986
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: SseService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
987
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: SseService, providedIn: 'root' });
988
- }
989
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: SseService, decorators: [{
990
- type: Injectable,
991
- args: [{
992
- providedIn: 'root'
993
- }]
994
- }], ctorParameters: () => [] });
995
-
996
- class BaseEditClass {
997
- /** Сервис индикатор загрузки. */
998
- loaderService = inject(LoaderService);
999
- /** Сервис уведомлений. */
1000
- alertService = inject(AlertService);
1001
- /** Объект для отписки (вызывается метод unsubscribe при уничтожении компонента). */
1002
- subscription = new Subscription();
1003
- ngOnDestroy() {
1004
- this.subscription.unsubscribe();
1005
- }
1006
- onNoClick(event) {
1007
- this.dialogRef?.close(null);
1008
- event.preventDefault(); // иначе сработает onSubmit
1009
- }
1010
- onSubmit() {
1011
- if (this.form) {
1012
- if (this.form.valid) {
1013
- if (this.dialogData)
1014
- Object.keys(this.form.controls).forEach(controlName => this.dialogData.entity[controlName] = this.form?.controls[controlName].value);
1015
- this.dialogRef?.close(this.dialogData);
1016
- }
1017
- else {
1018
- Object.keys(this.form.controls).forEach(controlName => this.form?.controls[controlName].markAsTouched());
1019
- }
1020
- }
1021
- }
1022
- formActionIsAdd() {
1023
- return this.dialogData?.action === Action.Add;
1024
- }
1025
- formActionIsEdit() {
1026
- return this.dialogData?.action === Action.Edit;
1027
- }
1028
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseEditClass, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1029
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.0", type: BaseEditClass, isStandalone: true, ngImport: i0 });
1030
- }
1031
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseEditClass, decorators: [{
1032
- type: Directive
1033
- }] });
1034
-
1035
- var EntityAction;
1036
- (function (EntityAction) {
1037
- EntityAction["Init"] = "\u0418\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u044F";
1038
- EntityAction["Add"] = "\u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u0438\u0435";
1039
- EntityAction["Edit"] = "\u0418\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0435";
1040
- EntityAction["Delete"] = "\u0423\u0434\u0430\u043B\u0435\u043D\u0438\u0435";
1041
- })(EntityAction || (EntityAction = {}));
1042
-
1043
- class BaseFilterClass {
1044
- /** Сервис для работы с LocalStorage. */
1045
- localStorageService = inject(LocalStorageService);
1046
- /** Сервис индикатор загрузки. */
1047
- loaderService = inject(LoaderService);
1048
- /** Сервис уведомлений. */
1049
- alertService = inject(AlertService);
1050
- // eslint-disable-next-line no-magic-numbers
1051
- defaultDebounceTime = 500;
1052
- /** Объект для отписки (вызывается метод unsubscribe при уничтожении компонента). */
1053
- subscription = new Subscription();
1054
- constructor() {
1055
- }
1056
- ngOnDestroy() {
1057
- this.subscription.unsubscribe();
1058
- }
1059
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseFilterClass, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1060
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.0", type: BaseFilterClass, isStandalone: true, ngImport: i0 });
1061
- }
1062
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseFilterClass, decorators: [{
1063
- type: Directive
1064
- }], ctorParameters: () => [] });
1065
-
1066
- class BaseNavBarMenuClass {
1067
- subscription = new Subscription();
1068
- router = inject(Router);
1069
- ngOnDestroy() {
1070
- if (this.subscription)
1071
- this.subscription.unsubscribe();
1072
- }
1073
- /** Нажата средняя кнопка (открыть ссылку в новой вкладке). */
1074
- onMiddleClick(event, baseUrl, menu) {
1075
- // 1 - Auxiliary button pressed (usually the middle button)
1076
- if (event.button === 1) {
1077
- // event.preventDefault();
1078
- menu.closeMenu();
1079
- const urlTree = this.router.serializeUrl(this.router.createUrlTree([baseUrl]));
1080
- window.open(urlTree, '_blank');
1081
- }
1082
- }
1083
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseNavBarMenuClass, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1084
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.0", type: BaseNavBarMenuClass, isStandalone: true, ngImport: i0 });
1085
- }
1086
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseNavBarMenuClass, decorators: [{
1087
- type: Directive
1088
- }] });
1089
-
1090
- class DialogComponent {
1091
- data = inject(MAT_DIALOG_DATA);
1092
- dialogRef = inject((MatDialogRef));
1093
- constructor() {
1094
- if (!this.data.title) {
1095
- this.data.title = 'Подтверждение';
1096
- }
1097
- if (!this.data.btnNoTitle) {
1098
- this.data.btnNoTitle = 'Нет';
1099
- }
1100
- if (!this.data.btnYesTitle) {
1101
- this.data.btnYesTitle = 'Да';
1102
- }
1103
- }
1104
- onNoClick() {
1105
- this.dialogRef.close();
1106
- }
1107
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: DialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1108
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.0", type: DialogComponent, isStandalone: true, selector: "ngx-uik-dialog", ngImport: i0, template: "<h1 mat-dialog-title>{{ data.title }}</h1>\r\n<div mat-dialog-content>\r\n <div style=\"white-space: pre-line\">{{ data.message }}</div>\r\n</div>\r\n<div mat-dialog-actions align=\"end\">\r\n <button mat-raised-button (click)=\"onNoClick()\" cdkFocusInitial>{{ data.btnNoTitle }}</button>\r\n <button mat-raised-button color=\"warn\" [mat-dialog-close]=\"data.id\">{{ data.btnYesTitle }}</button>\r\n</div>\r\n\r\n", styles: [""], dependencies: [{ kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }] });
1109
- }
1110
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: DialogComponent, decorators: [{
1111
- type: Component,
1112
- args: [{ selector: 'ngx-uik-dialog', imports: [MatDialogTitle, MatDialogContent, MatDialogActions, MatButton, MatDialogClose], template: "<h1 mat-dialog-title>{{ data.title }}</h1>\r\n<div mat-dialog-content>\r\n <div style=\"white-space: pre-line\">{{ data.message }}</div>\r\n</div>\r\n<div mat-dialog-actions align=\"end\">\r\n <button mat-raised-button (click)=\"onNoClick()\" cdkFocusInitial>{{ data.btnNoTitle }}</button>\r\n <button mat-raised-button color=\"warn\" [mat-dialog-close]=\"data.id\">{{ data.btnYesTitle }}</button>\r\n</div>\r\n\r\n" }]
1113
- }], ctorParameters: () => [] });
1114
-
1115
- class BasePageClass {
1116
- dialog = inject(MatDialog);
1117
- /** Данные для табличного компонента. */
1118
- data = signal([], ...(ngDevMode ? [{ debugName: "data" }] : []));
1119
- /** Количество записей по фильтру. */
1120
- length = signal(0, ...(ngDevMode ? [{ debugName: "length" }] : []));
1121
- entityService;
1122
- entityType;
1123
- entityEditComponent;
1124
- extraData;
1125
- // eslint-disable-next-line no-magic-numbers
1126
- defaultPageIndex = 0;
1127
- // eslint-disable-next-line no-magic-numbers
1128
- defaultPageSize = 10;
1129
- dialogEditWidth = 'auto';
1130
- dialogRemoveWidth = '400px';
1131
- routeAddress = '';
1132
- /** Сообщение при удалении записи(й). */
1133
- removalMessage = '';
1134
- /** Заголовок страницы. */
1135
- pageTitle = '';
1136
- /**
1137
- * Создание записи: вызывается перед открытием диалога.
1138
- */
1139
- beforeOpenDialogOnNewEvent;
1140
- /**
1141
- * Редактирование записи: вызывается перед открытием диалога.
1142
- */
1143
- beforeOpenDialogOnEditEvent;
1144
- /**
1145
- * Создание записи: вызывается перед сохранением объекта.
1146
- */
1147
- beforeSaveOnNewEvent;
1148
- /**
1149
- * Редактирование записи: вызывается перед сохранением объекта.
1150
- */
1151
- beforeSaveOnEditEvent;
1152
- /**
1153
- * Создание записи: вызывается после сохранения объекта.
1154
- */
1155
- afterSaveOnNewEvent;
1156
- /**
1157
- * Редактирование записи: вызывается после сохранения объекта.
1158
- */
1159
- afterSaveOnEditEvent;
1160
- editorRoles = [];
1161
- executeRoles = [];
1162
- /** Список ролей, для которых скрыть элемент. */
1163
- hideRoles = ['HIDE'];
1164
- /** Загрузка данных. */
1165
- loadData$ = new Subject();
1166
- /** Загрузка количества записей. */
1167
- loadLength$ = new Subject();
1168
- /** Очистка фильтра. */
1169
- clearFilter$ = new Subject();
1170
- /** Очистка фильтра (для очистки присвоить пустой объект '{}'). */
1171
- clearFilter = null;
1172
- /** Разрешен выбор нескольких строк. */
1173
- allowMultiSelect = false;
1174
- /** Выбранные строки в таблице. */
1175
- selected = [];
1176
- /** Состояние сортировки, пагинации. */
1177
- tableState;
1178
- /** Доступность кнопки "Изменить". */
1179
- editBtnDisabled = true;
1180
- /** Доступность кнопки "Удалить". */
1181
- removeBtnDisabled = true;
1182
- /** Разрешено ли отправлять событие rowDoubleClicked при двойном щелчке мышью. */
1183
- dblClickedEventEnable = true;
1184
- // Список элементов контекстного меню.
1185
- opt = [];
1186
- // DI
1187
- router = inject(Router);
1188
- /** Сервис для работы с LocalStorage. */
1189
- localStorageService = inject(LocalStorageService);
1190
- /** Сервис индикатор загрузки. */
1191
- loaderService = inject(LoaderService);
1192
- /** Сервис уведомлений. */
1193
- alertService = inject(AlertService);
1194
- /** Объект для отписки (вызывается метод unsubscribe при уничтожении компонента). */
1195
- subscription = new Subscription();
1196
- constructor() {
1197
- this.tableState = {
1198
- sortActive: this.localStorageService.getData(this.constructor.name + 'SortActive') || '',
1199
- sortDirection: (this.localStorageService.getData(this.constructor.name + 'SortDirection') || ''),
1200
- pageIndex: Number(this.localStorageService.getData(this.constructor.name + 'PageIndex')) || this.defaultPageIndex,
1201
- pageSize: Number(this.localStorageService.getData(this.constructor.name + 'PageSize')) || this.defaultPageSize
1202
- };
1203
- }
1204
- ngOnDestroy() {
1205
- this.subscription.unsubscribe();
1206
- }
1207
- subscribeToLoadData(fnGetData, fnGetCount, fnMapEntity) {
1208
- // отменять стримы, созданные ранее
1209
- const subs = this.loadData$
1210
- .pipe(tap(() => this.loaderService.show()), switchMap(() => fnGetData()), map$1(v => fnMapEntity ? v.map(fnMapEntity()) : v))
1211
- .subscribe({
1212
- next: (response) => {
1213
- this.data.set(response);
1214
- this.loaderService.hide();
1215
- },
1216
- error: (error) => {
1217
- this.loaderService.hide();
1218
- console.log(error);
1219
- this.alertService.error('Произошла ошибка: ' + error, 0);
1220
- }
1221
- });
1222
- this.subscription?.add(subs);
1223
- const subs2 = this.loadLength$
1224
- .pipe(switchMap(() => fnGetCount()))
1225
- .subscribe({
1226
- next: (response) => {
1227
- this.length.set(response);
1228
- },
1229
- error: (error) => {
1230
- console.log(error);
1231
- this.alertService.error('Произошла ошибка: ' + error, 0);
1232
- }
1233
- });
1234
- this.subscription?.add(subs2);
1235
- // загрузить данные и количество записей
1236
- this.loadData$.next(null);
1237
- this.loadLength$.next(null);
1238
- }
1239
- onPageChange(pageState) {
1240
- this.tableState.pageIndex = pageState.pageIndex;
1241
- this.tableState.pageSize = pageState.pageSize;
1242
- this.localStorageService.saveData(this.constructor.name + 'PageIndex', pageState.pageIndex.toString());
1243
- this.localStorageService.saveData(this.constructor.name + 'PageSize', pageState.pageSize.toString());
1244
- this.loadData$.next(null);
1245
- this.loadLength$.next(null);
1246
- }
1247
- onSortChange(sortState) {
1248
- this.tableState.sortActive = sortState.sortActive;
1249
- this.tableState.sortDirection = sortState.sortDirection;
1250
- this.localStorageService.saveData(this.constructor.name + 'SortActive', sortState.sortActive);
1251
- this.localStorageService.saveData(this.constructor.name + 'SortDirection', sortState.sortDirection);
1252
- this.loadData$.next(null);
1253
- this.loadLength$.next(null);
1254
- }
1255
- entityFactory(type) {
1256
- return new type();
1257
- }
1258
- /** Событие изменение выбранных записей. */
1259
- onSelectionChange(selected) {
1260
- this.selected = selected;
1261
- this.editBtnDisabledUpdate(this.selected);
1262
- this.removeBtnDisabledUpdate(this.selected);
1263
- }
1264
- /** Обновление доступности кнопки "Изменить" - вызывается при изменении выбранных записей. */
1265
- editBtnDisabledUpdate(selected) {
1266
- this.editBtnDisabled = !(selected && selected.length === 1);
1267
- }
1268
- /** Обновление доступности кнопки "Удалить" - вызывается при изменении выбранных записей. */
1269
- removeBtnDisabledUpdate(selected) {
1270
- this.removeBtnDisabled = !(selected && selected.length > 0);
1271
- }
1272
- /** Событие двойной клик. */
1273
- onRowDoubleClicked() {
1274
- this.editEvent();
1275
- }
1276
- /** Событие создание. */
1277
- newEvent() {
1278
- if (this.entityEditComponent) {
1279
- const data = { action: Action.Add, entity: new this.entityType(null) };
1280
- // Назначить значения полей объекта перед открытием диалога.
1281
- if (this.beforeOpenDialogOnNewEvent) {
1282
- this.beforeOpenDialogOnNewEvent(data.entity, data.extraData);
1283
- }
1284
- // Открытие окна
1285
- const dialogRef = this.openDialog(this.entityEditComponent, data, this.dialog);
1286
- // Обработка закрытия окна
1287
- const subs = dialogRef.afterClosed().subscribe((result) => {
1288
- // Проверка результата
1289
- if (result && result.entity && (Object.keys(result.entity).length !== 0)) {
1290
- // Дополнительные действия перед сохранением объекта.
1291
- if (this.beforeSaveOnNewEvent)
1292
- this.beforeSaveOnNewEvent(result.entity, result.extraData);
1293
- const subs = this.entityService.newObject(result.entity)
1294
- .subscribe({
1295
- next: (obj) => {
1296
- // Дополнительные действия после сохранения объекта.
1297
- if (this.afterSaveOnNewEvent) {
1298
- const callback = () => {
1299
- this.refreshEvent();
1300
- this.alertService.success('Запись добавлена.');
1301
- };
1302
- this.afterSaveOnNewEvent(callback.bind(this), obj, result.extraData);
1303
- }
1304
- else {
1305
- this.refreshEvent();
1306
- this.alertService.success('Запись добавлена.');
1307
- }
1308
- },
1309
- error: (error) => {
1310
- console.log('error', error);
1311
- this.alertService.error('Произошла ошибка при добавлении записи: ' + error, 0);
1312
- }
1313
- });
1314
- this.subscription.add(subs);
1315
- }
1316
- });
1317
- this.subscription.add(subs);
1318
- // Закрытие окна по нажатию Escape
1319
- const subs2 = dialogRef.keydownEvents().subscribe((event) => {
1320
- if (event.key === 'Escape') {
1321
- dialogRef.close(null);
1322
- }
1323
- });
1324
- this.subscription.add(subs2);
1325
- }
1326
- else {
1327
- this.alertService.warning('Действие не доступно.');
1328
- }
1329
- }
1330
- /** Событие редактирование. */
1331
- editEvent() {
1332
- if (this.selected && this.selected.length === 1) {
1333
- if (this.entityEditComponent) {
1334
- const data = { action: Action.Edit, entity: this.selected[0] };
1335
- // Назначить значения полей объекта перед открытием диалога.
1336
- if (this.beforeOpenDialogOnEditEvent) {
1337
- this.beforeOpenDialogOnEditEvent(data.entity, data.extraData);
1338
- }
1339
- // Открытие окна
1340
- const dialogRef = this.openDialog(this.entityEditComponent, data, this.dialog);
1341
- // Обработка закрытия окна
1342
- const subs = dialogRef.afterClosed().subscribe((result) => {
1343
- // Проверка результата
1344
- if (result && result.entity && (Object.keys(result.entity).length !== 0)) {
1345
- // Дополнительные действия перед сохранением объекта.
1346
- if (this.beforeSaveOnEditEvent)
1347
- this.beforeSaveOnEditEvent(result.entity, result.extraData);
1348
- const subs = this.entityService.editObject(result.entity)
1349
- .subscribe({
1350
- next: () => {
1351
- // Дополнительные действия после сохранения объекта.
1352
- if (this.afterSaveOnEditEvent) {
1353
- const callback = () => {
1354
- this.refreshEvent();
1355
- this.alertService.success('Запись изменена.');
1356
- };
1357
- this.afterSaveOnEditEvent(callback.bind(this), result.entity, result.extraData);
1358
- }
1359
- else {
1360
- this.refreshEvent();
1361
- this.alertService.success('Запись изменена.');
1362
- }
1363
- },
1364
- error: (error) => {
1365
- console.log('error', error);
1366
- this.alertService.error('Произошла ошибка при изменении записи: ' + error, 0);
1367
- }
1368
- });
1369
- this.subscription.add(subs);
1370
- }
1371
- });
1372
- this.subscription.add(subs);
1373
- // Закрытие окна по нажатию Escape
1374
- const subs2 = dialogRef.keydownEvents().subscribe((event) => {
1375
- if (event.key === 'Escape') {
1376
- dialogRef.close(null);
1377
- }
1378
- });
1379
- this.subscription.add(subs2);
1380
- }
1381
- else {
1382
- this.alertService.warning('Действие не доступно.');
1383
- }
1384
- }
1385
- }
1386
- /** Событие удаление. */
1387
- removeEvent() {
1388
- // если выбрана запись(и)
1389
- if (this.selected && this.selected.length > 0) {
1390
- const dialogRef = this.openDialogRemoveConfirm(this.removalMessage);
1391
- if (dialogRef) {
1392
- const subs = dialogRef.afterClosed().subscribe((result) => {
1393
- // при подтверждении возвращается 'delete'
1394
- if (result === 'delete') {
1395
- // готовим объект с запросами на удаление
1396
- const sourcesObject = {};
1397
- this.selected.forEach((item, index) => sourcesObject['obj' + index] = this.entityService.deleteObject(item));
1398
- // ждем, когда выполнятся все запросы
1399
- const subs = forkJoin(sourcesObject)
1400
- .subscribe({
1401
- next: () => {
1402
- this.refreshEvent();
1403
- this.alertService.success('Выбранные записи удалены.');
1404
- },
1405
- error: (error) => {
1406
- console.log('error', error);
1407
- this.alertService.error('Произошла ошибка при удалении записи: ' + error, 0);
1408
- }
1409
- });
1410
- this.subscription.add(subs);
1411
- }
1412
- });
1413
- this.subscription.add(subs);
1414
- // Закрытие окна по нажатию Escape
1415
- const subs2 = dialogRef.keydownEvents().subscribe((event) => {
1416
- if (event.key === 'Escape') {
1417
- dialogRef.close(null);
1418
- }
1419
- });
1420
- this.subscription.add(subs2);
1421
- }
1422
- }
1423
- }
1424
- /** Событие обновления данных. */
1425
- refreshEvent() {
1426
- this.loadData$.next(null);
1427
- this.loadLength$.next(null);
1428
- }
1429
- /** Событие очистки фильтра. */
1430
- clearEvent() {
1431
- this.clearFilter$.next(null);
1432
- this.clearFilter = {};
1433
- }
1434
- /** Изменение сообщения об удалении. */
1435
- onRemovalMessageChange(message) {
1436
- this.removalMessage = message;
1437
- }
1438
- /** Изменение заголовка страницы. */
1439
- onPageTitleChange(title) {
1440
- this.pageTitle = title;
1441
- }
1442
- openDialog(entityComponent, data, dialog) {
1443
- // create dialog config
1444
- const dialogConfig = new MatDialogConfig();
1445
- dialogConfig.disableClose = true;
1446
- dialogConfig.autoFocus = true;
1447
- dialogConfig.width = this.dialogEditWidth;
1448
- dialogConfig.data = data;
1449
- dialogConfig.panelClass = this.entityType.name + '-edit-dialog';
1450
- // return dialog
1451
- return dialog.open(entityComponent, dialogConfig);
1452
- }
1453
- openDialogRemoveConfirm(removalMessage) {
1454
- let message = 'Вы хотите удалить ';
1455
- message += removalMessage ?
1456
- removalMessage :
1457
- this.allowMultiSelect ? `выбранные записи (${this.selected.length})?` : 'выбранную запись?';
1458
- return this.dialog.open(DialogComponent, {
1459
- width: this.dialogRemoveWidth,
1460
- data: {
1461
- id: 'delete',
1462
- title: 'Подтверждение',
1463
- message: message,
1464
- btnNoTitle: 'Отмена',
1465
- btnYesTitle: 'Удалить'
1466
- }
1467
- });
1468
- }
1469
- // contextMenu: При щелчке ПКМ открыть в новой вкладке.
1470
- onMiddleButton(baseUrl, queryParamName, queryParamValue) {
1471
- return ($event, item, contextMenu) => {
1472
- // Нажата средняя кнопка (в новой вкладке).
1473
- // 1 - Auxiliary button pressed (usually the middle button)
1474
- if ($event.button === 1) {
1475
- //$event.preventDefault();
1476
- contextMenu.closeMenu();
1477
- // Converts the route into a string that can be used
1478
- // with the window.open() function
1479
- const url = this.router.serializeUrl(queryParamName && queryParamValue ?
1480
- this.router.createUrlTree([baseUrl], { queryParams: { [queryParamName]: item[queryParamValue] } })
1481
- : this.router.createUrlTree([baseUrl]));
1482
- window.open(url, '_blank');
1483
- }
1484
- };
1485
- }
1486
- // Action в таблице: При щелчке ПКМ открыть в новой вкладке.
1487
- onActionMiddleButton(baseUrl, queryParamName, queryParamValue) {
1488
- return ($event, item) => {
1489
- // Нажата средняя кнопка (в новой вкладке).
1490
- // 1 - Auxiliary button pressed (usually the middle button)
1491
- if ($event.button === 1) {
1492
- //$event.preventDefault();
1493
- // Converts the route into a string that can be used
1494
- // with the window.open() function
1495
- const url = this.router.serializeUrl(queryParamName && queryParamValue ?
1496
- this.router.createUrlTree([baseUrl], { queryParams: { [queryParamName]: item[queryParamValue] } })
1497
- : this.router.createUrlTree([baseUrl]));
1498
- window.open(url, '_blank');
1499
- }
1500
- };
1501
- }
1502
- dateToString(date) {
1503
- return date ? (new Date(date)).toLocaleString('ru-RU', { timeZone: 'Europe/Samara' }) : null; // MSK+01
1504
- }
1505
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BasePageClass, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1506
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.0", type: BasePageClass, isStandalone: true, ngImport: i0 });
1507
- }
1508
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BasePageClass, decorators: [{
1509
- type: Directive
1510
- }], ctorParameters: () => [] });
1511
-
1512
- class BaseServiceClass {
1513
- countRoute = 'count';
1514
- pageIndexParam = 'page';
1515
- pageSizeParam = 'limit';
1516
- sortColumnParam = 'column';
1517
- directionParam = 'direction';
1518
- http = inject(HttpClient);
1519
- getObjects() {
1520
- return this.http.get(this.baseRoute)
1521
- .pipe(map(data => data.map(item => new this.entityType(item).deserialize(item))));
1522
- }
1523
- getObject(id) {
1524
- return this.http.get(this.baseRoute + id)
1525
- .pipe(map(data => new this.entityType(data).deserialize(data)));
1526
- }
1527
- getCount() {
1528
- return this.http.get(this.baseRoute + this.countRoute);
1529
- }
1530
- getObjectsByPaging(pageIndex, pageSize, sortColumn, direction) {
1531
- const params = this.getParams(pageIndex, pageSize, sortColumn, direction);
1532
- return this.http.get(this.baseRoute, { params })
1533
- .pipe(map(data => data.map(item => new this.entityType(item).deserialize(item))));
1534
- }
1535
- newObject(entity) {
1536
- return this.http.post(this.baseRoute, entity);
1537
- }
1538
- editObject(entity) {
1539
- return this.http.put(this.baseRoute + entity.id, entity);
1540
- }
1541
- deleteObject(entity) {
1542
- return this.http.delete(this.baseRoute + entity.id);
1543
- }
1544
- getParams(pageIndex, pageSize, sortColumn, direction) {
1545
- let params = new HttpParams();
1546
- if (pageIndex + 1)
1547
- // переход от индекса к номеру страницы
1548
- params = params.append(this.pageIndexParam, pageIndex + 1);
1549
- if (pageSize)
1550
- params = params.append(this.pageSizeParam, pageSize);
1551
- if (sortColumn)
1552
- params = params.append(this.sortColumnParam, sortColumn);
1553
- if (direction)
1554
- params = params.append(this.directionParam, direction);
1555
- return params;
1556
- }
1557
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseServiceClass, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1558
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseServiceClass, providedIn: 'root' });
1559
- }
1560
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseServiceClass, decorators: [{
1561
- type: Injectable,
1562
- args: [{
1563
- providedIn: 'root'
1564
- }]
1565
- }] });
1566
-
1567
- class SetValueDirective {
1568
- ngControl = inject(NgControl);
1569
- set setValue(val) {
1570
- this.ngControl.control?.setValue(val, { emitEvent: false });
1571
- }
1572
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: SetValueDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1573
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.0", type: SetValueDirective, isStandalone: true, selector: "[setValue]", inputs: { setValue: "setValue" }, ngImport: i0 });
1574
- }
1575
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: SetValueDirective, decorators: [{
1576
- type: Directive,
1577
- args: [{
1578
- selector: "[setValue]"
1579
- }]
1580
- }], propDecorators: { setValue: [{
1581
- type: Input
1582
- }] } });
1583
-
1584
- class RedirectGuard {
1585
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1586
- canActivate(route, state) {
1587
- console.log(route.data['externalUrl']);
1588
- window.location.href = route.data['externalUrl'];
1589
- return true;
1590
- }
1591
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: RedirectGuard, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1592
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: RedirectGuard, providedIn: 'root' });
1593
- }
1594
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: RedirectGuard, decorators: [{
1595
- type: Injectable,
1596
- args: [{
1597
- providedIn: 'root'
1598
- }]
1599
- }] });
1600
-
1601
- class SecUser {
1602
- id = 0;
1603
- login = '';
1604
- fio = '';
1605
- dept = 0;
1606
- tabnum = 0;
1607
- userView;
1608
- constructor(init) {
1609
- if (init) {
1610
- Object.assign(this, init);
1611
- }
1612
- else {
1613
- this.id = 0;
1614
- this.login = '';
1615
- this.dept = 0;
1616
- this.tabnum = 0;
1617
- this.fio = '';
1618
- }
1619
- }
1620
- deserialize(input) {
1621
- Object.assign(this, input);
1622
- return this;
1623
- }
1624
- }
1625
-
1626
- class SafePipe {
1627
- sanitizer = inject(DomSanitizer);
1628
- transform(url) {
1629
- return this.sanitizer.bypassSecurityTrustResourceUrl(url);
1630
- }
1631
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: SafePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1632
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.0", ngImport: i0, type: SafePipe, isStandalone: true, name: "safe" });
1633
- }
1634
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: SafePipe, decorators: [{
1635
- type: Pipe,
1636
- args: [{
1637
- name: 'safe'
1638
- }]
1639
- }] });
1640
-
1641
- class TimePipe {
1642
- transform(value) {
1643
- // const hour = Math.abs(value) >= 60 ? Math.round(value / 60) + 'ч.' : '';
1644
- // const minute = ' ' + Math.abs(value % 60) + 'м.';
1645
- // return value === 0 ? '0' : hour + ' ' + minute;
1646
- const hour = Math.abs(value) >= 60 ? Math.floor(Math.abs(value) / 60).toString().padStart(2, '0') : '00';
1647
- const minute = Math.abs(value % 60).toString().padStart(2, '0');
1648
- const time = hour + ':' + minute;
1649
- return value < 0 ? '-' + time : time;
1650
- }
1651
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TimePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1652
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.0", ngImport: i0, type: TimePipe, isStandalone: true, name: "time" });
1653
- }
1654
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TimePipe, decorators: [{
1655
- type: Pipe,
1656
- args: [{
1657
- name: 'time'
1658
- }]
1659
- }] });
1660
-
1661
- class TruncatePipe {
1662
- // Usage:
1663
- // {{ str | truncate:[20] }} // or
1664
- // {{ str | truncate:[20, '...'] }} // or|
1665
- transform(value, args) {
1666
- const limit = args.length > 0 ? parseInt(args[0], 10) : 20;
1667
- const trail = args.length > 1 ? args[1] : '...';
1668
- return value.length > limit ? value.substring(0, limit) + trail : value;
1669
- }
1670
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TruncatePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1671
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.0", ngImport: i0, type: TruncatePipe, isStandalone: true, name: "truncate" });
1672
- }
1673
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TruncatePipe, decorators: [{
1674
- type: Pipe,
1675
- args: [{
1676
- name: 'truncate'
1677
- }]
1678
- }] });
1679
-
1680
- class BaseMatChipComponent {
1681
- // Все элементы
1682
- items = input([], ...(ngDevMode ? [{ debugName: "items" }] : []));
1683
- // Выбранные элементы, ключи (ChipItem.value)
1684
- selectedItemsInput = input([], ...(ngDevMode ? [{ debugName: "selectedItemsInput" }] : []));
1685
- // Заголовок
1686
- title = input('', ...(ngDevMode ? [{ debugName: "title" }] : []));
1687
- // Событие изменения выбранных элементов
1688
- selectedItemsChange = output();
1689
- input = viewChild('input', ...(ngDevMode ? [{ debugName: "input" }] : []));
1690
- separatorKeysCodes = [ENTER, COMMA];
1691
- inputCtrl = new FormControl();
1692
- filteredItems$;
1693
- selectedItems = [];
1694
- constructor() {
1695
- effect(() => {
1696
- if (this.items().length > 0) {
1697
- this.filteredItems$ = this.inputCtrl.valueChanges.pipe(startWith(null), map(item => (item ? this._filter(item) : this.items().slice())));
1698
- }
1699
- });
1700
- effect(() => {
1701
- if (this.selectedItemsInput())
1702
- this.selectedItems = this.items().filter(s => this.selectedItemsInput().includes(s.value));
1703
- });
1704
- }
1705
- remove(value) {
1706
- this.selectedItems = [...this.selectedItems];
1707
- const index = this.selectedItems.map(i => i.value).indexOf(value);
1708
- if (index >= 0) {
1709
- this.selectedItems.splice(index, 1);
1710
- this.selectedItemsChange.emit(this.selectedItems.map(i => i.value));
1711
- }
1712
- }
1713
- selected(event) {
1714
- this.selectedItems = [...this.selectedItems];
1715
- const item = this.items().find(s => s.value == event.option.value);
1716
- if (item) {
1717
- this.selectedItems.push(item);
1718
- }
1719
- this.selectedItemsChange.emit(this.selectedItems.map(i => i.value));
1720
- const inputValue = this.input();
1721
- if (inputValue)
1722
- inputValue.nativeElement.value = '';
1723
- this.inputCtrl.setValue(null);
1724
- }
1725
- _filter(value) {
1726
- const filterValue = value.toLowerCase();
1727
- return this.items().filter(item => item.viewValue.toLowerCase().includes(filterValue));
1728
- }
1729
- onCloseClick($event) {
1730
- $event.stopPropagation();
1731
- this.selectedItemsChange.emit([]);
1732
- }
1733
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseMatChipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1734
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: BaseMatChipComponent, isStandalone: true, selector: "ngx-uik-chip-input-autocomplete", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, selectedItemsInput: { classPropertyName: "selectedItemsInput", publicName: "selectedItemsInput", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedItemsChange: "selectedItemsChange" }, viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true, isSignal: true }], ngImport: i0, template: "<mat-form-field class=\"chip-list\" appearance=\"fill\">\r\n <mat-label>{{ title() }}</mat-label>\r\n <mat-chip-grid #chipList aria-label=\"'\u0412\u044B\u0431\u043E\u0440 '+title()\">\r\n @for (item of selectedItems; track item) {\r\n <mat-chip-row color=\"primary\"\r\n (removed)=\"remove(item.value)\">\r\n {{ item.viewValue }}\r\n <button matChipRemove>\r\n <mat-icon>cancel</mat-icon>\r\n </button>\r\n </mat-chip-row>\r\n }\r\n </mat-chip-grid>\r\n <input\r\n #input\r\n [placeholder]=\"'\u0412\u0432\u0435\u0434\u0438\u0442\u0435 '+title()+'...'\"\r\n [formControl]=\"inputCtrl\"\r\n [matAutocomplete]=\"auto\"\r\n [matChipInputFor]=\"chipList\"\r\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\r\n >\r\n <mat-autocomplete #auto=\"matAutocomplete\" (optionSelected)=\"selected($event)\">\r\n @for (item of filteredItems$ | async; track item) {\r\n <mat-option [value]=\"item.value\"\r\n [disabled]=\"selectedItemsInput()?.includes(item.value)\">\r\n {{ item.viewValue }}\r\n </mat-option>\r\n }\r\n </mat-autocomplete>\r\n @if (selectedItems.length > 0) {\r\n <button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"onCloseClick($event)\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n</mat-form-field>\r\n", styles: [".chip-list{width:100%}\n"], dependencies: [{ kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i2.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i2.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i3.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i3.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled", "readonly", "matChipInputDisabledInteractive"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "directive", type: i3.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i3.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "pipe", type: AsyncPipe, name: "async" }] });
1735
- }
1736
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseMatChipComponent, decorators: [{
1737
- type: Component,
1738
- args: [{ selector: 'ngx-uik-chip-input-autocomplete', imports: [MatFormField, AsyncPipe, FormsModule, ReactiveFormsModule, MatAutocompleteModule, MatIcon, MatOption,
1739
- MatChipsModule, MatLabel], template: "<mat-form-field class=\"chip-list\" appearance=\"fill\">\r\n <mat-label>{{ title() }}</mat-label>\r\n <mat-chip-grid #chipList aria-label=\"'\u0412\u044B\u0431\u043E\u0440 '+title()\">\r\n @for (item of selectedItems; track item) {\r\n <mat-chip-row color=\"primary\"\r\n (removed)=\"remove(item.value)\">\r\n {{ item.viewValue }}\r\n <button matChipRemove>\r\n <mat-icon>cancel</mat-icon>\r\n </button>\r\n </mat-chip-row>\r\n }\r\n </mat-chip-grid>\r\n <input\r\n #input\r\n [placeholder]=\"'\u0412\u0432\u0435\u0434\u0438\u0442\u0435 '+title()+'...'\"\r\n [formControl]=\"inputCtrl\"\r\n [matAutocomplete]=\"auto\"\r\n [matChipInputFor]=\"chipList\"\r\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\r\n >\r\n <mat-autocomplete #auto=\"matAutocomplete\" (optionSelected)=\"selected($event)\">\r\n @for (item of filteredItems$ | async; track item) {\r\n <mat-option [value]=\"item.value\"\r\n [disabled]=\"selectedItemsInput()?.includes(item.value)\">\r\n {{ item.viewValue }}\r\n </mat-option>\r\n }\r\n </mat-autocomplete>\r\n @if (selectedItems.length > 0) {\r\n <button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"onCloseClick($event)\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n</mat-form-field>\r\n", styles: [".chip-list{width:100%}\n"] }]
1740
- }], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], selectedItemsInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItemsInput", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], selectedItemsChange: [{ type: i0.Output, args: ["selectedItemsChange"] }], input: [{ type: i0.ViewChild, args: ['input', { isSignal: true }] }] } });
1741
-
1742
- function dateFormat(date) {
1743
- if (date)
1744
- return moment(date).format("YYYY-MM-DD");
1745
- else
1746
- return '';
1747
- }
1748
-
1749
- // See the Moment.js docs for the meaning of these formats:
1750
- // https://momentjs.com/docs/#/displaying/format/
1751
- const MY_FORMATS = {
1752
- parse: {
1753
- dateInput: 'DD.MM.YYYY',
1754
- },
1755
- display: {
1756
- dateInput: 'DD.MM.YYYY',
1757
- monthYearLabel: 'MMM YYYY',
1758
- dateA11yLabel: 'LL',
1759
- monthYearA11yLabel: 'MMMM YYYY',
1760
- },
1761
- };
1762
-
1763
- class DateRangeInputComponent {
1764
- label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
1765
- dateRange = input({ begin: '', end: '' }, ...(ngDevMode ? [{ debugName: "dateRange" }] : []));
1766
- // eslint-disable-next-line no-magic-numbers
1767
- minDate = input(new Date(2020, 0, 1), ...(ngDevMode ? [{ debugName: "minDate" }] : []));
1768
- clearInput = input(null, ...(ngDevMode ? [{ debugName: "clearInput" }] : []));
1769
- required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : []));
1770
- dateRangeChange = output();
1771
- form = new FormGroup({
1772
- begin: new FormControl(),
1773
- end: new FormControl(),
1774
- });
1775
- subscription = new Subscription();
1776
- constructor() {
1777
- effect(() => {
1778
- if (this.clearInput())
1779
- this.form.reset();
1780
- });
1781
- effect(() => {
1782
- const value = this.dateRange();
1783
- if (this.form) {
1784
- this.form.controls['begin'].setValue(value.begin ? new Date(value.begin) : null);
1785
- this.form.controls['end'].setValue(value.end ? new Date(value.begin) : null);
1786
- }
1787
- this.dateRangeChange.emit(this.rangeToDateDateRange(this.form.value));
1788
- });
1789
- }
1790
- ngOnInit() {
1791
- if (this.required()) {
1792
- this.form.controls['begin'].addValidators(Validators.required);
1793
- this.form.controls['end'].addValidators(Validators.required);
1794
- }
1795
- // подписка на изменение периода
1796
- this.form.valueChanges
1797
- .pipe(
1798
- // eslint-disable-next-line no-magic-numbers
1799
- debounceTime(500), distinctUntilChanged())
1800
- .subscribe({
1801
- next: range => {
1802
- if (this.required()) {
1803
- if (range.begin && range.end) {
1804
- this.dateRangeChange.emit(this.rangeToDateDateRange(range));
1805
- }
1806
- }
1807
- else {
1808
- this.dateRangeChange.emit(this.rangeToDateDateRange(range));
1809
- }
1810
- }
1811
- });
1812
- }
1813
- ngOnDestroy() {
1814
- if (this.subscription)
1815
- this.subscription.unsubscribe();
1816
- }
1817
- rangeToDateDateRange(range) {
1818
- return {
1819
- begin: range.begin ? dateFormat(range.begin) : '',
1820
- end: range.end ? dateFormat(range.end) : ''
1821
- };
1822
- }
1823
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: DateRangeInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1824
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.0", type: DateRangeInputComponent, isStandalone: true, selector: "ngx-uik-date-range-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, dateRange: { classPropertyName: "dateRange", publicName: "dateRange", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, clearInput: { classPropertyName: "clearInput", publicName: "clearInput", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateRangeChange: "dateRangeChange" }, providers: [
1825
- { provide: MAT_DATE_LOCALE, useValue: 'ru' },
1826
- { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS },
1827
- ], ngImport: i0, template: "<mat-form-field appearance=\"fill\">\r\n <mat-label>{{label()}}</mat-label>\r\n <mat-date-range-input\r\n [rangePicker]=\"picker\"\r\n [formGroup]=\"form\"\r\n [min]=\"minDate()\">\r\n <input matStartDate formControlName=\"begin\" placeholder=\"\u0414\u0430\u0442\u0430 \u043D\u0430\u0447\u0430\u043B\u0430\">\r\n <input matEndDate formControlName=\"end\" placeholder=\"\u0414\u0430\u0442\u0430 \u043E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u044F\">\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 <mat-error>\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u043F\u0435\u0440\u0438\u043E\u0434</mat-error>\r\n</mat-form-field>\r\n\r\n", styles: ["mat-form-field{margin-right:16px}\n"], dependencies: [{ kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: MatStartDate, selector: "input[matStartDate]", outputs: ["dateChange", "dateInput"] }, { kind: "directive", type: MatEndDate, selector: "input[matEndDate]", outputs: ["dateChange", "dateInput"] }, { kind: "component", type: MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }, { kind: "directive", type: MatError, selector: "mat-error, [matError]", inputs: ["id"] }] });
1828
- }
1829
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: DateRangeInputComponent, decorators: [{
1830
- type: Component,
1831
- args: [{ selector: 'ngx-uik-date-range-input', imports: [MatFormField, MatLabel, MatDateRangeInput, FormsModule, ReactiveFormsModule, MatStartDate, MatEndDate,
1832
- MatDatepickerToggle, MatSuffix, MatDateRangePicker, MatError], providers: [
1833
- { provide: MAT_DATE_LOCALE, useValue: 'ru' },
1834
- { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS },
1835
- ], template: "<mat-form-field appearance=\"fill\">\r\n <mat-label>{{label()}}</mat-label>\r\n <mat-date-range-input\r\n [rangePicker]=\"picker\"\r\n [formGroup]=\"form\"\r\n [min]=\"minDate()\">\r\n <input matStartDate formControlName=\"begin\" placeholder=\"\u0414\u0430\u0442\u0430 \u043D\u0430\u0447\u0430\u043B\u0430\">\r\n <input matEndDate formControlName=\"end\" placeholder=\"\u0414\u0430\u0442\u0430 \u043E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u044F\">\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 <mat-error>\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u043F\u0435\u0440\u0438\u043E\u0434</mat-error>\r\n</mat-form-field>\r\n\r\n", styles: ["mat-form-field{margin-right:16px}\n"] }]
1836
- }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], dateRange: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateRange", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], clearInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearInput", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], dateRangeChange: [{ type: i0.Output, args: ["dateRangeChange"] }] } });
1837
-
1838
- var DialogAction;
1839
- (function (DialogAction) {
1840
- DialogAction["Add"] = "\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C";
1841
- DialogAction["Edit"] = "\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C";
1842
- DialogAction["Delete"] = "\u0423\u0434\u0430\u043B\u0438\u0442\u044C";
1843
- DialogAction["None"] = "";
1844
- })(DialogAction || (DialogAction = {}));
1845
-
1846
- class NavBarComponent extends BaseNavBarMenuClass {
1847
- /** Видимость панели, когда loggedIn === false. */
1848
- visibleOnLogout = input(false, ...(ngDevMode ? [{ debugName: "visibleOnLogout" }] : []));
1849
- /** Видимость аватара. */
1850
- visibleAvatar = input(true, ...(ngDevMode ? [{ debugName: "visibleAvatar" }] : []));
1851
- /** Видимость кнопки "Выйти". */
1852
- visibleLogoutBtn = input(true, ...(ngDevMode ? [{ debugName: "visibleLogoutBtn" }] : []));
1853
- /** Признак, что пользователь авторизован. */
1854
- loggedIn = input(false, ...(ngDevMode ? [{ debugName: "loggedIn" }] : []));
1855
- /** ФИО пользователя. */
1856
- fioUser = input('', ...(ngDevMode ? [{ debugName: "fioUser" }] : []));
1857
- /** Всплывающая подсказка о пользователе. */
1858
- userTooltip = input('', ...(ngDevMode ? [{ debugName: "userTooltip" }] : []));
1859
- /** URL аватара */
1860
- avatarURL = input('', ...(ngDevMode ? [{ debugName: "avatarURL" }] : []));
1861
- /** Нажата кнопка "Выйти". */
1862
- logout = output();
1863
- dialog = inject(MatDialog);
1864
- constructor() {
1865
- super();
1866
- }
1867
- onLogout() {
1868
- this.logout.emit(this.router.url);
1869
- }
1870
- openDialog() {
1871
- const dialogRef = this.dialog.open(DialogComponent, {
1872
- width: '400px',
1873
- data: {
1874
- id: 'logout',
1875
- title: 'Подтверждение',
1876
- message: 'Вы хотите выйти?',
1877
- btnNoTitle: 'Отмена',
1878
- btnYesTitle: 'Выйти'
1879
- }
1880
- });
1881
- const subs = dialogRef.afterClosed().subscribe((id) => {
1882
- if (id) {
1883
- this.onLogout();
1884
- }
1885
- });
1886
- this.subscription.add(subs);
1887
- }
1888
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NavBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1889
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: NavBarComponent, isStandalone: true, selector: "ngx-uik-navbar", inputs: { visibleOnLogout: { classPropertyName: "visibleOnLogout", publicName: "visibleOnLogout", isSignal: true, isRequired: false, transformFunction: null }, visibleAvatar: { classPropertyName: "visibleAvatar", publicName: "visibleAvatar", isSignal: true, isRequired: false, transformFunction: null }, visibleLogoutBtn: { classPropertyName: "visibleLogoutBtn", publicName: "visibleLogoutBtn", isSignal: true, isRequired: false, transformFunction: null }, loggedIn: { classPropertyName: "loggedIn", publicName: "loggedIn", isSignal: true, isRequired: false, transformFunction: null }, fioUser: { classPropertyName: "fioUser", publicName: "fioUser", isSignal: true, isRequired: false, transformFunction: null }, userTooltip: { classPropertyName: "userTooltip", publicName: "userTooltip", isSignal: true, isRequired: false, transformFunction: null }, avatarURL: { classPropertyName: "avatarURL", publicName: "avatarURL", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { logout: "logout" }, usesInheritance: true, ngImport: i0, template: "@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()\">\u0412\u044B\u0439\u0442\u0438 <mat-icon>logout</mat-icon></a>\r\n }\r\n </nav>\r\n}", styles: [".ngx-uik-navbar-header{display:flex;flex-wrap:wrap;align-items:center;padding:8px 16px}.flex-spacer{flex-grow:1}.user-name{margin-left:8px;line-height:1rem;white-space:normal}.user-photo{border-radius:50%;width:32px;height:32px;margin-right:10px}.mat-mdc-button{color:#fff!important;padding-left:16px!important;padding-right:16px!important}.mdc-button{letter-spacing:normal}\n"], dependencies: [{ kind: "component", type: MatAnchor, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: SafePipe, name: "safe" }] });
1890
- }
1891
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NavBarComponent, decorators: [{
1892
- type: Component,
1893
- args: [{ selector: 'ngx-uik-navbar', imports: [MatAnchor, MatIcon, MatTooltip, SafePipe], template: "@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()\">\u0412\u044B\u0439\u0442\u0438 <mat-icon>logout</mat-icon></a>\r\n }\r\n </nav>\r\n}", styles: [".ngx-uik-navbar-header{display:flex;flex-wrap:wrap;align-items:center;padding:8px 16px}.flex-spacer{flex-grow:1}.user-name{margin-left:8px;line-height:1rem;white-space:normal}.user-photo{border-radius:50%;width:32px;height:32px;margin-right:10px}.mat-mdc-button{color:#fff!important;padding-left:16px!important;padding-right:16px!important}.mdc-button{letter-spacing:normal}\n"] }]
1894
- }], ctorParameters: () => [], propDecorators: { visibleOnLogout: [{ type: i0.Input, args: [{ isSignal: true, alias: "visibleOnLogout", required: false }] }], visibleAvatar: [{ type: i0.Input, args: [{ isSignal: true, alias: "visibleAvatar", required: false }] }], visibleLogoutBtn: [{ type: i0.Input, args: [{ isSignal: true, alias: "visibleLogoutBtn", required: false }] }], loggedIn: [{ type: i0.Input, args: [{ isSignal: true, alias: "loggedIn", required: false }] }], fioUser: [{ type: i0.Input, args: [{ isSignal: true, alias: "fioUser", required: false }] }], userTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "userTooltip", required: false }] }], avatarURL: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarURL", required: false }] }], logout: [{ type: i0.Output, args: ["logout"] }] } });
1895
-
1896
- class NotFoundComponent {
1897
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NotFoundComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1898
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.0", type: NotFoundComponent, isStandalone: true, selector: "ngx-uik-not-found", ngImport: i0, template: "<div class=\"center\">\r\n <h3 class=\"mat-display-1\">\u0421\u0442\u0440\u0430\u043D\u0438\u0446\u0430 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u0430</h3>\r\n</div>\r\n", styles: [".center{display:flex;justify-content:center;margin:3rem}\n"] });
1899
- }
1900
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NotFoundComponent, decorators: [{
1901
- type: Component,
1902
- args: [{ selector: 'ngx-uik-not-found', standalone: true, template: "<div class=\"center\">\r\n <h3 class=\"mat-display-1\">\u0421\u0442\u0440\u0430\u043D\u0438\u0446\u0430 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u0430</h3>\r\n</div>\r\n", styles: [".center{display:flex;justify-content:center;margin:3rem}\n"] }]
1903
- }] });
1904
-
1905
- class BaseSelectAutocompleteWithVsComponent {
1906
- // https://stackblitz.com/edit/autocomplete-with-virtual-scroll-dc9u2g
1907
- // Все элементы
1908
- items = input([], ...(ngDevMode ? [{ debugName: "items" }] : []));
1909
- // Выбранный элемент (входной параметр)
1910
- selectedItemInput = input(undefined, ...(ngDevMode ? [{ debugName: "selectedItemInput" }] : []));
1911
- // Заголовок
1912
- title = input('', ...(ngDevMode ? [{ debugName: "title" }] : []));
1913
- // Видимость
1914
- isVisible = input(true, ...(ngDevMode ? [{ debugName: "isVisible" }] : []));
1915
- // Обязательность
1916
- isRequired = input(false, ...(ngDevMode ? [{ debugName: "isRequired" }] : []));
1917
- // Доступность
1918
- isDisabled = input(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
1919
- // Доступность
1920
- width = input('200', ...(ngDevMode ? [{ debugName: "width" }] : []));
1921
- // Выбранный элемент
1922
- selectedItem = linkedSignal(() => this.selectedItemInput(), ...(ngDevMode ? [{ debugName: "selectedItem" }] : []));
1923
- // Событие изменения выбранного элемента
1924
- selectedItemChange = output();
1925
- height = '200px';
1926
- // input элемент
1927
- inputCtrl = new FormControl();
1928
- // отфильтрованные (отображаемые) элементы
1929
- filteredItems = [];
1930
- subscription = new Subscription();
1931
- constructor() {
1932
- effect(() => {
1933
- console.log('ITEMS =', this.items());
1934
- //this.filteredItems = this.items();
1935
- console.log('selectedItem =', this.selectedItemInput());
1936
- if (this.items().length > 0) {
1937
- console.log('filteredItems SET');
1938
- this.setFileredItems(this.items());
1939
- this.inputCtrl.setValue(this.selectedItemInput());
1940
- }
1941
- });
1942
- }
1943
- ngOnInit() {
1944
- // Listen for changes to the input
1945
- const subs = this.inputCtrl.valueChanges
1946
- .pipe(startWith$1(''),
1947
- // eslint-disable-next-line no-magic-numbers
1948
- debounceTime(500), distinctUntilChanged(),
1949
- // Note: If the option value is bound to object, after selecting the option
1950
- // Note: the value will change from string to {}. We want to perform search
1951
- // Note: only when the type is string (no match)
1952
- //filter(q => typeof q === 'string'),
1953
- //tap((v) => console.log('v=', v)),
1954
- map((value) => {
1955
- // Filter the options
1956
- console.log('typeof value =', typeof value);
1957
- if (typeof value === 'undefined') {
1958
- this.setFileredItems(this.items());
1959
- }
1960
- else {
1961
- if (typeof value !== 'object') {
1962
- console.log('v1=', value);
1963
- this.setFileredItems(this.items()
1964
- .filter(option => option.viewValue.toLowerCase().includes(value.toLowerCase())));
1965
- }
1966
- else {
1967
- // typeof value === 'object'
1968
- console.log('v2=', value);
1969
- if (value) {
1970
- // this.predmet = value;
1971
- this.setFileredItems(this.items()
1972
- .filter((option) => option.viewValue.toLowerCase().includes(value.viewValue.toLowerCase())));
1973
- console.log('v3=', value);
1974
- }
1975
- else {
1976
- this.setFileredItems(this.items());
1977
- console.log('v4=', value);
1978
- }
1979
- }
1980
- }
1981
- }))
1982
- .subscribe();
1983
- this.subscription.add(subs);
1984
- if (this.isDisabled()) {
1985
- this.inputCtrl.disable();
1986
- }
1987
- else {
1988
- this.inputCtrl.enable();
1989
- }
1990
- }
1991
- ngOnDestroy() {
1992
- if (this.subscription)
1993
- this.subscription.unsubscribe();
1994
- }
1995
- onSelectedItemChange(item) {
1996
- console.log("onSelectedItemChange, item=", item);
1997
- this.selectedItem.set(item);
1998
- this.selectedItemChange.emit(item);
1999
- }
2000
- onClearClick($event) {
2001
- $event.stopPropagation();
2002
- this.inputCtrl.setValue('');
2003
- }
2004
- displayWithFn(lookup) {
2005
- return lookup ? lookup.viewValue : null;
2006
- }
2007
- setFileredItems(items) {
2008
- this.filteredItems = items;
2009
- // Recompute how big the viewport should be.
2010
- // eslint-disable-next-line no-magic-numbers
2011
- if (items.length < 4) {
2012
- // eslint-disable-next-line no-magic-numbers
2013
- this.height = items.length * 50 + 'px';
2014
- }
2015
- else {
2016
- this.height = '200px';
2017
- }
2018
- console.log('update filteredItems =', this.filteredItems);
2019
- }
2020
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseSelectAutocompleteWithVsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2021
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: BaseSelectAutocompleteWithVsComponent, isStandalone: true, selector: "ngx-uik-select-autocomplete-with-vs", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, selectedItemInput: { classPropertyName: "selectedItemInput", publicName: "selectedItemInput", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, isVisible: { classPropertyName: "isVisible", publicName: "isVisible", isSignal: true, isRequired: false, transformFunction: null }, isRequired: { classPropertyName: "isRequired", publicName: "isRequired", isSignal: true, isRequired: false, transformFunction: null }, isDisabled: { classPropertyName: "isDisabled", publicName: "isDisabled", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedItemChange: "selectedItemChange" }, ngImport: i0, template: "@if (isVisible()) {\r\n <mat-form-field [style.width.px]=\"width()\">\r\n <mat-label>{{ title() }}</mat-label>\r\n <input type=\"text\"\r\n [placeholder]=title()\r\n aria-label=\"Number\"\r\n matInput\r\n (ngModelChange)=\"onSelectedItemChange($event)\"\r\n [formControl]=\"inputCtrl\"\r\n [matAutocomplete]=\"auto\"\r\n [required]=\"isRequired() ? 'required' : ''\"\r\n >\r\n @if (!isDisabled && selectedItem()) {\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\">\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\" class=\"autocomplete-item\">\r\n {{option.viewValue}}\r\n </mat-option>\r\n </cdk-virtual-scroll-viewport>\r\n </mat-autocomplete>\r\n @if (inputCtrl.invalid) {\r\n <mat-error>\u0412\u0432\u0435\u0434\u0438\u0442\u0435 {{title()}}</mat-error>\r\n }\r\n @if (!inputCtrl.value) {\r\n <mat-hint>\u041D\u0430\u0447\u043D\u0438\u0442\u0435 \u0432\u0432\u043E\u0434\u0438\u0442\u044C ...</mat-hint>\r\n }\r\n </mat-form-field>\r\n}", styles: ["mat-form-field{margin-right:12px}.autocomplete-item{height:50px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i2.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i2.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i3$1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i3$1.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i3$1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }] });
2022
- }
2023
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseSelectAutocompleteWithVsComponent, decorators: [{
2024
- type: Component,
2025
- args: [{ selector: 'ngx-uik-select-autocomplete-with-vs', imports: [FormsModule, ReactiveFormsModule, MatAutocompleteModule, MatHint, MatError, MatOption, MatIcon,
2026
- MatFormField, ScrollingModule, MatInput, MatLabel], template: "@if (isVisible()) {\r\n <mat-form-field [style.width.px]=\"width()\">\r\n <mat-label>{{ title() }}</mat-label>\r\n <input type=\"text\"\r\n [placeholder]=title()\r\n aria-label=\"Number\"\r\n matInput\r\n (ngModelChange)=\"onSelectedItemChange($event)\"\r\n [formControl]=\"inputCtrl\"\r\n [matAutocomplete]=\"auto\"\r\n [required]=\"isRequired() ? 'required' : ''\"\r\n >\r\n @if (!isDisabled && selectedItem()) {\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\">\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\" class=\"autocomplete-item\">\r\n {{option.viewValue}}\r\n </mat-option>\r\n </cdk-virtual-scroll-viewport>\r\n </mat-autocomplete>\r\n @if (inputCtrl.invalid) {\r\n <mat-error>\u0412\u0432\u0435\u0434\u0438\u0442\u0435 {{title()}}</mat-error>\r\n }\r\n @if (!inputCtrl.value) {\r\n <mat-hint>\u041D\u0430\u0447\u043D\u0438\u0442\u0435 \u0432\u0432\u043E\u0434\u0438\u0442\u044C ...</mat-hint>\r\n }\r\n </mat-form-field>\r\n}", styles: ["mat-form-field{margin-right:12px}.autocomplete-item{height:50px}\n"] }]
2027
- }], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], selectedItemInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItemInput", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], isVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "isVisible", required: false }] }], isRequired: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRequired", required: false }] }], isDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDisabled", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], selectedItemChange: [{ type: i0.Output, args: ["selectedItemChange"] }] } });
2028
-
2029
- class BaseSelectWithGroupComponent {
2030
- // Все группы
2031
- groups = input([], ...(ngDevMode ? [{ debugName: "groups" }] : []));
2032
- // Выбранные элементы, ключи (BaseSelectItem.value)
2033
- selectedItems = input([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : []));
2034
- // Заголовок
2035
- title = input('', ...(ngDevMode ? [{ debugName: "title" }] : []));
2036
- // Событие изменения выбранных элементов
2037
- selectedItemsChange = output();
2038
- separatorKeysCodes = [ENTER, COMMA];
2039
- control = new FormControl([]);
2040
- constructor() {
2041
- effect(() => {
2042
- if (this.groups().length > 0) {
2043
- this.control.setValue(this.selectedItems().map(i => Number(i)));
2044
- }
2045
- });
2046
- }
2047
- selectionChange($event) {
2048
- this.selectedItemsChange.emit($event.value.map((i) => i.toString()));
2049
- }
2050
- onClearClick($event) {
2051
- $event.stopPropagation();
2052
- // this.control.setValue('');
2053
- this.selectedItemsChange.emit([]);
2054
- }
2055
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseSelectWithGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2056
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: BaseSelectWithGroupComponent, isStandalone: true, selector: "ngx-uik-select-with-group", inputs: { groups: { classPropertyName: "groups", publicName: "groups", isSignal: true, isRequired: false, transformFunction: null }, selectedItems: { classPropertyName: "selectedItems", publicName: "selectedItems", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedItemsChange: "selectedItemsChange" }, ngImport: i0, template: "<mat-form-field class=\"select-with-group\" appearance=\"fill\">\r\n <mat-label>{{ title() }}</mat-label>\r\n <mat-select [formControl]=\"control\" (selectionChange)=\"selectionChange($event)\" multiple>\r\n @for (group of groups(); track group) {\r\n <mat-optgroup [label]=\"group.name\">\r\n @for (item of group.items; track item) {\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 (control.value && control.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", styles: [".select-with-group{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatOption$1, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: MatOptgroup, selector: "mat-optgroup", inputs: ["label", "disabled"], exportAs: ["matOptgroup"] }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatFormField$1, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel$1, selector: "mat-label" }] });
2057
- }
2058
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseSelectWithGroupComponent, decorators: [{
2059
- type: Component,
2060
- args: [{ selector: 'ngx-uik-select-with-group', imports: [FormsModule, ReactiveFormsModule, MatIcon, MatOption$1, MatOptgroup, MatSelect, MatFormField$1, MatLabel$1], template: "<mat-form-field class=\"select-with-group\" appearance=\"fill\">\r\n <mat-label>{{ title() }}</mat-label>\r\n <mat-select [formControl]=\"control\" (selectionChange)=\"selectionChange($event)\" multiple>\r\n @for (group of groups(); track group) {\r\n <mat-optgroup [label]=\"group.name\">\r\n @for (item of group.items; track item) {\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 (control.value && control.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", styles: [".select-with-group{width:100%}\n"] }]
2061
- }], ctorParameters: () => [], propDecorators: { groups: [{ type: i0.Input, args: [{ isSignal: true, alias: "groups", required: false }] }], selectedItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItems", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], selectedItemsChange: [{ type: i0.Output, args: ["selectedItemsChange"] }] } });
2062
-
2063
- class TableComponent {
2064
- /** Отображаемые данные. */
2065
- data = input([], ...(ngDevMode ? [{ debugName: "data" }] : []));
2066
- /** Количество записей. */
2067
- length = input(0, ...(ngDevMode ? [{ debugName: "length" }] : []));
2068
- /** Настройки колонок. */
2069
- columnOptions = input([], ...(ngDevMode ? [{ debugName: "columnOptions" }] : []));
2070
- /** Состояние сортировки, пагинации. */
2071
- tableState = input.required(...(ngDevMode ? [{ debugName: "tableState" }] : []));
2072
- /** Разрешен выбор нескольких строк. */
2073
- allowMultiSelect = input(false, ...(ngDevMode ? [{ debugName: "allowMultiSelect" }] : []));
2074
- /** Список элементов контекстного меню. */
2075
- opt = input([], ...(ngDevMode ? [{ debugName: "opt" }] : []));
2076
- /** Отправка события rowDoubleClicked (при двойном щелчке мышью) отключена. */
2077
- rowDblClickedDisable = input(false, ...(ngDevMode ? [{ debugName: "rowDblClickedDisable" }] : []));
2078
- /** Отображать строку с итогом. */
2079
- footer = input(false, ...(ngDevMode ? [{ debugName: "footer" }] : []));
2080
- /** Изменение страницы. */
2081
- pageStateChange = output();
2082
- /** Изменение сортировки. */
2083
- sortStateChange = output();
2084
- /** Изменение выбранных записей. */
2085
- selectionChange = output();
2086
- /** Двойной щелчек ЛКМ*/
2087
- rowDoubleClicked = output();
2088
- sort = viewChild(MatSort, ...(ngDevMode ? [{ debugName: "sort" }] : []));
2089
- paginator = viewChild(MatPaginator, ...(ngDevMode ? [{ debugName: "paginator" }] : []));
2090
- contextMenu = viewChild(MatMenuTrigger, ...(ngDevMode ? [{ debugName: "contextMenu" }] : []));
2091
- pageState = linkedSignal(() => {
2092
- return { pageIndex: this.tableState().pageIndex, pageSize: this.tableState().pageSize };
2093
- }, ...(ngDevMode ? [{ debugName: "pageState" }] : []));
2094
- sortState = linkedSignal(() => {
2095
- return { sortActive: this.tableState().sortActive, sortDirection: this.tableState().sortDirection };
2096
- }, ...(ngDevMode ? [{ debugName: "sortState" }] : []));
2097
- /** Выбранная строка, для которого будет показываться меню при нажатии правой кнопки мыши. */
2098
- itemForMenu;
2099
- /** Позиция в которой отображается контекстное меню. */
2100
- contextMenuPosition = { x: '0px', y: '0px' };
2101
- // eslint-disable-next-line no-magic-numbers
2102
- defaultPageIndex = 0;
2103
- // eslint-disable-next-line no-magic-numbers
2104
- defaultPageSize = 10;
2105
- /** Источник данных для отображения. */
2106
- dataSource = new MatTableDataSource();
2107
- /** Выбранные записи. */
2108
- selection = new SelectionModel();
2109
- /** Список отображаемых колонок (формируется из @columnOptions). */
2110
- displayedColumns;
2111
- subscription = new Subscription();
2112
- constructor() {
2113
- effect(() => {
2114
- this.dataSource.data = this.data();
2115
- // сохранить выделенные строки, если они все еще есть в данных
2116
- const selected = this.selection.selected;
2117
- this.selection.clear();
2118
- this.data().filter(v => selected.map(s => JSON.stringify(s)).includes(JSON.stringify(v))).map(d => {
2119
- this.selection.select(d);
2120
- });
2121
- });
2122
- }
2123
- ngOnInit() {
2124
- this.displayedColumns = ['select'].concat(this.columnOptions()?.filter(c => !c.hide).map((item) => item.name) || []);
2125
- // пересоздаем, т.к. параметр allowMultiSelect появляется только сейчас
2126
- this.selection = new SelectionModel(this.allowMultiSelect());
2127
- }
2128
- ngOnDestroy() {
2129
- if (this.subscription)
2130
- this.subscription.unsubscribe();
2131
- }
2132
- ngAfterViewInit() {
2133
- // подписи элементов управления пагинатора (MatPaginatorIntl)
2134
- const paginator = this.paginator();
2135
- if (paginator) {
2136
- paginator._intl.itemsPerPageLabel = 'Записей на странице';
2137
- paginator._intl.firstPageLabel = 'Первая страница';
2138
- paginator._intl.previousPageLabel = 'Предыдущая страница';
2139
- paginator._intl.nextPageLabel = 'Следующая страница';
2140
- paginator._intl.lastPageLabel = 'Последняя страница';
2141
- // изменение пагинации
2142
- const subs = paginator.page.subscribe(page => {
2143
- const pageState = {
2144
- pageIndex: page.pageIndex,
2145
- pageSize: page.pageSize
2146
- };
2147
- this.pageState.set(pageState);
2148
- this.pageStateChange.emit(pageState);
2149
- });
2150
- this.subscription.add(subs);
2151
- }
2152
- // изменение сортировки
2153
- const sortValue = this.sort();
2154
- if (sortValue) {
2155
- const subs = sortValue.sortChange
2156
- .subscribe(sort => {
2157
- const sortState = {
2158
- sortActive: sort.active,
2159
- sortDirection: sort.direction
2160
- };
2161
- this.sortState.set(sortState);
2162
- this.sortStateChange.emit(sortState);
2163
- });
2164
- this.subscription.add(subs);
2165
- }
2166
- // изменение выбранных записей
2167
- if (this.selection) {
2168
- const subs = this.selection.changed.subscribe(change => {
2169
- this.selectionChange.emit(change.source.selected);
2170
- });
2171
- this.subscription.add(subs);
2172
- }
2173
- }
2174
- /** Whether the number of selected elements matches the total number of rows. */
2175
- isAllSelected() {
2176
- const numSelected = this.selection.selected.length;
2177
- const numRows = this.dataSource.data.length;
2178
- return numSelected === numRows;
2179
- }
2180
- /** Selects all rows if they are not all selected; otherwise clear selection. */
2181
- masterToggle() {
2182
- console.log(this.selection.isMultipleSelection());
2183
- if (this.isAllSelected()) {
2184
- this.selection.clear();
2185
- }
2186
- else {
2187
- this.dataSource.data.forEach(row => this.selection.select(row));
2188
- }
2189
- }
2190
- /** При щелчке по строке. */
2191
- onRowClicked(row) {
2192
- // выделение строки при щелчке по строке
2193
- if (this.selection.isSelected(row)) {
2194
- this.selection.deselect(row);
2195
- }
2196
- else {
2197
- this.selection.select(row);
2198
- }
2199
- }
2200
- /** При двойном щелчке по строке. */
2201
- onRowDblClicked(row) {
2202
- // выделение строки при двойном щелчке по строке
2203
- this.selection.clear();
2204
- this.selection.select(row);
2205
- if (!this.rowDblClickedDisable())
2206
- this.rowDoubleClicked.emit(row);
2207
- }
2208
- /** При вызове контекстного меню. */
2209
- onContextMenu(event, itemForMenu) {
2210
- if (this.opt() && this.opt().length === 0) {
2211
- // если нет пунктов меню, то не показываем меню
2212
- return;
2213
- }
2214
- event.preventDefault();
2215
- this.itemForMenu = itemForMenu;
2216
- this.contextMenuPosition.x = event.clientX + 'px';
2217
- this.contextMenuPosition.y = event.clientY + 'px';
2218
- // как это (menuData) использовать в шаблоне не понятно, поэтому использую this.itemForMenu
2219
- // https://www.concretepage.com/angular-material/passing-data-to-mat-menu-angular-material
2220
- const contextMenu = this.contextMenu();
2221
- if (contextMenu) {
2222
- contextMenu.menuData = { itemForMenu };
2223
- contextMenu.menu?.focusFirstItem('mouse');
2224
- contextMenu.openMenu();
2225
- }
2226
- }
2227
- getTotal(columnName) {
2228
- const arr = this.dataSource.data
2229
- .filter(t => typeof t[columnName] === 'number')
2230
- .map(t => t[columnName]);
2231
- if (arr.length === 0)
2232
- return '';
2233
- else
2234
- return arr.reduce((acc, value) => acc + value, 0);
2235
- }
2236
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2237
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: TableComponent, isStandalone: true, selector: "ngx-uik-table", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null }, columnOptions: { classPropertyName: "columnOptions", publicName: "columnOptions", isSignal: true, isRequired: false, transformFunction: null }, tableState: { classPropertyName: "tableState", publicName: "tableState", isSignal: true, isRequired: true, transformFunction: null }, allowMultiSelect: { classPropertyName: "allowMultiSelect", publicName: "allowMultiSelect", isSignal: true, isRequired: false, transformFunction: null }, opt: { classPropertyName: "opt", publicName: "opt", isSignal: true, isRequired: false, transformFunction: null }, rowDblClickedDisable: { classPropertyName: "rowDblClickedDisable", publicName: "rowDblClickedDisable", isSignal: true, isRequired: false, transformFunction: null }, footer: { classPropertyName: "footer", publicName: "footer", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pageStateChange: "pageStateChange", sortStateChange: "sortStateChange", selectionChange: "selectionChange", rowDoubleClicked: "rowDoubleClicked" }, viewQueries: [{ propertyName: "sort", first: true, predicate: MatSort, descendants: true, isSignal: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true, isSignal: true }, { propertyName: "contextMenu", first: true, predicate: MatMenuTrigger, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"component-container\">\r\n <div class=\"table-container\">\r\n <table mat-table [dataSource]=\"dataSource\"\r\n matSort\r\n [matSortActive]=\"sortState().sortActive || ''\"\r\n [matSortDirection]=\"sortState().sortDirection\"\r\n matSortDisableClear>\r\n\r\n <!-- \u0412\u044B\u0431\u043E\u0440 \u0441\u0442\u0440\u043E\u043A\u0438 Column -->\r\n <ng-container matColumnDef=\"select\">\r\n <th mat-header-cell *matHeaderCellDef>\r\n @if (allowMultiSelect()) {\r\n <mat-checkbox (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\"\r\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\">\r\n </mat-checkbox>\r\n }\r\n </th>\r\n <td mat-cell *matCellDef=\"let row\">\r\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(row) : null\"\r\n [checked]=\"selection.isSelected(row)\">\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) {\r\n <ng-container matColumnDef={{item.name}}>\r\n <th mat-header-cell *matHeaderCellDef mat-sort-header [disabled]=\"item.titleSortDisable\">{{item.title}}</th>\r\n @if (!item.format) {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\" [matTooltip]=\"item.tooltip ?? ''\">\r\n {{element[item.name]}}\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footer) {\r\n <strong>{{ getTotal(item.name) }}</strong>\r\n }\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n } \r\n }\r\n @if (item.format === 'pre-wrap') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\" class=\"pre-wrap\" [matTooltip]=\"item.tooltip ?? ''\">\r\n {{element[item.name]}}\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n @if (item.format === 'link') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\" [matTooltip]=\"item.tooltip ?? ''\">\r\n <a [href]=\"element[item.name]\" target=\"_blank\">{{element[item.name]}}</a>\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n @if (item.format === 'linkIcon') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\" [matTooltip]=\"item.tooltip ?? ''\">\r\n @if (element[item.name]) {\r\n <a [href]=\"element[item.name]\" target=\"_blank\">\r\n @if (item.icon) {\r\n <mat-icon [class]=\"item.classList ? item.classList : ''\" >{{item.icon}}</mat-icon>\r\n } \r\n @if (item.symbol) {\r\n <span [class]=\"item.classList ? item.classList : ''\" >{{item.symbol}}</span>\r\n }\r\n </a>\r\n }\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n @if (item.format === 'routerLink') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\" [matTooltip]=\"item.tooltip ?? ''\">\r\n <a [routerLink]=\"[element[item.name]]\">{{element[item.name]}}</a>\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n @if (item.format === 'routerLinkIcon') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\" [matTooltip]=\"item.tooltip ?? ''\">\r\n @if (element[item.name]) {\r\n <a [routerLink]=\"[element[item.name]]\">\r\n @if (item.icon) {\r\n <mat-icon [class]=\"item.classList ? item.classList : ''\" >{{item.icon}}</mat-icon>\r\n } \r\n @if (item.symbol) {\r\n <span [class]=\"item.classList ? item.classList : ''\" >{{item.symbol}}</span>\r\n }\r\n </a>\r\n }\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n @if (item.format === 'checkbox') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\" [matTooltip]=\"item.tooltip ?? ''\">\r\n <mat-checkbox [checked]=\"element[item.name] === 1\" [disabled]=\"true\"></mat-checkbox>\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n @if (item.format === 'icon') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\" [matTooltip]=\"item.tooltip ?? ''\">\r\n @if (item.icon) {\r\n <mat-icon [class]=\"item.classList ? item.classList : ''\" >{{item.icon}}</mat-icon>\r\n } \r\n @if (item.symbol) {\r\n <span [class]=\"item.classList ? item.classList : ''\" >{{item.symbol}}</span>\r\n }\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n @if (item.format === 'icons') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\">\r\n @if (item.icons) {\r\n <mat-icon [class]=\"item.classList ? item.classList[element[item.name]] : ''\" \r\n [matTooltip]=\"item.tooltips ? item.tooltips[element[item.name]] : ''\">{{item.icons[element[item.name]]}}</mat-icon>\r\n } \r\n @if (item.symbols) {\r\n <span [class]=\"item.classList ? item.classList[element[item.name]] : ''\" >{{item.symbols[element[item.name]]}}</span>\r\n }\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n @if (item.format === 'actions') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\">\r\n @if (item.actions) {\r\n <div class=\"actions-container\">\r\n @for (action of item.actions; track action) {\r\n @if (!(action.hideFn ? action.hideFn(element) : action.hide)) {\r\n <button mat-icon-button\r\n (click)=\"action.onClickFn ? action.onClickFn(element) : ''\"\r\n (mousedown)=\"action.onClickMiddleFn ? action.onClickMiddleFn($event, element) : ''\"\r\n [disabled]=\"action.disabledFn ? action.disabledFn(element) : action.disabled\"\r\n [matTooltip]=\"action.tooltip ? action.tooltip : ''\" >\r\n @if (action.icon) {\r\n <mat-icon [class]=\"action.classList ? action.classList : ''\" >{{action.icon}}</mat-icon>\r\n }\r\n @if (action.symbol) {\r\n <span [class]=\"action.classList ? action.classList : ''\" >{{action.symbol}}</span>\r\n }\r\n {{ action.title }}\r\n </button>\r\n }\r\n }\r\n </div>\r\n } \r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n @if (item.format === 'image') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\" [matTooltip]=\"item.tooltip ?? ''\">\r\n @if (element[item.name]) {\r\n <img\r\n [src]=\"element[item.name]\"\r\n [alt]=\"item.imageAlt && element[item.imageAlt] ? element[item.imageAlt] : ''\"\r\n [class]=\"item.classList ? item.classList : ''\"\r\n />\r\n } \r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n </ng-container>\r\n }\r\n\r\n <tr class=\"mat-row\" *matNoDataRow>\r\n <td class=\"mat-cell\" colspan=\"9999\">\r\n \u041D\u0435\u0442 \u0434\u0430\u043D\u043D\u044B\u0445 \u0434\u043B\u044F \u043E\u0442\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F\r\n </td>\r\n </tr>\r\n\r\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\r\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\" \r\n (click)=\"onRowClicked(row)\" (dblclick)=\"onRowDblClicked(row)\" \r\n class=\"element-row\" [class.selected-row]=\"selection.isSelected(row)\">\r\n </tr>\r\n @if (footer()) {\r\n <tr mat-footer-row *matFooterRowDef=\"displayedColumns; sticky: true\"></tr>\r\n }\r\n </table>\r\n <div style=\"visibility: hidden; position: fixed\"\r\n [style.left]=\"contextMenuPosition.x\"\r\n [style.top]=\"contextMenuPosition.y\"\r\n [matMenuTriggerFor]=\"contextMenu\" #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 (menuItem.title === '-' && !(menuItem.hideFn ? menuItem.hideFn(itemForMenu) : menuItem.hide)) {\r\n <mat-divider></mat-divider>\r\n }\r\n @if (menuItem.title !== '-' && !(menuItem.hideFn ? menuItem.hideFn(itemForMenu) : menuItem.hide)) {\r\n <button mat-menu-item\r\n (click)=\"menuItem.onClickFn ? menuItem.onClickFn(itemForMenu) : ''\"\r\n (mousedown)=\"menuItem.onClickMiddleFn ? menuItem.onClickMiddleFn($event, itemForMenu, menuTrigger) : ''\"\r\n [disabled]=\"menuItem.disabledFn ? menuItem.disabledFn(itemForMenu) : menuItem.disabled\">\r\n @if (menuItem.icon) {\r\n <mat-icon [class]=\"menuItem.classList ? menuItem.classList : ''\">{{menuItem.icon}}</mat-icon>\r\n }\r\n @if (menuItem.symbol) {\r\n <span [class]=\"menuItem.classList ? menuItem.classList : ''\">{{menuItem.symbol}}</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\r\n<mat-paginator [length]=\"length()\"\r\n [pageIndex]=\"pageState().pageIndex || defaultPageIndex\"\r\n [pageSizeOptions]=\"[5, 10, 20, 50, 100]\"\r\n [pageSize]=\"pageState().pageSize || defaultPageSize\"\r\n showFirstLastButtons\r\n itemsPerPageLabel=\"\"\r\n></mat-paginator>\r\n</div>\r\n", styles: [".component-container{display:flex;flex-direction:column;height:100%}.table-container{display:flex;flex-direction:column;justify-content:space-between;flex:auto;margin:0 20px;overflow:auto;height:400px}.center{position:absolute;inset:0 0 56px;background:#00000026;z-index:1;display:flex;align-items:center;justify-content:center}.mat-column-select{overflow:initial}tr.mat-footer-row{font-weight:700;height:56px}.mat-table{overflow-x:scroll}.mat-cell,.mat-header-cell{word-wrap:initial;display:table-cell;padding:0 10px;line-break:unset;white-space:nowrap;overflow:hidden;vertical-align:middle}.mat-row,.mat-header-row{display:table-row}tr.element-row:not(.selected-row):hover{background:#f5f5f5}tr.element-row:not(.selected-row):active{background:#efefef}.selected-row{background-color:#eee}.fact-done-row{background-color:#eefdec}a,a:visited,a:hover,a:active{color:inherit}.pre-wrap{white-space:pre-wrap}.actions-container{display:flex;column-gap:5px}\n"], dependencies: [{ kind: "component", type: MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "directive", type: MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "component", type: MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "directive", type: MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: MatNoDataRow, selector: "ng-template[matNoDataRow]" }, { kind: "directive", type: MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "component", type: MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "directive", type: MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "component", type: MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "directive", type: MatMenuContent, selector: "ng-template[matMenuContent]" }, { kind: "component", type: MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "component", type: MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "directive", type: MatFooterRowDef, selector: "[matFooterRowDef]", inputs: ["matFooterRowDef", "matFooterRowDefSticky"] }, { kind: "component", type: MatFooterRow, selector: "mat-footer-row, tr[mat-footer-row]", exportAs: ["matFooterRow"] }, { kind: "directive", type: MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "ngmodule", type: MatTableModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i1$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }] });
2238
- }
2239
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TableComponent, decorators: [{
2240
- type: Component,
2241
- args: [{ selector: 'ngx-uik-table', imports: [MatTable, MatSort, MatColumnDef, MatHeaderCellDef, MatHeaderCell, MatCheckbox, MatCellDef, MatCell,
2242
- MatSortHeader, MatIcon, RouterLink, MatNoDataRow, MatHeaderRowDef, MatHeaderRow, MatRowDef, MatRow,
2243
- MatMenuTrigger, MatMenu, MatMenuContent, MatDivider, MatMenuItem, MatPaginator, MatFooterRowDef, MatFooterRow,
2244
- MatFooterCellDef, MatFooterCell, MatTableModule, MatTooltipModule, MatIconButton], template: "<div class=\"component-container\">\r\n <div class=\"table-container\">\r\n <table mat-table [dataSource]=\"dataSource\"\r\n matSort\r\n [matSortActive]=\"sortState().sortActive || ''\"\r\n [matSortDirection]=\"sortState().sortDirection\"\r\n matSortDisableClear>\r\n\r\n <!-- \u0412\u044B\u0431\u043E\u0440 \u0441\u0442\u0440\u043E\u043A\u0438 Column -->\r\n <ng-container matColumnDef=\"select\">\r\n <th mat-header-cell *matHeaderCellDef>\r\n @if (allowMultiSelect()) {\r\n <mat-checkbox (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\"\r\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\">\r\n </mat-checkbox>\r\n }\r\n </th>\r\n <td mat-cell *matCellDef=\"let row\">\r\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(row) : null\"\r\n [checked]=\"selection.isSelected(row)\">\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) {\r\n <ng-container matColumnDef={{item.name}}>\r\n <th mat-header-cell *matHeaderCellDef mat-sort-header [disabled]=\"item.titleSortDisable\">{{item.title}}</th>\r\n @if (!item.format) {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\" [matTooltip]=\"item.tooltip ?? ''\">\r\n {{element[item.name]}}\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footer) {\r\n <strong>{{ getTotal(item.name) }}</strong>\r\n }\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n } \r\n }\r\n @if (item.format === 'pre-wrap') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\" class=\"pre-wrap\" [matTooltip]=\"item.tooltip ?? ''\">\r\n {{element[item.name]}}\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n @if (item.format === 'link') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\" [matTooltip]=\"item.tooltip ?? ''\">\r\n <a [href]=\"element[item.name]\" target=\"_blank\">{{element[item.name]}}</a>\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n @if (item.format === 'linkIcon') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\" [matTooltip]=\"item.tooltip ?? ''\">\r\n @if (element[item.name]) {\r\n <a [href]=\"element[item.name]\" target=\"_blank\">\r\n @if (item.icon) {\r\n <mat-icon [class]=\"item.classList ? item.classList : ''\" >{{item.icon}}</mat-icon>\r\n } \r\n @if (item.symbol) {\r\n <span [class]=\"item.classList ? item.classList : ''\" >{{item.symbol}}</span>\r\n }\r\n </a>\r\n }\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n @if (item.format === 'routerLink') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\" [matTooltip]=\"item.tooltip ?? ''\">\r\n <a [routerLink]=\"[element[item.name]]\">{{element[item.name]}}</a>\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n @if (item.format === 'routerLinkIcon') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\" [matTooltip]=\"item.tooltip ?? ''\">\r\n @if (element[item.name]) {\r\n <a [routerLink]=\"[element[item.name]]\">\r\n @if (item.icon) {\r\n <mat-icon [class]=\"item.classList ? item.classList : ''\" >{{item.icon}}</mat-icon>\r\n } \r\n @if (item.symbol) {\r\n <span [class]=\"item.classList ? item.classList : ''\" >{{item.symbol}}</span>\r\n }\r\n </a>\r\n }\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n @if (item.format === 'checkbox') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\" [matTooltip]=\"item.tooltip ?? ''\">\r\n <mat-checkbox [checked]=\"element[item.name] === 1\" [disabled]=\"true\"></mat-checkbox>\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n @if (item.format === 'icon') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\" [matTooltip]=\"item.tooltip ?? ''\">\r\n @if (item.icon) {\r\n <mat-icon [class]=\"item.classList ? item.classList : ''\" >{{item.icon}}</mat-icon>\r\n } \r\n @if (item.symbol) {\r\n <span [class]=\"item.classList ? item.classList : ''\" >{{item.symbol}}</span>\r\n }\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n @if (item.format === 'icons') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\">\r\n @if (item.icons) {\r\n <mat-icon [class]=\"item.classList ? item.classList[element[item.name]] : ''\" \r\n [matTooltip]=\"item.tooltips ? item.tooltips[element[item.name]] : ''\">{{item.icons[element[item.name]]}}</mat-icon>\r\n } \r\n @if (item.symbols) {\r\n <span [class]=\"item.classList ? item.classList[element[item.name]] : ''\" >{{item.symbols[element[item.name]]}}</span>\r\n }\r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n @if (item.format === 'actions') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\">\r\n @if (item.actions) {\r\n <div class=\"actions-container\">\r\n @for (action of item.actions; track action) {\r\n @if (!(action.hideFn ? action.hideFn(element) : action.hide)) {\r\n <button mat-icon-button\r\n (click)=\"action.onClickFn ? action.onClickFn(element) : ''\"\r\n (mousedown)=\"action.onClickMiddleFn ? action.onClickMiddleFn($event, element) : ''\"\r\n [disabled]=\"action.disabledFn ? action.disabledFn(element) : action.disabled\"\r\n [matTooltip]=\"action.tooltip ? action.tooltip : ''\" >\r\n @if (action.icon) {\r\n <mat-icon [class]=\"action.classList ? action.classList : ''\" >{{action.icon}}</mat-icon>\r\n }\r\n @if (action.symbol) {\r\n <span [class]=\"action.classList ? action.classList : ''\" >{{action.symbol}}</span>\r\n }\r\n {{ action.title }}\r\n </button>\r\n }\r\n }\r\n </div>\r\n } \r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n @if (item.format === 'image') {\r\n <td mat-cell *matCellDef=\"let element\" (contextmenu)=\"onContextMenu($event, element)\" [matTooltip]=\"item.tooltip ?? ''\">\r\n @if (element[item.name]) {\r\n <img\r\n [src]=\"element[item.name]\"\r\n [alt]=\"item.imageAlt && element[item.imageAlt] ? element[item.imageAlt] : ''\"\r\n [class]=\"item.classList ? item.classList : ''\"\r\n />\r\n } \r\n </td>\r\n @if (footer()) {\r\n <td mat-footer-cell *matFooterCellDef>\r\n @if (item.footerTitle) {\r\n <strong>{{ item.footerTitle }}</strong>\r\n }\r\n </td>\r\n }\r\n }\r\n </ng-container>\r\n }\r\n\r\n <tr class=\"mat-row\" *matNoDataRow>\r\n <td class=\"mat-cell\" colspan=\"9999\">\r\n \u041D\u0435\u0442 \u0434\u0430\u043D\u043D\u044B\u0445 \u0434\u043B\u044F \u043E\u0442\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F\r\n </td>\r\n </tr>\r\n\r\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\r\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\" \r\n (click)=\"onRowClicked(row)\" (dblclick)=\"onRowDblClicked(row)\" \r\n class=\"element-row\" [class.selected-row]=\"selection.isSelected(row)\">\r\n </tr>\r\n @if (footer()) {\r\n <tr mat-footer-row *matFooterRowDef=\"displayedColumns; sticky: true\"></tr>\r\n }\r\n </table>\r\n <div style=\"visibility: hidden; position: fixed\"\r\n [style.left]=\"contextMenuPosition.x\"\r\n [style.top]=\"contextMenuPosition.y\"\r\n [matMenuTriggerFor]=\"contextMenu\" #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 (menuItem.title === '-' && !(menuItem.hideFn ? menuItem.hideFn(itemForMenu) : menuItem.hide)) {\r\n <mat-divider></mat-divider>\r\n }\r\n @if (menuItem.title !== '-' && !(menuItem.hideFn ? menuItem.hideFn(itemForMenu) : menuItem.hide)) {\r\n <button mat-menu-item\r\n (click)=\"menuItem.onClickFn ? menuItem.onClickFn(itemForMenu) : ''\"\r\n (mousedown)=\"menuItem.onClickMiddleFn ? menuItem.onClickMiddleFn($event, itemForMenu, menuTrigger) : ''\"\r\n [disabled]=\"menuItem.disabledFn ? menuItem.disabledFn(itemForMenu) : menuItem.disabled\">\r\n @if (menuItem.icon) {\r\n <mat-icon [class]=\"menuItem.classList ? menuItem.classList : ''\">{{menuItem.icon}}</mat-icon>\r\n }\r\n @if (menuItem.symbol) {\r\n <span [class]=\"menuItem.classList ? menuItem.classList : ''\">{{menuItem.symbol}}</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\r\n<mat-paginator [length]=\"length()\"\r\n [pageIndex]=\"pageState().pageIndex || defaultPageIndex\"\r\n [pageSizeOptions]=\"[5, 10, 20, 50, 100]\"\r\n [pageSize]=\"pageState().pageSize || defaultPageSize\"\r\n showFirstLastButtons\r\n itemsPerPageLabel=\"\"\r\n></mat-paginator>\r\n</div>\r\n", styles: [".component-container{display:flex;flex-direction:column;height:100%}.table-container{display:flex;flex-direction:column;justify-content:space-between;flex:auto;margin:0 20px;overflow:auto;height:400px}.center{position:absolute;inset:0 0 56px;background:#00000026;z-index:1;display:flex;align-items:center;justify-content:center}.mat-column-select{overflow:initial}tr.mat-footer-row{font-weight:700;height:56px}.mat-table{overflow-x:scroll}.mat-cell,.mat-header-cell{word-wrap:initial;display:table-cell;padding:0 10px;line-break:unset;white-space:nowrap;overflow:hidden;vertical-align:middle}.mat-row,.mat-header-row{display:table-row}tr.element-row:not(.selected-row):hover{background:#f5f5f5}tr.element-row:not(.selected-row):active{background:#efefef}.selected-row{background-color:#eee}.fact-done-row{background-color:#eefdec}a,a:visited,a:hover,a:active{color:inherit}.pre-wrap{white-space:pre-wrap}.actions-container{display:flex;column-gap:5px}\n"] }]
2245
- }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", required: false }] }], columnOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnOptions", required: false }] }], tableState: [{ type: i0.Input, args: [{ isSignal: true, alias: "tableState", required: true }] }], allowMultiSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowMultiSelect", required: false }] }], opt: [{ type: i0.Input, args: [{ isSignal: true, alias: "opt", required: false }] }], rowDblClickedDisable: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowDblClickedDisable", required: false }] }], footer: [{ type: i0.Input, args: [{ isSignal: true, alias: "footer", required: false }] }], pageStateChange: [{ type: i0.Output, args: ["pageStateChange"] }], sortStateChange: [{ type: i0.Output, args: ["sortStateChange"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], rowDoubleClicked: [{ type: i0.Output, args: ["rowDoubleClicked"] }], sort: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatSort), { isSignal: true }] }], paginator: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatPaginator), { isSignal: true }] }], contextMenu: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatMenuTrigger), { isSignal: true }] }] } });
2246
-
2247
- /*
2248
- * Public API Surface of uikit
2249
- */
2250
-
2251
298
  /**
2252
299
  * Generated bundle index. Do not edit.
2253
300
  */
2254
301
 
2255
- export { Action, AlertService, AuthService, AvatarService, BaseEditClass, BaseFilterClass, BaseMatChipComponent, BaseNavBarMenuClass, BasePageClass, BaseSelectAutocompleteWithVsComponent, BaseSelectWithGroupComponent, BaseServiceClass, BaseToolbarComponent, DateRangeInputComponent, DialogAction, DialogComponent, DisableIfRoleDirective, DisableIfUnauthorizedDirective, EntityAction, Environment, ExportService, HideIfRoleNotDirective, HideIfUnauthorizedDirective, LoaderService, LocalStorageService, LoginPageComponent, MY_FORMATS, NavBarComponent, NotFoundComponent, ProgressSpinnerComponent, RedirectGuard, RoleService, SafePipe, SecUser, SetValueDirective, SseService, TableComponent, TimePipe, TruncatePipe, User, UserService, authGuard, dateFormat, roleGuard };
302
+ export { API_NAME, AuthEventService, AuthService, BYPASS_AUTH, NotificationService, RoleService, UIKIT_CONFIG, UIKIT_NOTIFICATION_TOKEN, User, UserService };
2256
303
  //# sourceMappingURL=kuzntsv-uikit.mjs.map