@nettyapps/ntybase 21.0.33 → 21.0.35-beta.1

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,37 +1,37 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, Injectable, inject, NgModule, signal, input, output, computed, effect, ViewChild, model, InjectionToken, Optional, Inject, Input, makeEnvironmentProviders, provideAppInitializer } from '@angular/core';
3
- import * as i1$2 from '@angular/common/http';
2
+ import { Component, Injectable, inject, NgModule, signal, input, computed, output, effect, ViewChild, model, Input, InjectionToken, Optional, Inject } from '@angular/core';
3
+ import * as i1$3 from '@angular/common/http';
4
4
  import { HttpErrorResponse, HttpResponse, HTTP_INTERCEPTORS, HttpClient, HttpHeaders } from '@angular/common/http';
5
- import { of, throwError, lastValueFrom, map, catchError as catchError$1, Subject, finalize, take as take$1, takeUntil } from 'rxjs';
5
+ import { of, throwError, Subject, lastValueFrom, map, catchError as catchError$1, finalize, take as take$1, takeUntil } from 'rxjs';
6
6
  import { catchError, map as map$1, take, finalize as finalize$1 } from 'rxjs/operators';
7
7
  import { Router, ActivatedRoute } from '@angular/router';
8
- import * as i2$1 from '@nettyapps/ntycontract';
9
- import { EnvironmentProxy } from '@nettyapps/ntycontract';
8
+ import * as i2$2 from '@nettyapps/ntycontract';
9
+ import { EnvironmentProxy, injectNettyStandardProxy, injectNettyStandardLogProxy } from '@nettyapps/ntycontract';
10
10
  import { DatePipe, CommonModule, Location, DecimalPipe } from '@angular/common';
11
11
  import { toSignal } from '@angular/core/rxjs-interop';
12
- import { Buffer } from 'buffer';
13
12
  import * as i1 from '@angular/material/dialog';
14
13
  import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule, MatDialog } from '@angular/material/dialog';
15
- import * as i3 from '@angular/material/divider';
16
- import { MatDividerModule } from '@angular/material/divider';
14
+ import { ModuleRegistry, AllCommunityModule, ClientSideRowModelModule, HighlightChangesModule } from 'ag-grid-community';
15
+ import { themeQuartz, StatusBarModule, ClipboardModule, ExcelExportModule, ColumnMenuModule, ContextMenuModule, CellSelectionModule, RowSelectionModule } from 'ag-grid-enterprise';
17
16
  import * as i2 from '@angular/material/icon';
18
17
  import { MatIconModule } from '@angular/material/icon';
19
- import * as i1$1 from '@angular/material/snack-bar';
20
- import { MatSnackBarModule } from '@angular/material/snack-bar';
21
- import * as i3$1 from '@ngx-translate/core';
22
- import { TranslateModule, TranslateService } from '@ngx-translate/core';
23
- import { Mutex } from 'async-mutex';
24
- import { ModuleRegistry, AllCommunityModule, ClientSideRowModelModule, HighlightChangesModule, themeQuartz } from 'ag-grid-community';
25
- import { StatusBarModule, ClipboardModule, ExcelExportModule, ColumnMenuModule, ContextMenuModule, CellSelectionModule, RowSelectionModule } from 'ag-grid-enterprise';
26
- import * as i2$2 from '@angular/material/tooltip';
18
+ import * as i2$1 from '@angular/material/tooltip';
27
19
  import { MatTooltipModule } from '@angular/material/tooltip';
28
20
  import * as i2$3 from '@angular/material/menu';
29
21
  import { MatMenuModule } from '@angular/material/menu';
22
+ import { Buffer } from 'buffer';
23
+ import * as i3 from '@angular/material/divider';
24
+ import { MatDividerModule } from '@angular/material/divider';
25
+ import * as i1$2 from '@angular/material/snack-bar';
26
+ import { MatSnackBarModule } from '@angular/material/snack-bar';
27
+ import * as i1$1 from '@ngx-translate/core';
28
+ import { TranslateModule, TranslateService } from '@ngx-translate/core';
29
+ import { Mutex } from 'async-mutex';
30
30
  import * as XLSX from 'xlsx';
31
31
  import { I18nService } from '@nettyapps/ntyi18n';
32
- import * as i1$3 from '@angular/forms';
32
+ import * as i1$4 from '@angular/forms';
33
33
  import { FormBuilder, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
34
- import * as i3$2 from '@angular/material/input';
34
+ import * as i3$1 from '@angular/material/input';
35
35
  import { MatInputModule } from '@angular/material/input';
36
36
  import { MatFormFieldModule } from '@angular/material/form-field';
37
37
 
@@ -310,84 +310,157 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
310
310
  }]
311
311
  }] });
312
312
 
313
- class NettyHelper {
314
- /**
315
- * Returns null if fields are equal otherwise return second field
316
- * @param firstField
317
- * @param secondField
318
- * @returns
319
- */
320
- static difference(firstField, secondField) {
321
- if (firstField != secondField) {
322
- return secondField;
313
+ class ButtonRenderer {
314
+ params = null;
315
+ label = '';
316
+ type = '';
317
+ toggleValue = null;
318
+ editValid = false;
319
+ historyValid = false;
320
+ lineValid = false;
321
+ popupSelectValid = false;
322
+ popupEditValid = false;
323
+ toggleValid = false;
324
+ toggle_icon = '';
325
+ none = false;
326
+ addValid = false;
327
+ deleteValid = false;
328
+ agInit(params) {
329
+ this.params = params;
330
+ this.type = this.params.type || null;
331
+ this.label = this.params.label || null;
332
+ this.toggleValue = this.params.value || null;
333
+ switch (this.toggleValue) {
334
+ case true:
335
+ this.toggle_icon = 'select_check_box';
336
+ break;
337
+ case false:
338
+ this.toggle_icon = 'check_box_outline_blank';
339
+ break;
340
+ default:
341
+ this.toggle_icon = '';
342
+ break;
343
+ }
344
+ this.resetValids();
345
+ switch (this.type.toLowerCase().trim()) {
346
+ case 'edit':
347
+ this.editValid = true;
348
+ break;
349
+ case 'log':
350
+ this.historyValid = true;
351
+ break;
352
+ case 'line':
353
+ this.lineValid = true;
354
+ break;
355
+ case 'popupselect':
356
+ this.popupSelectValid = true;
357
+ break;
358
+ case 'toggle':
359
+ this.toggleValid = true;
360
+ break;
361
+ case 'none':
362
+ this.none = true;
363
+ break;
364
+ case 'add':
365
+ this.addValid = true;
366
+ break;
367
+ case 'delete':
368
+ this.deleteValid = true;
369
+ break;
370
+ default:
371
+ this.popupEditValid = true;
372
+ break;
323
373
  }
324
- return null;
325
374
  }
326
- /**
327
- * Returns null if fields are equal otherwise return second field
328
- * @param firstField
329
- * @param secondField
330
- * @param format
375
+ /** Refresh the display
376
+ *
377
+ * @param params
331
378
  * @returns
332
379
  */
333
- static dateDifference(firstField, secondField, format) {
334
- let culture = localStorage.getItem('languageApiCode') ?? 'tr-TR';
335
- let datePipe = new DatePipe(culture);
336
- if (datePipe.transform(firstField, format) !=
337
- datePipe.transform(secondField, format)) {
338
- return secondField;
380
+ refresh(params) {
381
+ return false;
382
+ }
383
+ resetValids() {
384
+ this.editValid = false;
385
+ this.historyValid = false;
386
+ this.lineValid = false;
387
+ this.popupSelectValid = false;
388
+ this.popupEditValid = false;
389
+ this.toggleValid = false;
390
+ }
391
+ onClick(event) {
392
+ if (this.params.onClick instanceof Function) {
393
+ // put anything into params u want pass into parents component
394
+ const params = {
395
+ event: event,
396
+ rowData: this.params.node.data,
397
+ type: this.type,
398
+ // ...something
399
+ };
400
+ this.params.onClick(params);
339
401
  }
340
- return null;
341
402
  }
403
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ButtonRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
404
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ButtonRenderer, isStandalone: true, selector: "ntybase-button-renderer", host: { attributes: { "ntybase-id": "ButtonRenderer" } }, ngImport: i0, template: "@if (editValid || popupEditValid) {\n<mat-icon\n class=\"cursor center edit\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"4000\"\n >edit</mat-icon\n>\n} @if (historyValid) {\n<mat-icon\n class=\"cursor center-log\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >log</mat-icon\n>\n} @if (historyValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >history</mat-icon\n>\n} @if (lineValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >menu_open</mat-icon\n>\n} @if (popupSelectValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >content_copy</mat-icon\n>\n} @if (toggleValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >{{toggleValue ? 'check_box' : 'check_box_outline_blank'}}</mat-icon\n>\n} @if (none) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n [matTooltipShowDelay]=\"3000\"\n >menu_open</mat-icon\n>\n} @if (addValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >playlist_add</mat-icon\n>\n} @if (deleteValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >delete_outline</mat-icon\n>\n}\n", styles: [".cursor{cursor:pointer}.center{display:flex;justify-content:center;align-items:center;width:100%}.center-log{display:flex;justify-content:center;align-items:center;margin-bottom:-12px}.edit{margin-top:8px}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatMenuModule }] });
342
405
  }
406
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ButtonRenderer, decorators: [{
407
+ type: Component,
408
+ args: [{ selector: 'ntybase-button-renderer', imports: [MatIconModule, MatTooltipModule, MatMenuModule], host: { 'ntybase-id': 'ButtonRenderer' }, template: "@if (editValid || popupEditValid) {\n<mat-icon\n class=\"cursor center edit\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"4000\"\n >edit</mat-icon\n>\n} @if (historyValid) {\n<mat-icon\n class=\"cursor center-log\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >log</mat-icon\n>\n} @if (historyValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >history</mat-icon\n>\n} @if (lineValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >menu_open</mat-icon\n>\n} @if (popupSelectValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >content_copy</mat-icon\n>\n} @if (toggleValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >{{toggleValue ? 'check_box' : 'check_box_outline_blank'}}</mat-icon\n>\n} @if (none) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n [matTooltipShowDelay]=\"3000\"\n >menu_open</mat-icon\n>\n} @if (addValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >playlist_add</mat-icon\n>\n} @if (deleteValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >delete_outline</mat-icon\n>\n}\n", styles: [".cursor{cursor:pointer}.center{display:flex;justify-content:center;align-items:center;width:100%}.center-log{display:flex;justify-content:center;align-items:center;margin-bottom:-12px}.edit{margin-top:8px}\n"] }]
409
+ }] });
343
410
 
344
- class CurrentUserPreference {
345
- coid = null;
346
- nettyUserPreferenceGUID = null;
347
- nettyUserGUID = null;
348
- nettyUserName = null;
349
- nettyUserFullName = null;
350
- nettyPreferenceType = null;
351
- nettyPreferenceData = null;
352
- init() {
353
- this.coid = null;
354
- this.nettyUserPreferenceGUID = null;
355
- this.nettyUserGUID = null;
356
- this.nettyUserName = '';
357
- this.nettyUserFullName = '';
358
- this.nettyPreferenceType = '';
359
- this.nettyPreferenceData = '';
411
+ class CheckboxRenderer {
412
+ params = null;
413
+ label = '';
414
+ type = '';
415
+ supportClick = false;
416
+ checked = null;
417
+ agInit(params) {
418
+ this.onProcess(params);
360
419
  }
361
- initParameter(parameters) {
362
- if (parameters == null || parameters == undefined) {
363
- this.init();
364
- return;
420
+ refresh(params) {
421
+ if (params != null) {
422
+ this.onProcess(params);
365
423
  }
366
- this.coid = parameters.coid;
367
- this.nettyUserPreferenceGUID = parameters.nettyUserPreferenceGUID;
368
- this.nettyUserGUID = parameters.nettyUserGUID;
369
- this.nettyUserName = parameters.nettyUserName;
370
- this.nettyUserFullName = parameters.nettyUserFullName;
371
- this.nettyPreferenceType = parameters.nettyPreferenceType;
372
- this.nettyPreferenceData = parameters.nettyPreferenceData;
424
+ return true;
373
425
  }
374
- compare(record) {
375
- let newRecord = new CurrentUserPreference();
376
- newRecord.init();
377
- newRecord.coid = record.coid;
378
- newRecord.nettyUserPreferenceGUID = record.nettyUserPreferenceGUID;
379
- newRecord.nettyUserGUID = NettyHelper.difference(this.nettyUserGUID, record.nettyUserGUID);
380
- newRecord.nettyPreferenceType = NettyHelper.difference(this.nettyPreferenceType, record.nettyPreferenceType);
381
- newRecord.nettyPreferenceData = NettyHelper.difference(this.nettyPreferenceData, record.nettyPreferenceData);
382
- return newRecord;
426
+ onProcess(params) {
427
+ this.params = params;
428
+ this.checked = this.params.value ?? false;
429
+ this.type = this.params.type || null;
430
+ this.label = this.params.label || null;
431
+ if (this.type != null) {
432
+ if (this.type.toLowerCase().trim() == 'click') {
433
+ this.supportClick = true;
434
+ }
435
+ }
436
+ }
437
+ onClick(event) {
438
+ this.checked = !this.checked;
439
+ if (this.params.onClick instanceof Function) {
440
+ // put anything into params u want pass into parents component
441
+ const params = {
442
+ event: event,
443
+ rowData: this.params.node.data,
444
+ type: this.type,
445
+ checked: this.checked,
446
+ // ...something
447
+ };
448
+ this.params.onClick(params);
449
+ }
383
450
  }
451
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CheckboxRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
452
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: CheckboxRenderer, isStandalone: true, selector: "ntybase-checkbox-renderer", host: { attributes: { "ntybase-id": "CheckboxRenderer" } }, ngImport: i0, template: "@if (supportClick) {\n<input\n id=\"checkbox\"\n type=\"checkbox\"\n [checked]=\"checked\"\n (click)=\"onClick($event)\"\n/>\n} @if (!supportClick) {\n<input id=\"checkbox\" type=\"checkbox\" [checked]=\"params.value\" disabled />\n}\n\n<label for=\"checkbox\">{{label}}</label>\n", styles: [""] });
384
453
  }
454
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CheckboxRenderer, decorators: [{
455
+ type: Component,
456
+ args: [{ selector: 'ntybase-checkbox-renderer', imports: [], host: { 'ntybase-id': 'CheckboxRenderer' }, template: "@if (supportClick) {\n<input\n id=\"checkbox\"\n type=\"checkbox\"\n [checked]=\"checked\"\n (click)=\"onClick($event)\"\n/>\n} @if (!supportClick) {\n<input id=\"checkbox\" type=\"checkbox\" [checked]=\"params.value\" disabled />\n}\n\n<label for=\"checkbox\">{{label}}</label>\n" }]
457
+ }] });
385
458
 
386
459
  class ConfirmDialog {
387
460
  dialogRef = inject((MatDialogRef));
388
461
  data = inject(MAT_DIALOG_DATA);
389
462
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ConfirmDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
390
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: ConfirmDialog, isStandalone: true, selector: "ntybase-confirm-dialog", ngImport: i0, template: "<div class=\"dialog-container\">\n <h2 mat-dialog-title class=\"dialog-title\">\n <mat-icon color=\"warn\" class=\"warning-icon\">warning</mat-icon>\n <span>{{data.title}}</span>\n </h2>\n\n <mat-divider class=\"divider\"></mat-divider>\n\n <mat-dialog-content class=\"dialog-content\">\n <p class=\"message\">{{data.message}}</p>\n </mat-dialog-content>\n\n <mat-dialog-actions align=\"end\" class=\"dialog-actions\">\n <button mat-stroked-button [mat-dialog-close]=\"false\" class=\"btn-cancel\">\n {{'@btnCancel' | translate}}\n </button>\n <button\n mat-flat-button\n color=\"warn\"\n [mat-dialog-close]=\"true\"\n class=\"btn-ok\"\n >\n {{'@btnOK' | translate}}\n </button>\n </mat-dialog-actions>\n</div>\n", styles: [".dialog-container{display:flex;flex-direction:column;min-width:400px;max-width:90vw;padding:24px;border-radius:12px!important}.dialog-title{display:flex;align-items:center;margin:0 0 12px;padding:0;color:var(--mat-sys-primary)}.dialog-title span{margin-left:8px}.warning-icon{color:var(--mat-sys-primary);transform:scale(1.2)}.divider{margin:8px 0 16px;border-top-color:var(--mat-sys-primary)}.dialog-content{padding:8px 0 24px;margin:0;color:var(--mat-sys-primary);line-height:1.6}.dialog-content .message{margin:0;white-space:pre-wrap}.dialog-actions{padding:16px 0 0;margin:0;gap:8px}.btn-ok{padding:8px 16px;border-radius:6px;font-weight:500;background-color:var(--mat-sys-primary);color:var(--mat-sys-primary-container)}.btn-cancel{padding:8px 16px;border-radius:6px;color:var(--mat-sys-secondary-container);background-color:var(--mat-sys-secondary)}\n"], dependencies: [{ kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i3.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }] });
463
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: ConfirmDialog, isStandalone: true, selector: "ntybase-confirm-dialog", ngImport: i0, template: "<div class=\"dialog-container\">\n <h2 mat-dialog-title class=\"dialog-title\">\n <mat-icon color=\"warn\" class=\"warning-icon\">warning</mat-icon>\n <span>{{data.title}}</span>\n </h2>\n\n <mat-divider class=\"divider\"></mat-divider>\n\n <mat-dialog-content class=\"dialog-content\">\n <p class=\"message\">{{data.message}}</p>\n </mat-dialog-content>\n\n <mat-dialog-actions align=\"end\" class=\"dialog-actions\">\n <button mat-stroked-button [mat-dialog-close]=\"false\" class=\"btn-cancel\">\n {{'@btnCancel' | translate}}\n </button>\n <button\n mat-flat-button\n color=\"warn\"\n [mat-dialog-close]=\"true\"\n class=\"btn-ok\"\n >\n {{'@btnOK' | translate}}\n </button>\n </mat-dialog-actions>\n</div>\n", styles: [".dialog-container{display:flex;flex-direction:column;min-width:400px;max-width:90vw;padding:24px;border-radius:12px!important}.dialog-title{display:flex;align-items:center;margin:0 0 12px;padding:0;color:var(--mat-sys-primary)}.dialog-title span{margin-left:8px}.warning-icon{color:var(--mat-sys-primary);transform:scale(1.2)}.divider{margin:8px 0 16px;border-top-color:var(--mat-sys-primary)}.dialog-content{padding:8px 0 24px;margin:0;color:var(--mat-sys-primary);line-height:1.6}.dialog-content .message{margin:0;white-space:pre-wrap}.dialog-actions{padding:16px 0 0;margin:0;gap:8px}.btn-ok{padding:8px 16px;border-radius:6px;font-weight:500;background-color:var(--mat-sys-primary);color:var(--mat-sys-primary-container)}.btn-cancel{padding:8px 16px;border-radius:6px;color:var(--mat-sys-secondary-container);background-color:var(--mat-sys-secondary)}\n"], dependencies: [{ kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i3.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
391
464
  }
392
465
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ConfirmDialog, decorators: [{
393
466
  type: Component,
@@ -404,7 +477,7 @@ class ErrorAlert {
404
477
  dialogRef = inject((MatDialogRef));
405
478
  data = inject(MAT_DIALOG_DATA);
406
479
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ErrorAlert, deps: [], target: i0.ɵɵFactoryTarget.Component });
407
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: ErrorAlert, isStandalone: true, selector: "ntybase-error-alert", ngImport: i0, template: "<div class=\"error-dialog-container\">\n <div class=\"header\">\n <mat-icon color=\"error\">error_outline</mat-icon>\n <h2 class=\"error-title\">{{ data.title }}</h2>\n </div>\n\n <div class=\"error-content\">\n <p>{{ data.message }}</p>\n </div>\n\n <mat-dialog-actions class=\"dialog-actions\">\n <button mat-flat-button [mat-dialog-close]=\"true\" class=\"btn-ok\">\n {{'@btnOK' | translate}}\n </button>\n </mat-dialog-actions>\n</div>\n", styles: [".error-dialog-container{padding:40px 32px;text-align:center;min-width:380px;max-width:450px;background:var(--mat-sys-primary);border-radius:20px;box-shadow:0 15px 35px #00000012}.error-dialog-container .header{display:flex;flex-direction:column;align-items:center;gap:12px}.error-dialog-container .header mat-icon{font-size:52px;width:52px;height:52px;color:var(--mat-sys-inverse-primary);margin-bottom:8px}.error-dialog-container .header .error-title{margin:0;font-size:1.4rem;font-weight:700;color:var(--mat-sys-surface);letter-spacing:-.02em}.error-dialog-container .error-content{margin:24px 0 32px;font-size:1rem;line-height:1.6;color:var(--mat-sys-surface)}.error-dialog-container .dialog-actions{display:flex;justify-content:center;padding:0;margin:0}.error-dialog-container .btn-ok{min-width:120px;padding:12px 24px;font-weight:600;font-size:1rem;border-radius:10px;background:var(--mat-sys-inverse-primary);color:var(--mat-sys-primary);border:none;cursor:pointer;transition:all .2s ease}.error-dialog-container .btn-ok:hover{background:var(--mat-sys-inverse-primary);opacity:.9;box-shadow:0 5px 15px #0000001a}\n"], dependencies: [{ kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }] });
480
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: ErrorAlert, isStandalone: true, selector: "ntybase-error-alert", ngImport: i0, template: "<div class=\"error-dialog-container\">\n <div class=\"header\">\n <mat-icon color=\"error\">error_outline</mat-icon>\n <h2 class=\"error-title\">{{ data.title }}</h2>\n </div>\n\n <div class=\"error-content\">\n <p>{{ data.message }}</p>\n </div>\n\n <mat-dialog-actions class=\"dialog-actions\">\n <button mat-flat-button [mat-dialog-close]=\"true\" class=\"btn-ok\">\n {{'@btnOK' | translate}}\n </button>\n </mat-dialog-actions>\n</div>\n", styles: [".error-dialog-container{padding:40px 32px;text-align:center;min-width:380px;max-width:450px;background:var(--mat-sys-primary);border-radius:20px;box-shadow:0 15px 35px #00000012}.error-dialog-container .header{display:flex;flex-direction:column;align-items:center;gap:12px}.error-dialog-container .header mat-icon{font-size:52px;width:52px;height:52px;color:var(--mat-sys-inverse-primary);margin-bottom:8px}.error-dialog-container .header .error-title{margin:0;font-size:1.4rem;font-weight:700;color:var(--mat-sys-surface);letter-spacing:-.02em}.error-dialog-container .error-content{margin:24px 0 32px;font-size:1rem;line-height:1.6;color:var(--mat-sys-surface)}.error-dialog-container .dialog-actions{display:flex;justify-content:center;padding:0;margin:0}.error-dialog-container .btn-ok{min-width:120px;padding:12px 24px;font-weight:600;font-size:1rem;border-radius:10px;background:var(--mat-sys-inverse-primary);color:var(--mat-sys-primary);border:none;cursor:pointer;transition:all .2s ease}.error-dialog-container .btn-ok:hover{background:var(--mat-sys-inverse-primary);opacity:.9;box-shadow:0 5px 15px #0000001a}\n"], dependencies: [{ kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
408
481
  }
409
482
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ErrorAlert, decorators: [{
410
483
  type: Component,
@@ -484,7 +557,7 @@ class AlertService {
484
557
  });
485
558
  });
486
559
  }
487
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AlertService, deps: [{ token: i1$1.MatSnackBar }, { token: i1.MatDialog }, { token: i3$1.TranslateService }], target: i0.ɵɵFactoryTarget.Injectable });
560
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AlertService, deps: [{ token: i1$2.MatSnackBar }, { token: i1.MatDialog }, { token: i1$1.TranslateService }], target: i0.ɵɵFactoryTarget.Injectable });
488
561
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AlertService, providedIn: 'root' });
489
562
  }
490
563
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AlertService, decorators: [{
@@ -492,53 +565,249 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
492
565
  args: [{
493
566
  providedIn: 'root',
494
567
  }]
495
- }], ctorParameters: () => [{ type: i1$1.MatSnackBar }, { type: i1.MatDialog }, { type: i3$1.TranslateService }] });
568
+ }], ctorParameters: () => [{ type: i1$2.MatSnackBar }, { type: i1.MatDialog }, { type: i1$1.TranslateService }] });
496
569
 
497
- class CommonService {
498
- // Services
499
- router = inject(Router);
500
- location = inject(Location);
501
- datePipe = inject(DatePipe);
502
- decimalPipe = inject(DecimalPipe);
570
+ class NettyAppsBase {
571
+ // ---------------------------------
572
+ // --- SERVICES ---
573
+ // ---------------------------------
503
574
  alertService = inject(AlertService);
504
- translate = inject(TranslateService);
505
- dialog = inject(MatDialog);
506
- // Right sidenav
507
- rightSidenavOpen = signal(false, ...(ngDevMode ? [{ debugName: "rightSidenavOpen" }] : []));
508
- toggleRightSidenav(open) {
509
- this.rightSidenavOpen.set(open);
510
- }
575
+ translateService = inject(TranslateService);
576
+ // ---------------------------------
577
+ // --- DOWNLOAD METHODS ---
578
+ // ---------------------------------
511
579
  /**
512
- * Normalizes Turkish text for search and comparison operations by converting
513
- * Turkish special characters to their English equivalents and lowercasing.
580
+ * Download the given base64Encoded data as file
514
581
  *
582
+ * @param base64Data: base64 encoded data
583
+ * @param fileName: filename to download
515
584
  */
516
- normalizeTurkish(text) {
517
- return text
518
- .toLocaleLowerCase('tr-TR')
519
- .replace(/[ıİ]/g, 'i')
520
- .replace(/[ğĞ]/g, 'g')
521
- .replace(/[üÜ]/g, 'u')
522
- .replace(/[şŞ]/g, 's')
523
- .replace(/[öÖ]/g, 'o')
524
- .replace(/[çÇ]/g, 'c');
525
- }
526
- /**
527
- * Gets the clean URL path without fragments or query params
528
- */
529
- getCleanUrlPath() {
530
- const tree = this.router.parseUrl(this.router.url);
531
- const segments = tree.root.children['primary']?.segments || [];
532
- if (segments.length >= 2) {
533
- return segments
534
- .slice(0, 2)
535
- .map((s) => s.path)
536
- .join('/');
585
+ downloadFile(base64Data, fileName) {
586
+ if (base64Data == null) {
587
+ return;
537
588
  }
538
- return '/';
539
- }
540
- /**
541
- * Clears the right sidenav outlet and resets the UI state.
589
+ if (fileName == null) {
590
+ return;
591
+ }
592
+ // Check if header is present
593
+ if (!base64Data.startsWith('data:')) {
594
+ console.error('Provided data is not in base64 format (missing header)');
595
+ return;
596
+ }
597
+ const contentType = base64Data.split(';')[0].split(':')[1];
598
+ const byteCharacters = atob(base64Data.split(',')[1]);
599
+ const byteArrays = [];
600
+ for (let i = 0; i < byteCharacters.length; i++) {
601
+ const byteArray = byteCharacters.charCodeAt(i);
602
+ byteArrays.push(byteArray);
603
+ }
604
+ const byteArray = new Uint8Array(byteArrays);
605
+ const blob = new Blob([byteArray], { type: contentType });
606
+ const link = document.createElement('a');
607
+ link.href = URL.createObjectURL(blob);
608
+ link.download = fileName;
609
+ link.click();
610
+ }
611
+ /** Download the given base64Endoced data as text file
612
+ *
613
+ * @param base64EncodedFileData
614
+ * @param fileName
615
+ */
616
+ downloadTextFile(base64EncodedFileData, fileName) {
617
+ // Check if the data has a prefix like "data:application/pdf;base64,"
618
+ if (base64EncodedFileData == null) {
619
+ return;
620
+ }
621
+ if (fileName == null) {
622
+ return;
623
+ }
624
+ let _data = base64EncodedFileData;
625
+ const prefix = 'data:';
626
+ if (_data.startsWith(prefix)) {
627
+ // Remove the prefix
628
+ _data = _data.slice(_data.indexOf(',') + 1);
629
+ }
630
+ // Convert the base64 data to a Uint8Array
631
+ const textData = Buffer.from(_data ?? '', 'base64').toString();
632
+ this.downloadTextFileNotEncoded(textData, fileName);
633
+ }
634
+ /** Save the given text as a text file
635
+ *
636
+ * @param fileData
637
+ * @param fileName
638
+ */
639
+ downloadTextFileNotEncoded(fileData, fileName) {
640
+ if (fileData == null) {
641
+ return;
642
+ }
643
+ if (fileName == null) {
644
+ return;
645
+ }
646
+ // Create a Blob from the Text
647
+ const blob = new Blob([fileData], { type: 'text/plain' });
648
+ // Create a download link
649
+ const url = window.URL.createObjectURL(blob);
650
+ const a = document.createElement('a');
651
+ document.body.appendChild(a);
652
+ a.style.display = 'none';
653
+ a.href = url;
654
+ a.download = fileName ?? 'filename';
655
+ // Trigger the download
656
+ a.click();
657
+ // Clean up
658
+ window.URL.revokeObjectURL(url);
659
+ document.body.removeChild(a);
660
+ }
661
+ /**
662
+ * Download file where the data is provided as blob
663
+ * @param data - Array Buffer data
664
+ * @param type - type of the document.
665
+ */
666
+ downloadBlobFile(data, type, fileName) {
667
+ let blob = new Blob([data], { type: type });
668
+ let downloadLink = document.createElement('a');
669
+ downloadLink.href = window.URL.createObjectURL(blob);
670
+ downloadLink.setAttribute('download', fileName);
671
+ document.body.appendChild(downloadLink);
672
+ downloadLink.click();
673
+ downloadLink.parentNode?.removeChild(downloadLink);
674
+ }
675
+ // ---------------------------------
676
+ // --- INTERFACE IMPLEMENTATIONS ---
677
+ // ---------------------------------
678
+ onDestroy$ = new Subject();
679
+ ngOnDestroy() {
680
+ //Called once, before the instance is destroyed.
681
+ //Add 'implements OnDestroy' to the class.
682
+ this.onDestroy$.next();
683
+ this.onDestroy$.complete();
684
+ }
685
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAppsBase, deps: [], target: i0.ɵɵFactoryTarget.Component });
686
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: NettyAppsBase, isStandalone: true, selector: "ntybase-netty-apps-base", ngImport: i0, template: ``, isInline: true });
687
+ }
688
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAppsBase, decorators: [{
689
+ type: Component,
690
+ args: [{ selector: 'ntybase-netty-apps-base', imports: [], template: `` }]
691
+ }] });
692
+
693
+ class NettyHelper {
694
+ /**
695
+ * Returns null if fields are equal otherwise return second field
696
+ * @param firstField
697
+ * @param secondField
698
+ * @returns
699
+ */
700
+ static difference(firstField, secondField) {
701
+ if (firstField != secondField) {
702
+ return secondField;
703
+ }
704
+ return null;
705
+ }
706
+ /**
707
+ * Returns null if fields are equal otherwise return second field
708
+ * @param firstField
709
+ * @param secondField
710
+ * @param format
711
+ * @returns
712
+ */
713
+ static dateDifference(firstField, secondField, format) {
714
+ let culture = localStorage.getItem('languageApiCode') ?? 'tr-TR';
715
+ let datePipe = new DatePipe(culture);
716
+ if (datePipe.transform(firstField, format) !=
717
+ datePipe.transform(secondField, format)) {
718
+ return secondField;
719
+ }
720
+ return null;
721
+ }
722
+ }
723
+
724
+ class CurrentUserPreference {
725
+ coid = null;
726
+ nettyUserPreferenceGUID = null;
727
+ nettyUserGUID = null;
728
+ nettyUserName = null;
729
+ nettyUserFullName = null;
730
+ nettyPreferenceType = null;
731
+ nettyPreferenceData = null;
732
+ init() {
733
+ this.coid = null;
734
+ this.nettyUserPreferenceGUID = null;
735
+ this.nettyUserGUID = null;
736
+ this.nettyUserName = '';
737
+ this.nettyUserFullName = '';
738
+ this.nettyPreferenceType = '';
739
+ this.nettyPreferenceData = '';
740
+ }
741
+ initParameter(parameters) {
742
+ if (parameters == null || parameters == undefined) {
743
+ this.init();
744
+ return;
745
+ }
746
+ this.coid = parameters.coid;
747
+ this.nettyUserPreferenceGUID = parameters.nettyUserPreferenceGUID;
748
+ this.nettyUserGUID = parameters.nettyUserGUID;
749
+ this.nettyUserName = parameters.nettyUserName;
750
+ this.nettyUserFullName = parameters.nettyUserFullName;
751
+ this.nettyPreferenceType = parameters.nettyPreferenceType;
752
+ this.nettyPreferenceData = parameters.nettyPreferenceData;
753
+ }
754
+ compare(record) {
755
+ let newRecord = new CurrentUserPreference();
756
+ newRecord.init();
757
+ newRecord.coid = record.coid;
758
+ newRecord.nettyUserPreferenceGUID = record.nettyUserPreferenceGUID;
759
+ newRecord.nettyUserGUID = NettyHelper.difference(this.nettyUserGUID, record.nettyUserGUID);
760
+ newRecord.nettyPreferenceType = NettyHelper.difference(this.nettyPreferenceType, record.nettyPreferenceType);
761
+ newRecord.nettyPreferenceData = NettyHelper.difference(this.nettyPreferenceData, record.nettyPreferenceData);
762
+ return newRecord;
763
+ }
764
+ }
765
+
766
+ class CommonService {
767
+ // Services
768
+ router = inject(Router);
769
+ location = inject(Location);
770
+ datePipe = inject(DatePipe);
771
+ decimalPipe = inject(DecimalPipe);
772
+ alertService = inject(AlertService);
773
+ translate = inject(TranslateService);
774
+ dialog = inject(MatDialog);
775
+ // Right sidenav
776
+ rightSidenavOpen = signal(false, ...(ngDevMode ? [{ debugName: "rightSidenavOpen" }] : []));
777
+ toggleRightSidenav(open) {
778
+ this.rightSidenavOpen.set(open);
779
+ }
780
+ /**
781
+ * Normalizes Turkish text for search and comparison operations by converting
782
+ * Turkish special characters to their English equivalents and lowercasing.
783
+ *
784
+ */
785
+ normalizeTurkish(text) {
786
+ return text
787
+ .toLocaleLowerCase('tr-TR')
788
+ .replace(/[ıİ]/g, 'i')
789
+ .replace(/[ğĞ]/g, 'g')
790
+ .replace(/[üÜ]/g, 'u')
791
+ .replace(/[şŞ]/g, 's')
792
+ .replace(/[öÖ]/g, 'o')
793
+ .replace(/[çÇ]/g, 'c');
794
+ }
795
+ /**
796
+ * Gets the clean URL path without fragments or query params
797
+ */
798
+ getCleanUrlPath() {
799
+ const tree = this.router.parseUrl(this.router.url);
800
+ const segments = tree.root.children['primary']?.segments || [];
801
+ if (segments.length >= 2) {
802
+ return segments
803
+ .slice(0, 2)
804
+ .map((s) => s.path)
805
+ .join('/');
806
+ }
807
+ return '/';
808
+ }
809
+ /**
810
+ * Clears the right sidenav outlet and resets the UI state.
542
811
  * Removes the right sidenav route while keeping the main content and query parameters.
543
812
  * Also collapses the sidenav and closes any open dialogs.
544
813
  */
@@ -751,6 +1020,7 @@ class NettyAgGridService {
751
1020
  nettyAlertService = inject(AlertService);
752
1021
  environmentProxy = inject(EnvironmentProxy);
753
1022
  commonService = inject(CommonService);
1023
+ translateService = inject(TranslateService);
754
1024
  constructor() {
755
1025
  this.userPreferenceLock = new Mutex();
756
1026
  }
@@ -976,363 +1246,176 @@ class NettyAgGridService {
976
1246
  },
977
1247
  ];
978
1248
  }
979
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAgGridService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
980
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAgGridService, providedIn: 'root' });
981
- }
982
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAgGridService, decorators: [{
983
- type: Injectable,
984
- args: [{
985
- providedIn: 'root',
986
- }]
987
- }], ctorParameters: () => [] });
988
-
989
- class SecurityDto {
990
- coid = null;
991
- userGUID = null;
992
- application = '';
993
- formCode = '';
994
- }
995
-
996
- class SysfunctionProxy {
997
- http;
998
- environmentProxy;
999
- constructor(http, environmentProxy) {
1000
- this.http = http;
1001
- this.environmentProxy = environmentProxy;
1002
- }
1003
- /** Get the authentication list for the given form
1004
- *
1005
- * @param formCode
1006
- * @returns
1007
- */
1008
- getAuthentication(formCode) {
1009
- let sysFunctionsURL = this.environmentProxy.getAdminLink('getAuthentication');
1010
- let securityDto = new SecurityDto();
1011
- securityDto.formCode = formCode;
1012
- securityDto.application = this.environmentProxy.getApplicationName();
1013
- let call$ = this.http.post(sysFunctionsURL, securityDto);
1014
- return call$.pipe(map((result) => result), catchError$1((error) => {
1015
- let errorMessage = error.message; //.error.title;
1016
- return throwError(() => new Error(errorMessage ?? ''));
1017
- }));
1018
- }
1019
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SysfunctionProxy, deps: [{ token: i1$2.HttpClient }, { token: i2$1.EnvironmentProxy }], target: i0.ɵɵFactoryTarget.Injectable });
1020
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SysfunctionProxy, providedIn: 'root' });
1021
- }
1022
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SysfunctionProxy, decorators: [{
1023
- type: Injectable,
1024
- args: [{
1025
- providedIn: 'root',
1026
- }]
1027
- }], ctorParameters: () => [{ type: i1$2.HttpClient }, { type: i2$1.EnvironmentProxy }] });
1028
-
1029
- class ButtonRenderer {
1030
- params = null;
1031
- label = '';
1032
- type = '';
1033
- toggleValue = null;
1034
- editValid = false;
1035
- historyValid = false;
1036
- lineValid = false;
1037
- popupSelectValid = false;
1038
- popupEditValid = false;
1039
- toggleValid = false;
1040
- toggle_icon = '';
1041
- none = false;
1042
- addValid = false;
1043
- deleteValid = false;
1044
- agInit(params) {
1045
- this.params = params;
1046
- this.type = this.params.type || null;
1047
- this.label = this.params.label || null;
1048
- this.toggleValue = this.params.value || null;
1049
- switch (this.toggleValue) {
1050
- case true:
1051
- this.toggle_icon = 'select_check_box';
1052
- break;
1053
- case false:
1054
- this.toggle_icon = 'check_box_outline_blank';
1055
- break;
1056
- default:
1057
- this.toggle_icon = '';
1058
- break;
1059
- }
1060
- this.resetValids();
1061
- switch (this.type.toLowerCase().trim()) {
1062
- case 'edit':
1063
- this.editValid = true;
1064
- break;
1065
- case 'log':
1066
- this.historyValid = true;
1067
- break;
1068
- case 'line':
1069
- this.lineValid = true;
1070
- break;
1071
- case 'popupselect':
1072
- this.popupSelectValid = true;
1073
- break;
1074
- case 'toggle':
1075
- this.toggleValid = true;
1076
- break;
1077
- case 'none':
1078
- this.none = true;
1079
- break;
1080
- case 'add':
1081
- this.addValid = true;
1082
- break;
1083
- case 'delete':
1084
- this.deleteValid = true;
1085
- break;
1086
- default:
1087
- this.popupEditValid = true;
1088
- break;
1089
- }
1090
- }
1091
- /** Refresh the display
1092
- *
1093
- * @param params
1094
- * @returns
1095
- */
1096
- refresh(params) {
1097
- return false;
1098
- }
1099
- resetValids() {
1100
- this.editValid = false;
1101
- this.historyValid = false;
1102
- this.lineValid = false;
1103
- this.popupSelectValid = false;
1104
- this.popupEditValid = false;
1105
- this.toggleValid = false;
1106
- }
1107
- onClick(event) {
1108
- if (this.params.onClick instanceof Function) {
1109
- // put anything into params u want pass into parents component
1110
- const params = {
1111
- event: event,
1112
- rowData: this.params.node.data,
1113
- type: this.type,
1114
- // ...something
1115
- };
1116
- this.params.onClick(params);
1117
- }
1118
- }
1119
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ButtonRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
1120
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ButtonRenderer, isStandalone: true, selector: "ntybase-button-renderer", host: { attributes: { "ntybase-id": "ButtonRenderer" } }, ngImport: i0, template: "@if (editValid || popupEditValid) {\n<mat-icon\n class=\"cursor center edit\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"4000\"\n >edit</mat-icon\n>\n} @if (historyValid) {\n<mat-icon\n class=\"cursor center-log\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >log</mat-icon\n>\n} @if (historyValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >history</mat-icon\n>\n} @if (lineValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >menu_open</mat-icon\n>\n} @if (popupSelectValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >content_copy</mat-icon\n>\n} @if (toggleValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >{{toggleValue ? 'check_box' : 'check_box_outline_blank'}}</mat-icon\n>\n} @if (none) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n [matTooltipShowDelay]=\"3000\"\n >menu_open</mat-icon\n>\n} @if (addValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >playlist_add</mat-icon\n>\n} @if (deleteValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >delete_outline</mat-icon\n>\n}\n", styles: [".cursor{cursor:pointer}.center{display:flex;justify-content:center;align-items:center;width:100%}.center-log{display:flex;justify-content:center;align-items:center;margin-bottom:-12px}.edit{margin-top:8px}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2$2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatMenuModule }] });
1121
- }
1122
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ButtonRenderer, decorators: [{
1123
- type: Component,
1124
- args: [{ selector: 'ntybase-button-renderer', imports: [MatIconModule, MatTooltipModule, MatMenuModule], host: { 'ntybase-id': 'ButtonRenderer' }, template: "@if (editValid || popupEditValid) {\n<mat-icon\n class=\"cursor center edit\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"4000\"\n >edit</mat-icon\n>\n} @if (historyValid) {\n<mat-icon\n class=\"cursor center-log\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >log</mat-icon\n>\n} @if (historyValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >history</mat-icon\n>\n} @if (lineValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >menu_open</mat-icon\n>\n} @if (popupSelectValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >content_copy</mat-icon\n>\n} @if (toggleValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >{{toggleValue ? 'check_box' : 'check_box_outline_blank'}}</mat-icon\n>\n} @if (none) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n [matTooltipShowDelay]=\"3000\"\n >menu_open</mat-icon\n>\n} @if (addValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >playlist_add</mat-icon\n>\n} @if (deleteValid) {\n<mat-icon\n class=\"cursor center\"\n matTooltip=\"{{label}}\"\n (click)=\"onClick($event)\"\n [matTooltipShowDelay]=\"3000\"\n >delete_outline</mat-icon\n>\n}\n", styles: [".cursor{cursor:pointer}.center{display:flex;justify-content:center;align-items:center;width:100%}.center-log{display:flex;justify-content:center;align-items:center;margin-bottom:-12px}.edit{margin-top:8px}\n"] }]
1125
- }] });
1126
-
1127
- class CheckboxRenderer {
1128
- params = null;
1129
- label = '';
1130
- type = '';
1131
- supportClick = false;
1132
- checked = null;
1133
- agInit(params) {
1134
- this.onProcess(params);
1135
- }
1136
- refresh(params) {
1137
- if (params != null) {
1138
- this.onProcess(params);
1139
- }
1140
- return true;
1141
- }
1142
- onProcess(params) {
1143
- this.params = params;
1144
- this.checked = this.params.value ?? false;
1145
- this.type = this.params.type || null;
1146
- this.label = this.params.label || null;
1147
- if (this.type != null) {
1148
- if (this.type.toLowerCase().trim() == 'click') {
1149
- this.supportClick = true;
1150
- }
1151
- }
1152
- }
1153
- onClick(event) {
1154
- this.checked = !this.checked;
1155
- if (this.params.onClick instanceof Function) {
1156
- // put anything into params u want pass into parents component
1157
- const params = {
1158
- event: event,
1159
- rowData: this.params.node.data,
1160
- type: this.type,
1161
- checked: this.checked,
1162
- // ...something
1163
- };
1164
- this.params.onClick(params);
1249
+ setAgGridTranslations(gridApi) {
1250
+ if (gridApi) {
1251
+ gridApi.setGridOption('localeText', {
1252
+ // Status panel translate
1253
+ totalRows: this.translateService.instant('AG_GRID.TOTAL_ROWS'),
1254
+ filteredRows: this.translateService.instant('AG_GRID.FILTERED_ROWS'),
1255
+ selectedRows: this.translateService.instant('AG_GRID.SELECTED_ROWS'),
1256
+ noRowsToShow: this.translateService.instant('AG_GRID.NO_ROWS_TO_SHOW'),
1257
+ loadingOoo: this.translateService.instant('AG_GRID.LOADING'),
1258
+ // Context menu translations
1259
+ copy: this.translateService.instant('AG_GRID.COPY'),
1260
+ copyWithHeaders: this.translateService.instant('AG_GRID.COPY_WITH_HEADERS'),
1261
+ copyWithGroupHeaders: this.translateService.instant('AG_GRID.COPY_WITH_GROUP_HEADERS'),
1262
+ paste: this.translateService.instant('AG_GRID.PASTE'),
1263
+ export: this.translateService.instant('AG_GRID.EXPORT'),
1264
+ csvExport: this.translateService.instant('AG_GRID.CSV_EXPORT'),
1265
+ excelExport: this.translateService.instant('AG_GRID.EXCEL_EXPORT'),
1266
+ pinColumn: this.translateService.instant('AG_GRID.PIN_COLUMN'),
1267
+ pinLeft: this.translateService.instant('AG_GRID.PIN_LEFT'),
1268
+ pinRight: this.translateService.instant('AG_GRID.PIN_RIGHT'),
1269
+ noPin: this.translateService.instant('AG_GRID.NO_PIN'),
1270
+ sortAscending: this.translateService.instant('AG_GRID.SORT_ASCENDING'),
1271
+ sortDescending: this.translateService.instant('AG_GRID.SORT_DESCENDING'),
1272
+ autosizeThisColumn: this.translateService.instant('AG_GRID.AUTOSIZE_THIS_COLUMN'),
1273
+ autosizeAllColumns: this.translateService.instant('AG_GRID.AUTOSIZE_ALL_COLUMNS'),
1274
+ resetColumns: this.translateService.instant('AG_GRID.RESET_COLUMNS'),
1275
+ expandAll: this.translateService.instant('AG_GRID.EXPAND_ALL'),
1276
+ collapseAll: this.translateService.instant('AG_GRID.COLLAPSE_ALL'),
1277
+ exportToExcel: this.translateService.instant('AG_GRID.EXPORT_TO_EXCEL'),
1278
+ sheetName: this.translateService.instant('AG_GRID.SHEET_NAME'),
1279
+ exportAsExcelTable: this.translateService.instant('AG_GRID.EXPORT_AS_EXCEL_TABLE'),
1280
+ rangeSelectTo: this.translateService.instant('AG_GRID.RANGE_SELECT_TO'),
1281
+ rangeSelectFrom: this.translateService.instant('AG_GRID.RANGE_SELECT_FROM'),
1282
+ rangeSelectCopy: this.translateService.instant('AG_GRID.RANGE_SELECT_COPY'),
1283
+ rangeSelectChart: this.translateService.instant('AG_GRID.RANGE_SELECT_CHART'),
1284
+ pasteAll: this.translateService.instant('AG_GRID.CLIPBOARD_PASTE'),
1285
+ pasteWithoutHeader: this.translateService.instant('AG_GRID.CLIPBOARD_PASTE_WITHOUT_HEADER'),
1286
+ copyAll: this.translateService.instant('AG_GRID.CLIPBOARD_COPY'),
1287
+ cut: this.translateService.instant('AG_GRID.CLIPBOARD_CUT'),
1288
+ // Pagination translations
1289
+ page: this.translateService.instant('AG_GRID.PAGE'),
1290
+ more: this.translateService.instant('AG_GRID.MORE'),
1291
+ to: this.translateService.instant('AG_GRID.TO'),
1292
+ of: this.translateService.instant('AG_GRID.OF'),
1293
+ next: this.translateService.instant('AG_GRID.NEXT'),
1294
+ last: this.translateService.instant('AG_GRID.LAST'),
1295
+ first: this.translateService.instant('AG_GRID.FIRST'),
1296
+ previous: this.translateService.instant('AG_GRID.PREVIOUS'),
1297
+ pageSizeSelectorLabel: this.translateService.instant('AG_GRID.PAGE_SIZE_SELECTOR_LABEL'),
1298
+ // Set Filter
1299
+ selectAll: this.translateService.instant('AG_GRID.SELECT_ALL'),
1300
+ selectAllSearchResults: this.translateService.instant('AG_GRID.SELECT_ALL_SEARCH_RESULTS'),
1301
+ searchOoo: this.translateService.instant('AG_GRID.SEARCH_OOO'),
1302
+ blanks: this.translateService.instant('AG_GRID.BLANKS'),
1303
+ noMatches: this.translateService.instant('AG_GRID.NO_MATCHES'),
1304
+ // Number Filter & Text Filter
1305
+ filterOoo: this.translateService.instant('AG_GRID.FILTER_OOO'),
1306
+ equals: this.translateService.instant('AG_GRID.EQUALS'),
1307
+ notEqual: this.translateService.instant('AG_GRID.NOT_EQUAL'),
1308
+ blank: this.translateService.instant('AG_GRID.BLANK'),
1309
+ notBlank: this.translateService.instant('AG_GRID.NOT_BLANK'),
1310
+ empty: this.translateService.instant('AG_GRID.EMPTY'),
1311
+ // Number Filter
1312
+ lessThan: this.translateService.instant('AG_GRID.LESS_THAN'),
1313
+ greaterThan: this.translateService.instant('AG_GRID.GREATER_THAN'),
1314
+ lessThanOrEqual: this.translateService.instant('AG_GRID.LESS_THAN_OR_EQUAL'),
1315
+ greaterThanOrEqual: this.translateService.instant('AG_GRID.GREATER_THAN_OR_EQUAL'),
1316
+ inRange: this.translateService.instant('AG_GRID.IN_RANGE'),
1317
+ inRangeStart: this.translateService.instant('AG_GRID.IN_RANGE_START'),
1318
+ inRangeEnd: this.translateService.instant('AG_GRID.IN_RANGE_END'),
1319
+ // Text Filter
1320
+ contains: this.translateService.instant('AG_GRID.CONTAINS'),
1321
+ notContains: this.translateService.instant('AG_GRID.NOT_CONTAINS'),
1322
+ startsWith: this.translateService.instant('AG_GRID.STARTS_WITH'),
1323
+ endsWith: this.translateService.instant('AG_GRID.ENDS_WITH'),
1324
+ // Date Filter
1325
+ dateFormatOoo: this.translateService.instant('AG_GRID.DATE_FORMAT_OOO'),
1326
+ // Filter Conditions
1327
+ andCondition: this.translateService.instant('AG_GRID.AND_CONDITION'),
1328
+ orCondition: this.translateService.instant('AG_GRID.OR_CONDITION'),
1329
+ // Filter Buttons
1330
+ applyFilter: this.translateService.instant('AG_GRID.APPLY_FILTER'),
1331
+ resetFilter: this.translateService.instant('AG_GRID.RESET_FILTER'),
1332
+ clearFilter: this.translateService.instant('AG_GRID.CLEAR_FILTER'),
1333
+ cancelFilter: this.translateService.instant('AG_GRID.CANCEL_FILTER'),
1334
+ // Filter Titles
1335
+ textFilter: this.translateService.instant('AG_GRID.TEXT_FILTER'),
1336
+ numberFilter: this.translateService.instant('AG_GRID.NUMBER_FILTER'),
1337
+ dateFilter: this.translateService.instant('AG_GRID.DATE_FILTER'),
1338
+ setFilter: this.translateService.instant('AG_GRID.SET_FILTER'),
1339
+ });
1165
1340
  }
1166
1341
  }
1167
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CheckboxRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
1168
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: CheckboxRenderer, isStandalone: true, selector: "ntybase-checkbox-renderer", host: { attributes: { "ntybase-id": "CheckboxRenderer" } }, ngImport: i0, template: "@if (supportClick) {\n<input\n id=\"checkbox\"\n type=\"checkbox\"\n [checked]=\"checked\"\n (click)=\"onClick($event)\"\n/>\n} @if (!supportClick) {\n<input id=\"checkbox\" type=\"checkbox\" [checked]=\"params.value\" disabled />\n}\n\n<label for=\"checkbox\">{{label}}</label>\n", styles: [""] });
1342
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAgGridService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1343
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAgGridService, providedIn: 'root' });
1169
1344
  }
1170
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CheckboxRenderer, decorators: [{
1171
- type: Component,
1172
- args: [{ selector: 'ntybase-checkbox-renderer', imports: [], host: { 'ntybase-id': 'CheckboxRenderer' }, template: "@if (supportClick) {\n<input\n id=\"checkbox\"\n type=\"checkbox\"\n [checked]=\"checked\"\n (click)=\"onClick($event)\"\n/>\n} @if (!supportClick) {\n<input id=\"checkbox\" type=\"checkbox\" [checked]=\"params.value\" disabled />\n}\n\n<label for=\"checkbox\">{{label}}</label>\n" }]
1173
- }] });
1174
-
1175
- class NettyAppsBase {
1176
- // ---------------------------------
1177
- // --- SERVICES ---
1178
- // ---------------------------------
1179
- alertService = inject(AlertService);
1180
- translateService = inject(TranslateService);
1181
- // ---------------------------------
1182
- // --- DOWNLOAD METHODS ---
1183
- // ---------------------------------
1184
- /**
1185
- * Download the given base64Encoded data as file
1186
- *
1187
- * @param base64Data: base64 encoded data
1188
- * @param fileName: filename to download
1189
- */
1190
- downloadFile(base64Data, fileName) {
1191
- if (base64Data == null) {
1192
- return;
1193
- }
1194
- if (fileName == null) {
1195
- return;
1196
- }
1197
- // Check if header is present
1198
- if (!base64Data.startsWith('data:')) {
1199
- console.error('Provided data is not in base64 format (missing header)');
1200
- return;
1201
- }
1202
- const contentType = base64Data.split(';')[0].split(':')[1];
1203
- const byteCharacters = atob(base64Data.split(',')[1]);
1204
- const byteArrays = [];
1205
- for (let i = 0; i < byteCharacters.length; i++) {
1206
- const byteArray = byteCharacters.charCodeAt(i);
1207
- byteArrays.push(byteArray);
1208
- }
1209
- const byteArray = new Uint8Array(byteArrays);
1210
- const blob = new Blob([byteArray], { type: contentType });
1211
- const link = document.createElement('a');
1212
- link.href = URL.createObjectURL(blob);
1213
- link.download = fileName;
1214
- link.click();
1215
- }
1216
- /** Download the given base64Endoced data as text file
1217
- *
1218
- * @param base64EncodedFileData
1219
- * @param fileName
1220
- */
1221
- downloadTextFile(base64EncodedFileData, fileName) {
1222
- // Check if the data has a prefix like "data:application/pdf;base64,"
1223
- if (base64EncodedFileData == null) {
1224
- return;
1225
- }
1226
- if (fileName == null) {
1227
- return;
1228
- }
1229
- let _data = base64EncodedFileData;
1230
- const prefix = 'data:';
1231
- if (_data.startsWith(prefix)) {
1232
- // Remove the prefix
1233
- _data = _data.slice(_data.indexOf(',') + 1);
1234
- }
1235
- // Convert the base64 data to a Uint8Array
1236
- const textData = Buffer.from(_data ?? '', 'base64').toString();
1237
- this.downloadTextFileNotEncoded(textData, fileName);
1238
- }
1239
- /** Save the given text as a text file
1240
- *
1241
- * @param fileData
1242
- * @param fileName
1243
- */
1244
- downloadTextFileNotEncoded(fileData, fileName) {
1245
- if (fileData == null) {
1246
- return;
1247
- }
1248
- if (fileName == null) {
1249
- return;
1250
- }
1251
- // Create a Blob from the Text
1252
- const blob = new Blob([fileData], { type: 'text/plain' });
1253
- // Create a download link
1254
- const url = window.URL.createObjectURL(blob);
1255
- const a = document.createElement('a');
1256
- document.body.appendChild(a);
1257
- a.style.display = 'none';
1258
- a.href = url;
1259
- a.download = fileName ?? 'filename';
1260
- // Trigger the download
1261
- a.click();
1262
- // Clean up
1263
- window.URL.revokeObjectURL(url);
1264
- document.body.removeChild(a);
1345
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAgGridService, decorators: [{
1346
+ type: Injectable,
1347
+ args: [{
1348
+ providedIn: 'root',
1349
+ }]
1350
+ }], ctorParameters: () => [] });
1351
+
1352
+ class SecurityDto {
1353
+ coid = null;
1354
+ userGUID = null;
1355
+ application = '';
1356
+ formCode = '';
1357
+ }
1358
+
1359
+ class SysfunctionProxy {
1360
+ http;
1361
+ environmentProxy;
1362
+ constructor(http, environmentProxy) {
1363
+ this.http = http;
1364
+ this.environmentProxy = environmentProxy;
1265
1365
  }
1266
- /**
1267
- * Download file where the data is provided as blob
1268
- * @param data - Array Buffer data
1269
- * @param type - type of the document.
1366
+ /** Get the authentication list for the given form
1367
+ *
1368
+ * @param formCode
1369
+ * @returns
1270
1370
  */
1271
- downloadBlobFile(data, type, fileName) {
1272
- let blob = new Blob([data], { type: type });
1273
- let downloadLink = document.createElement('a');
1274
- downloadLink.href = window.URL.createObjectURL(blob);
1275
- downloadLink.setAttribute('download', fileName);
1276
- document.body.appendChild(downloadLink);
1277
- downloadLink.click();
1278
- downloadLink.parentNode?.removeChild(downloadLink);
1279
- }
1280
- // ---------------------------------
1281
- // --- INTERFACE IMPLEMENTATIONS ---
1282
- // ---------------------------------
1283
- onDestroy$ = new Subject();
1284
- ngOnDestroy() {
1285
- //Called once, before the instance is destroyed.
1286
- //Add 'implements OnDestroy' to the class.
1287
- this.onDestroy$.next();
1288
- this.onDestroy$.complete();
1371
+ getAuthentication(formCode) {
1372
+ let sysFunctionsURL = this.environmentProxy.getAdminLink('getAuthentication');
1373
+ let securityDto = new SecurityDto();
1374
+ securityDto.formCode = formCode;
1375
+ securityDto.application = this.environmentProxy.getApplicationName();
1376
+ let call$ = this.http.post(sysFunctionsURL, securityDto);
1377
+ return call$.pipe(map((result) => result), catchError$1((error) => {
1378
+ let errorMessage = error.message; //.error.title;
1379
+ return throwError(() => new Error(errorMessage ?? ''));
1380
+ }));
1289
1381
  }
1290
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAppsBase, deps: [], target: i0.ɵɵFactoryTarget.Component });
1291
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: NettyAppsBase, isStandalone: true, selector: "ntybase-netty-apps-base", ngImport: i0, template: "", styles: [""] });
1382
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SysfunctionProxy, deps: [{ token: i1$3.HttpClient }, { token: i2$2.EnvironmentProxy }], target: i0.ɵɵFactoryTarget.Injectable });
1383
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SysfunctionProxy, providedIn: 'root' });
1292
1384
  }
1293
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAppsBase, decorators: [{
1294
- type: Component,
1295
- args: [{ selector: 'ntybase-netty-apps-base', imports: [], template: "" }]
1296
- }] });
1385
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SysfunctionProxy, decorators: [{
1386
+ type: Injectable,
1387
+ args: [{
1388
+ providedIn: 'root',
1389
+ }]
1390
+ }], ctorParameters: () => [{ type: i1$3.HttpClient }, { type: i2$2.EnvironmentProxy }] });
1297
1391
 
1298
- ModuleRegistry.registerModules([
1299
- AllCommunityModule,
1300
- StatusBarModule,
1301
- ClientSideRowModelModule,
1302
- ClipboardModule,
1303
- ExcelExportModule,
1304
- ColumnMenuModule,
1305
- ContextMenuModule,
1306
- CellSelectionModule,
1307
- HighlightChangesModule,
1308
- RowSelectionModule,
1309
- ]);
1310
- // AgGrid Dark Mode Row Style
1311
- const myTheme = themeQuartz.withParams({
1312
- backgroundColor: 'black',
1313
- browserColorScheme: 'dark',
1314
- }, 'dark');
1315
- const FILTER_MODE_KEY = 'nettyapps_filter_mode';
1316
1392
  class NettyAgGridBase extends NettyAppsBase {
1317
- // Input signals
1318
- readOnly = input(false, ...(ngDevMode ? [{ debugName: "readOnly" }] : []));
1319
- popupFilterValid = input(false, ...(ngDevMode ? [{ debugName: "popupFilterValid" }] : []));
1320
- popupValid = input(false, ...(ngDevMode ? [{ debugName: "popupValid" }] : []));
1321
- isEmbedded = input(false, ...(ngDevMode ? [{ debugName: "isEmbedded" }] : []));
1322
- // Parameters pass when the component is embeded into an other
1323
- componantParameterGUID = input('', ...(ngDevMode ? [{ debugName: "componantParameterGUID" }] : []));
1324
- componantParameterType = input('', ...(ngDevMode ? [{ debugName: "componantParameterType" }] : []));
1325
- // Events
1326
- /*
1327
- Selected records event
1328
- @param records: Array of selected records
1329
- */
1330
- onElementSelect = output();
1331
- // AG Grid Filter
1332
- customFilters = signal(this.getStoredFilterMode(), ...(ngDevMode ? [{ debugName: "customFilters" }] : []));
1333
- // Filter section
1334
- isFilterValid = signal(true, ...(ngDevMode ? [{ debugName: "isFilterValid" }] : []));
1335
- isFilterExpanded = signal(true, ...(ngDevMode ? [{ debugName: "isFilterExpanded" }] : []));
1393
+ FILTER_MODE_KEY = 'nettyapps_filter_mode';
1394
+ // AgGrid Dark Mode Row Style
1395
+ myTheme = themeQuartz.withParams({
1396
+ backgroundColor: 'black',
1397
+ browserColorScheme: 'dark',
1398
+ }, 'dark');
1399
+ // ********************************************
1400
+ // *** INPUTS ***
1401
+ // ********************************************
1402
+ readOnly = signal(true, ...(ngDevMode ? [{ debugName: "readOnly" }] : [])); // Is the form in readonly mode
1403
+ popupFilterValid = input(false, ...(ngDevMode ? [{ debugName: "popupFilterValid" }] : [])); // Is the popup filter valid
1404
+ popupValid = input(false, ...(ngDevMode ? [{ debugName: "popupValid" }] : [])); // Is the form in popup mode
1405
+ isEmbedded = input(false, ...(ngDevMode ? [{ debugName: "isEmbedded" }] : [])); // Is the form embedded to an other component
1406
+ // Component identifiers
1407
+ componentName = signal('Invalid', ...(ngDevMode ? [{ debugName: "componentName" }] : []));
1408
+ searchValueName = signal('Invalid_searchValue', ...(ngDevMode ? [{ debugName: "searchValueName" }] : []));
1409
+ preferenceType = signal('Invalid_columnState', ...(ngDevMode ? [{ debugName: "preferenceType" }] : []));
1410
+ searchValue = signal('', ...(ngDevMode ? [{ debugName: "searchValue" }] : []));
1411
+ // Query Parameters can be provide as parameters
1412
+ parameterGUID = signal('', ...(ngDevMode ? [{ debugName: "parameterGUID" }] : []));
1413
+ parameterType = signal('', ...(ngDevMode ? [{ debugName: "parameterType" }] : []));
1414
+ // Services
1415
+ nettyAgGridService = inject(NettyAgGridService);
1416
+ commonService = inject(CommonService);
1417
+ sysFunctionProxy = inject(SysfunctionProxy);
1418
+ environment = inject(EnvironmentProxy);
1336
1419
  // Authentication
1337
1420
  authenticationList = [];
1338
1421
  // User access writes
@@ -1342,15 +1425,75 @@ class NettyAgGridBase extends NettyAppsBase {
1342
1425
  allowDelete = signal(false, ...(ngDevMode ? [{ debugName: "allowDelete" }] : []));
1343
1426
  allowLog = signal(false, ...(ngDevMode ? [{ debugName: "allowLog" }] : []));
1344
1427
  allowRead = signal(true, ...(ngDevMode ? [{ debugName: "allowRead" }] : []));
1345
- // Button action management variables
1346
- menuValid = signal(true, ...(ngDevMode ? [{ debugName: "menuValid" }] : []));
1347
- deleteValid = signal(false, ...(ngDevMode ? [{ debugName: "deleteValid" }] : []));
1348
- selectionValid = signal(false, ...(ngDevMode ? [{ debugName: "selectionValid" }] : []));
1349
- refreshButtonValid = signal(false, ...(ngDevMode ? [{ debugName: "refreshButtonValid" }] : []));
1350
- // Parameters for embeded components
1351
- selectedElement = output();
1428
+ // ---------------------------------------------------
1429
+ // --- RECORD LIST ---
1430
+ // ---------------------------------------------------
1431
+ recordList = signal([], ...(ngDevMode ? [{ debugName: "recordList" }] : []));
1432
+ record = null;
1433
+ /**
1434
+ * Component initialization lifecycle hook Overide for custom initialization
1435
+ */
1436
+ async AfterOnInit() { }
1437
+ /** Set data into the grid */
1438
+ setData(data) {
1439
+ this.recordList.set(data);
1440
+ if (this.columnDefs() == null || this.columnDefs().length == 0) {
1441
+ this.initAgGrid();
1442
+ }
1443
+ if (this.searchValue() && this.gridApi) {
1444
+ this.gridApi.setGridOption('quickFilterText', this.searchValue());
1445
+ if (this.recordList == undefined || this.recordList.length == 0) {
1446
+ if (this.isEmbedded()) {
1447
+ this.alertService.showWarning('@recordNotFoundSearch');
1448
+ }
1449
+ }
1450
+ }
1451
+ }
1452
+ async setAccessRights() {
1453
+ this.authenticationList = await lastValueFrom(this.sysFunctionProxy.getAuthentication(this.componentName())).catch((e) => {
1454
+ return throwError(() => new Error(e));
1455
+ });
1456
+ try {
1457
+ this.allowRead.set(this.authenticationList.find((f) => f.action == 'read')?.allow ?? false);
1458
+ if (this.allowRead() == false) {
1459
+ this.commonService.userNotAllowedToRead();
1460
+ return false;
1461
+ }
1462
+ this.allowAdd.set(false);
1463
+ this.allowEdit.set(false);
1464
+ this.allowDelete.set(false);
1465
+ this.allowLog.set(false);
1466
+ }
1467
+ catch (error) {
1468
+ this.allowAdd.set(false);
1469
+ this.allowEdit.set(false);
1470
+ this.allowDelete.set(false);
1471
+ this.allowLog.set(false);
1472
+ return false;
1473
+ }
1474
+ this.accessRightsProcessed.set(true);
1475
+ return true;
1476
+ }
1477
+ /**
1478
+ * Get stored filter mode from local storage
1479
+ * @returns boolean
1480
+ */
1481
+ getStoredFilterMode() {
1482
+ try {
1483
+ const stored = localStorage.getItem(this.FILTER_MODE_KEY);
1484
+ return stored !== null ? JSON.parse(stored) : true;
1485
+ }
1486
+ catch {
1487
+ return true;
1488
+ }
1489
+ }
1490
+ // *********************************************************
1491
+ // *** AG Grid Management ***
1492
+ // *********************************************************
1493
+ // Component inputs
1494
+ agGridSelectionMode = input('multiRow', ...(ngDevMode ? [{ debugName: "agGridSelectionMode" }] : []));
1352
1495
  // AG-Grid theme setting (dark mode)
1353
- theme = myTheme;
1496
+ theme = this.myTheme;
1354
1497
  // Grid references
1355
1498
  gridApi;
1356
1499
  userGridApi;
@@ -1360,63 +1503,127 @@ class NettyAgGridBase extends NettyAppsBase {
1360
1503
  userColumnDefs = signal(null, ...(ngDevMode ? [{ debugName: "userColumnDefs" }] : []));
1361
1504
  groupMembersColumnDefs = signal(null, ...(ngDevMode ? [{ debugName: "groupMembersColumnDefs" }] : []));
1362
1505
  gridColumnsVisible = signal(true, ...(ngDevMode ? [{ debugName: "gridColumnsVisible" }] : []));
1506
+ gridExpanded = signal(false, ...(ngDevMode ? [{ debugName: "gridExpanded" }] : []));
1363
1507
  // Framework components
1364
1508
  frameworkComponents = null;
1365
1509
  // Selection management
1366
- selectedRows = signal([], ...(ngDevMode ? [{ debugName: "selectedRows" }] : []));
1367
- isSingleRowSelected = computed(() => this.selectedRows().length === 1, ...(ngDevMode ? [{ debugName: "isSingleRowSelected" }] : []));
1368
- isMultipleRowSelected = computed(() => this.selectedRows().length > 0, ...(ngDevMode ? [{ debugName: "isMultipleRowSelected" }] : []));
1369
- // Component identifiers
1370
- gridExpanded = signal(false, ...(ngDevMode ? [{ debugName: "gridExpanded" }] : []));
1371
- componentName = signal('Invalid', ...(ngDevMode ? [{ debugName: "componentName" }] : []));
1372
- searchValueName = signal('Invalid_searchValue', ...(ngDevMode ? [{ debugName: "searchValueName" }] : []));
1373
- preferenceType = signal('Invalid_columnState', ...(ngDevMode ? [{ debugName: "preferenceType" }] : []));
1374
- searchValue = signal('', ...(ngDevMode ? [{ debugName: "searchValue" }] : []));
1375
- // Open component management
1376
- openInPopup = signal(false, ...(ngDevMode ? [{ debugName: "openInPopup" }] : []));
1510
+ selectedRows = signal([], ...(ngDevMode ? [{ debugName: "selectedRows" }] : [])); // Selected rows in the grid
1511
+ isSingleRowSelected = computed(() => this.selectedRows().length === 1, ...(ngDevMode ? [{ debugName: "isSingleRowSelected" }] : [])); // True if only one row is selected
1512
+ isMultipleRowSelected = computed(() => this.selectedRows().length > 0, ...(ngDevMode ? [{ debugName: "isMultipleRowSelected" }] : [])); // True if multiple rows are selected
1377
1513
  // Services
1378
- nettyAgGridService = inject(NettyAgGridService);
1379
- commonService = inject(CommonService);
1380
- router = inject(Router);
1381
- routerActive = inject(ActivatedRoute);
1382
- dialog = inject(MatDialog);
1383
- sysFunctionProxy = inject(SysfunctionProxy);
1384
- environment = inject(EnvironmentProxy);
1385
- // Parse query parameters
1386
- queryParameterGUID = toSignal(this.routerActive.queryParamMap.pipe(map((params) => params.get('parameters')), map((value) => this.parseOrReturnValue(value))), {
1387
- initialValue: null, // set initial value to null
1388
- });
1389
- queryParameterType = toSignal(this.routerActive.queryParamMap.pipe(map((params) => params.get('type')), map((value) => this.parseOrReturnValue(value))), {
1390
- initialValue: null, // set initial value to null
1391
- });
1392
- // Query Parameters can be provide as parameters
1393
- parameterGUID = signal('', ...(ngDevMode ? [{ debugName: "parameterGUID" }] : []));
1394
- parameterType = signal('', ...(ngDevMode ? [{ debugName: "parameterType" }] : []));
1514
+ // AG Grid Filter
1515
+ customFilters = signal(this.getStoredFilterMode(), ...(ngDevMode ? [{ debugName: "customFilters" }] : []));
1516
+ // ---------------------------------------------
1517
+ // --- AG Grid Configuration ---
1518
+ // ---------------------------------------------
1519
+ // Grid configuration options
1520
+ gridOptions = {
1521
+ rowSelection: {
1522
+ mode: this.agGridSelectionMode(), checkboxes: true, headerCheckbox: true,
1523
+ selectAll: 'filtered', hideDisabledCheckboxes: true, suppressRowClickSelection: false,
1524
+ enableCellChangeFlash: true,
1525
+ },
1526
+ };
1527
+ // Statusbar
1528
+ statusBar = {
1529
+ statusPanels: [
1530
+ { statusPanel: 'agTotalRowCountComponent', align: 'left', key: 'rowCount' },
1531
+ { statusPanel: 'agFilteredRowCountComponent' },
1532
+ { statusPanel: 'agSelectedRowCountComponent' },
1533
+ { statusPanel: 'agAggregationComponent' },
1534
+ ],
1535
+ };
1536
+ // ---------------------------------------------
1537
+ // --- AG Grid Functions ---
1538
+ // ---------------------------------------------
1539
+ // Common grid ready handler
1540
+ onGridReady(params) {
1541
+ this.gridApi = params.api;
1542
+ this.setAgGridTranslations();
1543
+ this.gridApi.addEventListener('selectionChanged', () => {
1544
+ // Null-safe approach
1545
+ const selectedNodes = this.gridApi?.getSelectedNodes?.() || [];
1546
+ this.selectedRows.set(selectedNodes.map((node) => node.data));
1547
+ });
1548
+ if (this.searchValue()) {
1549
+ this.gridApi.setGridOption('quickFilterText', this.searchValue());
1550
+ }
1551
+ }
1552
+ onFirstDataRendered(params) {
1553
+ //TODO: Fix this
1554
+ try {
1555
+ this.nettyAgGridService.loadGridUserPreference(this.preferenceType(), this.gridApi);
1556
+ this.expandCollapse();
1557
+ }
1558
+ catch (error) {
1559
+ console.log('OnFirstDataRendered error:', error);
1560
+ }
1561
+ }
1562
+ // Save the user parameters
1563
+ saveGrid(params) {
1564
+ const gridState = {
1565
+ columnState: this.gridApi.getColumnState(),
1566
+ };
1567
+ this.nettyAgGridService.saveGridUserPreference(this.preferenceType(), this.gridApi, JSON.stringify(gridState));
1568
+ }
1569
+ // Grid utilities
1570
+ expandCollapse() {
1571
+ this.gridExpanded.set(this.nettyAgGridService.expandCollapseGrid(this.gridApi, this.gridExpanded()));
1572
+ }
1573
+ quickSearch(searchStr = '') {
1574
+ this.searchValue.set(searchStr);
1575
+ if (this.gridApi) {
1576
+ this.gridApi.setGridOption('quickFilterText', this.searchValue());
1577
+ }
1578
+ sessionStorage.setItem(this.searchValueName(), this.searchValue());
1579
+ }
1580
+ /**
1581
+ * Update a single row in the grid
1582
+ * @param rowData The updated row data
1583
+ * @param idField The field name that serves as unique identifier (default: 'id')
1584
+ */
1585
+ updateRowInGrid(rowData, idField = 'id') {
1586
+ const rowNode = this.gridApi.getRowNode(rowData[idField]);
1587
+ if (rowNode) {
1588
+ rowNode.setData(rowData);
1589
+ const params = { rowNodes: [rowNode], force: true, suppressFlash: false, };
1590
+ this.gridApi.refreshCells(params);
1591
+ }
1592
+ else {
1593
+ this.loadData(); // Reload all data if row not found
1594
+ }
1595
+ }
1596
+ /**
1597
+ * Filter mode change
1598
+ */
1599
+ toggleFilterMode() {
1600
+ const newMode = !this.customFilters();
1601
+ this.customFilters.set(newMode);
1602
+ localStorage.setItem(this.FILTER_MODE_KEY, JSON.stringify(newMode));
1603
+ this.initAgGrid();
1604
+ if (this.gridApi) {
1605
+ this.gridApi.refreshHeader();
1606
+ this.gridApi.setFilterModel(null);
1607
+ const message = this.customFilters()
1608
+ ? '@customFilterModeEnabled'
1609
+ : '@defaultFilterModeEnabled';
1610
+ this.alertService.showAlert(this.translateService.instant(message));
1611
+ }
1612
+ }
1613
+ setAgGridTranslations() {
1614
+ this.nettyAgGridService.setAgGridTranslations(this.gridApi);
1615
+ }
1395
1616
  initAgGrid_extension() {
1396
1617
  if (this.allowEdit() == false && (this.popupValid() ?? false) == false) {
1397
1618
  this.columnDefs().pop();
1398
1619
  this.columnDefs().shift();
1399
1620
  this.columnDefs().unshift({
1400
- headerName: '',
1401
- headerCheckboxSelection: true,
1402
- sortable: true,
1403
- resizable: true,
1404
- filter: true,
1405
- minWidth: 60,
1406
- maxWidth: 60,
1407
- suppressSizeToFit: true,
1408
- colId: 'editColumn',
1621
+ headerName: '', headerCheckboxSelection: true, sortable: true, resizable: true,
1622
+ filter: true, minWidth: 60, maxWidth: 60, suppressSizeToFit: true, colId: 'editColumn',
1409
1623
  cellRenderer: 'buttonRenderer',
1410
- cellRendererParams: {
1411
- //onClick: this.onBtnClick.bind(this),
1412
- label: '1',
1413
- type: 'edit',
1414
- },
1415
- });
1416
- this.gridApi.setGridOption('rowSelection', {
1417
- mode: 'multiRow',
1418
- checkboxes: true,
1624
+ cellRendererParams: { label: '1', type: 'edit' },
1419
1625
  });
1626
+ this.gridApi.setGridOption('rowSelection', { mode: 'multiRow', checkboxes: true });
1420
1627
  }
1421
1628
  if (this.popupValid() == true) {
1422
1629
  this.columnDefs().pop();
@@ -1424,155 +1631,158 @@ class NettyAgGridBase extends NettyAppsBase {
1424
1631
  if (this.popupFilterValid() == true) {
1425
1632
  if (this.allowEdit()) {
1426
1633
  this.columnDefs().unshift({
1427
- headerName: '',
1428
- sortable: false,
1429
- resizable: false,
1430
- filter: false,
1431
- minWidth: 50,
1432
- maxWidth: 50,
1433
- suppressSizeToFit: true,
1434
- cellRenderer: 'buttonRenderer',
1634
+ headerName: '', sortable: false, resizable: false, filter: false,
1635
+ minWidth: 50, maxWidth: 50, suppressSizeToFit: true, cellRenderer: 'buttonRenderer',
1435
1636
  cellRendererParams: {
1436
1637
  onClick: this.onBtnClick?.bind(this),
1437
1638
  label: this.translateService.instant('@Update'),
1438
1639
  type: 'popupEdit',
1439
1640
  },
1440
1641
  });
1441
- this.gridApi.setGridOption('rowSelection', {
1442
- mode: 'multiRow',
1443
- checkboxes: true,
1444
- });
1642
+ this.gridApi.setGridOption('rowSelection', { mode: 'multiRow', checkboxes: true, });
1445
1643
  }
1446
1644
  else {
1447
1645
  this.columnDefs().unshift({
1448
- headerName: '',
1449
- sortable: false,
1450
- resizable: false,
1451
- filter: false,
1452
- minWidth: 50,
1453
- maxWidth: 50,
1454
- suppressSizeToFit: true,
1455
- cellStyle: { 'padding-top': '5px' },
1456
- });
1457
- this.gridApi.setGridOption('rowSelection', {
1458
- mode: 'multiRow',
1459
- checkboxes: true,
1646
+ headerName: '', sortable: false, resizable: false, filter: false,
1647
+ minWidth: 50, maxWidth: 50, suppressSizeToFit: true, cellStyle: { 'padding-top': '5px' }
1460
1648
  });
1649
+ this.gridApi.setGridOption('rowSelection', { mode: 'multiRow', checkboxes: true });
1461
1650
  }
1462
1651
  }
1463
1652
  else {
1464
1653
  if (this.allowEdit() == false) {
1465
1654
  this.columnDefs().unshift({
1466
- headerName: '',
1467
- sortable: false,
1468
- resizable: false,
1469
- filter: false,
1470
- minWidth: 50,
1471
- maxWidth: 50,
1472
- suppressSizeToFit: true,
1473
- cellRenderer: 'buttonRenderer',
1655
+ headerName: '', sortable: false, resizable: false, filter: false, minWidth: 50,
1656
+ maxWidth: 50, suppressSizeToFit: true, cellRenderer: 'buttonRenderer',
1474
1657
  cellRendererParams: {
1475
1658
  onClick: this.onBtnClick?.bind(this),
1476
1659
  label: this.translateService.instant('@Update'),
1477
1660
  type: 'popupEdit',
1478
1661
  },
1479
1662
  });
1480
- this.gridApi.setGridOption('rowSelection', {
1481
- mode: 'singleRow',
1482
- checkboxes: false,
1483
- });
1663
+ this.gridApi.setGridOption('rowSelection', { mode: 'singleRow', checkboxes: false });
1484
1664
  }
1485
1665
  if (!this.readOnly()) {
1486
1666
  this.columnDefs().unshift({
1487
- headerName: this.translateService.instant('@select'),
1488
- sortable: false,
1489
- resizable: false,
1490
- filter: false,
1491
- minWidth: 80,
1492
- maxWidth: 80,
1493
- suppressSizeToFit: true,
1494
- cellRenderer: 'buttonRenderer',
1495
- cellStyle: { 'margin-top': '8px' },
1667
+ headerName: this.translateService.instant('@select'), sortable: false, resizable: false,
1668
+ filter: false, minWidth: 80, maxWidth: 80, suppressSizeToFit: true,
1669
+ cellRenderer: 'buttonRenderer', cellStyle: { 'margin-top': '8px' },
1496
1670
  cellRendererParams: {
1497
1671
  onClick: this.onBtnClick?.bind(this),
1498
1672
  label: this.translateService.instant('@select'),
1499
1673
  type: 'popupSelect',
1500
1674
  },
1501
1675
  });
1502
- this.gridApi.setGridOption('rowSelection', {
1503
- mode: 'singleRow',
1504
- checkboxes: false,
1505
- });
1676
+ this.gridApi.setGridOption('rowSelection', { mode: 'singleRow', checkboxes: false });
1506
1677
  }
1507
1678
  }
1508
1679
  }
1509
1680
  }
1510
- // Grid configuration options
1511
- gridOptions = {
1512
- rowSelection: {
1513
- mode: 'multiRow',
1514
- checkboxes: true,
1515
- headerCheckbox: true,
1516
- selectAll: 'filtered',
1517
- hideDisabledCheckboxes: true,
1518
- suppressRowClickSelection: false,
1519
- enableCellChangeFlash: true,
1520
- },
1521
- };
1522
- // Statusbar
1523
- statusBar = {
1524
- statusPanels: [
1525
- {
1526
- statusPanel: 'agTotalRowCountComponent',
1527
- align: 'left',
1528
- key: 'rowCount',
1529
- },
1530
- { statusPanel: 'agFilteredRowCountComponent' },
1531
- { statusPanel: 'agSelectedRowCountComponent' },
1532
- { statusPanel: 'agAggregationComponent' },
1533
- ],
1534
- };
1535
- /**
1536
- * Filter mode change
1537
- */
1538
- toggleFilterMode() {
1539
- const newMode = !this.customFilters();
1540
- this.customFilters.set(newMode);
1541
- localStorage.setItem(FILTER_MODE_KEY, JSON.stringify(newMode));
1542
- this.initAgGrid();
1543
- if (this.gridApi) {
1544
- this.gridApi.refreshHeader();
1545
- this.gridApi.setFilterModel(null);
1546
- const message = this.customFilters()
1547
- ? '@customFilterModeEnabled'
1548
- : '@defaultFilterModeEnabled';
1549
- this.alertService.showAlert(this.translateService.instant(message));
1681
+ // ---------------------------------------------
1682
+ // --- Functions to Show / Hide Grid Columns ---
1683
+ // ---------------------------------------------
1684
+ onShowHideColumns() {
1685
+ this.gridColumnsVisible.update((a) => !a);
1686
+ this.showHideColumnsAsync();
1687
+ }
1688
+ showHideColumnsAsync() {
1689
+ setTimeout(() => this.showHideColumns(), 400);
1690
+ }
1691
+ showHideColumns() {
1692
+ var fields = this.columnDefs()
1693
+ .filter((columnDef) => columnDef.ntyHide === 'x')
1694
+ .map((columnDef) => columnDef.field);
1695
+ this.gridApi?.setColumnsVisible(fields, this.gridColumnsVisible());
1696
+ }
1697
+ showHideEmbeddedColumnsAsync() {
1698
+ setTimeout(() => this.showHideEmbeddedColumns(), 100);
1699
+ }
1700
+ showHideEmbeddedColumns() {
1701
+ if (this.columnDefs() == undefined || this.columnDefs() == null) {
1702
+ return;
1550
1703
  }
1704
+ var fields = this.columnDefs()
1705
+ .filter((columnDef) => columnDef.ntyEmbeddedHide == 'x')
1706
+ .map((columnDef) => columnDef.field);
1707
+ this.gridApi?.setColumnsVisible(fields, !this.isEmbedded());
1551
1708
  }
1552
- getStoredFilterMode() {
1553
- try {
1554
- const stored = localStorage.getItem(FILTER_MODE_KEY);
1555
- return stored !== null ? JSON.parse(stored) : true;
1709
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAgGridBase, deps: null, target: i0.ɵɵFactoryTarget.Component });
1710
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.6", type: NettyAgGridBase, isStandalone: true, selector: "ntybase-ag-grid-base", inputs: { popupFilterValid: { classPropertyName: "popupFilterValid", publicName: "popupFilterValid", isSignal: true, isRequired: false, transformFunction: null }, popupValid: { classPropertyName: "popupValid", publicName: "popupValid", isSignal: true, isRequired: false, transformFunction: null }, isEmbedded: { classPropertyName: "isEmbedded", publicName: "isEmbedded", isSignal: true, isRequired: false, transformFunction: null }, agGridSelectionMode: { classPropertyName: "agGridSelectionMode", publicName: "agGridSelectionMode", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "ntybase-id": "NettyAgGridBase" } }, usesInheritance: true, ngImport: i0, template: ``, isInline: true });
1711
+ }
1712
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAgGridBase, decorators: [{
1713
+ type: Component,
1714
+ args: [{ selector: 'ntybase-ag-grid-base', imports: [], template: ``, host: { 'ntybase-id': 'NettyAgGridBase' } }]
1715
+ }], propDecorators: { popupFilterValid: [{ type: i0.Input, args: [{ isSignal: true, alias: "popupFilterValid", required: false }] }], popupValid: [{ type: i0.Input, args: [{ isSignal: true, alias: "popupValid", required: false }] }], isEmbedded: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEmbedded", required: false }] }], agGridSelectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "agGridSelectionMode", required: false }] }] } });
1716
+
1717
+ ModuleRegistry.registerModules([AllCommunityModule, StatusBarModule, ClientSideRowModelModule, ClipboardModule, ExcelExportModule, ColumnMenuModule,
1718
+ ContextMenuModule, CellSelectionModule, HighlightChangesModule, RowSelectionModule,]);
1719
+ // AgGrid Dark Mode Row Style
1720
+ class NettyAgGridListBase extends NettyAgGridBase {
1721
+ // ********************************************
1722
+ // *** INPUTS ***
1723
+ // ********************************************
1724
+ // Parameters passed when the component is embeded into an other
1725
+ componantParameterGUID = input('', ...(ngDevMode ? [{ debugName: "componantParameterGUID" }] : [])); // GUID of the parameter
1726
+ componantParameterType = input('', ...(ngDevMode ? [{ debugName: "componantParameterType" }] : [])); // Type of the parameter (Field Name)
1727
+ // ********************************************
1728
+ // *** EVENTS ***
1729
+ // ********************************************
1730
+ /*
1731
+ Selected records event
1732
+ @param records: Array of selected records
1733
+ */
1734
+ onElementSelect = output(); // Emit selected records when updated
1735
+ // Parameters for embeded components
1736
+ selectedElement = output(); // Selected element in popup mode
1737
+ // ********************************************
1738
+ // Filter section
1739
+ hasFilter = input(false, ...(ngDevMode ? [{ debugName: "hasFilter" }] : [])); // Does the component have a filter
1740
+ isFilterValid = signal(true, ...(ngDevMode ? [{ debugName: "isFilterValid" }] : [])); // Can the filter be used
1741
+ isFilterExpanded = computed(() => {
1742
+ if (this.isEmbedded()) {
1743
+ return false;
1556
1744
  }
1557
- catch {
1558
- return true;
1745
+ if (!this.hasFilter()) {
1746
+ return false;
1559
1747
  }
1560
- }
1748
+ return this.isFilterValid();
1749
+ }, ...(ngDevMode ? [{ debugName: "isFilterExpanded" }] : []));
1750
+ // Button action management variables
1751
+ menuValid = signal(true, ...(ngDevMode ? [{ debugName: "menuValid" }] : [])); // true: Filter editbox is not visible so the menus are visible
1752
+ refreshButtonValid = signal(false, ...(ngDevMode ? [{ debugName: "refreshButtonValid" }] : [])); // true: Refresh button is enabled
1753
+ // Open component management
1754
+ openEditComponentInPopup = signal(false, ...(ngDevMode ? [{ debugName: "openEditComponentInPopup" }] : []));
1755
+ // Services
1756
+ router = inject(Router);
1757
+ routerActive = inject(ActivatedRoute);
1758
+ dialog = inject(MatDialog);
1759
+ // Parse query parameters
1760
+ queryParameterGUID = toSignal(this.routerActive.queryParamMap.pipe(map((params) => params.get('parameters')), map((value) => this.parseOrReturnValue(value))), {
1761
+ initialValue: null, // set initial value to null
1762
+ });
1763
+ queryParameterType = toSignal(this.routerActive.queryParamMap.pipe(map((params) => params.get('type')), map((value) => this.parseOrReturnValue(value))), {
1764
+ initialValue: null, // set initial value to null
1765
+ });
1766
+ // ---------------------------------------------------
1767
+ // --- RECORD LIST ---
1768
+ // ---------------------------------------------------
1769
+ nettyAppsProxy = injectNettyStandardProxy(this.componentName());
1561
1770
  /**
1562
1771
  * Component initialization lifecycle hook
1563
1772
  */
1564
1773
  async ngOnInit() {
1774
+ this.nettyAppsProxy = injectNettyStandardProxy(this.componentName());
1565
1775
  await this.setAccessRights();
1566
1776
  const savedSearchValue = sessionStorage.getItem(this.searchValueName());
1567
1777
  if (savedSearchValue) {
1568
1778
  this.searchValue.set(savedSearchValue);
1569
- this.loadData(savedSearchValue);
1570
1779
  }
1571
- else {
1780
+ if (!this.hasFilter()) {
1572
1781
  this.loadData();
1573
1782
  }
1574
1783
  // Load user grid preferences
1575
1784
  await this.nettyAgGridService.copyGridUserPereferenceToLocal(this.preferenceType());
1785
+ await this.AfterOnInit();
1576
1786
  }
1577
1787
  parseOrReturnValue(value) {
1578
1788
  if (value) {
@@ -1585,47 +1795,6 @@ class NettyAgGridBase extends NettyAppsBase {
1585
1795
  }
1586
1796
  return null;
1587
1797
  }
1588
- // Common grid ready handler
1589
- onGridReady(params) {
1590
- this.gridApi = params.api;
1591
- this.setAgGridTranslations();
1592
- this.gridApi.addEventListener('selectionChanged', () => {
1593
- // Null-safe approach
1594
- const selectedNodes = this.gridApi?.getSelectedNodes?.() || [];
1595
- this.selectedRows.set(selectedNodes.map((node) => node.data));
1596
- });
1597
- if (this.searchValue()) {
1598
- this.gridApi.setGridOption('quickFilterText', this.searchValue());
1599
- }
1600
- }
1601
- onFirstDataRendered(params) {
1602
- //TODO: Fix this
1603
- try {
1604
- this.nettyAgGridService.loadGridUserPreference(this.preferenceType(), this.gridApi);
1605
- this.expandCollapse();
1606
- }
1607
- catch (error) {
1608
- console.log('OnFirstDataRendered error:', error);
1609
- }
1610
- }
1611
- // Save the user parameters
1612
- saveGrid(params) {
1613
- const gridState = {
1614
- columnState: this.gridApi.getColumnState(),
1615
- };
1616
- this.nettyAgGridService.saveGridUserPreference(this.preferenceType(), this.gridApi, JSON.stringify(gridState));
1617
- }
1618
- // Grid utilities
1619
- expandCollapse() {
1620
- this.gridExpanded.set(this.nettyAgGridService.expandCollapseGrid(this.gridApi, this.gridExpanded()));
1621
- }
1622
- quickSearch(searchStr = '') {
1623
- this.searchValue.set(searchStr);
1624
- if (this.gridApi) {
1625
- this.gridApi.setGridOption('quickFilterText', this.searchValue());
1626
- }
1627
- sessionStorage.setItem(this.searchValueName(), this.searchValue());
1628
- }
1629
1798
  /**
1630
1799
  * Handle back button click
1631
1800
  */
@@ -1705,8 +1874,8 @@ class NettyAgGridBase extends NettyAppsBase {
1705
1874
  ]);
1706
1875
  }
1707
1876
  toggleOpenMode() {
1708
- const newMode = !this.openInPopup();
1709
- this.openInPopup.set(newMode);
1877
+ const newMode = !this.openEditComponentInPopup();
1878
+ this.openEditComponentInPopup.set(newMode);
1710
1879
  localStorage.setItem('openInPopup', JSON.stringify(newMode));
1711
1880
  const message = newMode ? '@openInPopup' : '@openInSidenav';
1712
1881
  this.alertService.showSuccess(message);
@@ -1727,7 +1896,7 @@ class NettyAgGridBase extends NettyAppsBase {
1727
1896
  };
1728
1897
  const savedMode = localStorage.getItem('openInPopup');
1729
1898
  if (savedMode !== null) {
1730
- this.openInPopup.set(JSON.parse(savedMode) === true);
1899
+ this.openEditComponentInPopup.set(JSON.parse(savedMode) === true);
1731
1900
  }
1732
1901
  this.translateService.onLangChange.subscribe(() => {
1733
1902
  this.setAgGridTranslations();
@@ -1746,6 +1915,7 @@ class NettyAgGridBase extends NettyAppsBase {
1746
1915
  this.parameterType.set(this.queryParameterType());
1747
1916
  }
1748
1917
  if (this.hasValidValue(this.parameterGUID)) {
1918
+ this.isFilterValid.set(false);
1749
1919
  this.setFilter();
1750
1920
  this.loadData();
1751
1921
  }
@@ -1761,160 +1931,57 @@ class NettyAgGridBase extends NettyAppsBase {
1761
1931
  if (update.type === this.getEntityType?.()) {
1762
1932
  switch (update.action) {
1763
1933
  case 'add':
1764
- case 'update':
1765
- this.updateRowInGrid(update.data);
1766
- break;
1767
- }
1768
- }
1769
- });
1770
- effect(() => {
1771
- this.onElementSelect.emit(this.selectedRows());
1772
- });
1773
- // Manage filter expanded state
1774
- effect(() => {
1775
- if (this.isEmbedded()) {
1776
- this.isFilterExpanded.set(false);
1777
- }
1778
- else {
1779
- this.isFilterExpanded.set(this.isFilterValid());
1780
- }
1781
- this.showHideEmbeddedColumnsAsync();
1782
- });
1783
- }
1784
- onReverseIsFilterValid() {
1785
- if (this.isEmbedded()) {
1786
- this.isFilterExpanded.set(false);
1787
- }
1788
- else {
1789
- this.isFilterValid.update((a) => !a);
1790
- }
1791
- }
1792
- /**
1793
- * Validates if the given value is equal to null,undefined or ''
1794
- * @param value
1795
- * @returns true if has a valid value
1796
- */
1797
- hasValidValue(value) {
1798
- if (value == null || value == undefined) {
1799
- return false;
1800
- }
1801
- if (value == '') {
1802
- return false;
1803
- }
1804
- return true;
1805
- }
1806
- setAgGridTranslations() {
1807
- if (this.gridApi) {
1808
- this.gridApi.setGridOption('localeText', {
1809
- // Status panel translate
1810
- totalRows: this.translateService.instant('AG_GRID.TOTAL_ROWS'),
1811
- filteredRows: this.translateService.instant('AG_GRID.FILTERED_ROWS'),
1812
- selectedRows: this.translateService.instant('AG_GRID.SELECTED_ROWS'),
1813
- noRowsToShow: this.translateService.instant('AG_GRID.NO_ROWS_TO_SHOW'),
1814
- loadingOoo: this.translateService.instant('AG_GRID.LOADING'),
1815
- // Context menu translations
1816
- copy: this.translateService.instant('AG_GRID.COPY'),
1817
- copyWithHeaders: this.translateService.instant('AG_GRID.COPY_WITH_HEADERS'),
1818
- copyWithGroupHeaders: this.translateService.instant('AG_GRID.COPY_WITH_GROUP_HEADERS'),
1819
- paste: this.translateService.instant('AG_GRID.PASTE'),
1820
- export: this.translateService.instant('AG_GRID.EXPORT'),
1821
- csvExport: this.translateService.instant('AG_GRID.CSV_EXPORT'),
1822
- excelExport: this.translateService.instant('AG_GRID.EXCEL_EXPORT'),
1823
- pinColumn: this.translateService.instant('AG_GRID.PIN_COLUMN'),
1824
- pinLeft: this.translateService.instant('AG_GRID.PIN_LEFT'),
1825
- pinRight: this.translateService.instant('AG_GRID.PIN_RIGHT'),
1826
- noPin: this.translateService.instant('AG_GRID.NO_PIN'),
1827
- sortAscending: this.translateService.instant('AG_GRID.SORT_ASCENDING'),
1828
- sortDescending: this.translateService.instant('AG_GRID.SORT_DESCENDING'),
1829
- autosizeThisColumn: this.translateService.instant('AG_GRID.AUTOSIZE_THIS_COLUMN'),
1830
- autosizeAllColumns: this.translateService.instant('AG_GRID.AUTOSIZE_ALL_COLUMNS'),
1831
- resetColumns: this.translateService.instant('AG_GRID.RESET_COLUMNS'),
1832
- expandAll: this.translateService.instant('AG_GRID.EXPAND_ALL'),
1833
- collapseAll: this.translateService.instant('AG_GRID.COLLAPSE_ALL'),
1834
- exportToExcel: this.translateService.instant('AG_GRID.EXPORT_TO_EXCEL'),
1835
- sheetName: this.translateService.instant('AG_GRID.SHEET_NAME'),
1836
- exportAsExcelTable: this.translateService.instant('AG_GRID.EXPORT_AS_EXCEL_TABLE'),
1837
- rangeSelectTo: this.translateService.instant('AG_GRID.RANGE_SELECT_TO'),
1838
- rangeSelectFrom: this.translateService.instant('AG_GRID.RANGE_SELECT_FROM'),
1839
- rangeSelectCopy: this.translateService.instant('AG_GRID.RANGE_SELECT_COPY'),
1840
- rangeSelectChart: this.translateService.instant('AG_GRID.RANGE_SELECT_CHART'),
1841
- pasteAll: this.translateService.instant('AG_GRID.CLIPBOARD_PASTE'),
1842
- pasteWithoutHeader: this.translateService.instant('AG_GRID.CLIPBOARD_PASTE_WITHOUT_HEADER'),
1843
- copyAll: this.translateService.instant('AG_GRID.CLIPBOARD_COPY'),
1844
- cut: this.translateService.instant('AG_GRID.CLIPBOARD_CUT'),
1845
- // Pagination translations
1846
- page: this.translateService.instant('AG_GRID.PAGE'),
1847
- more: this.translateService.instant('AG_GRID.MORE'),
1848
- to: this.translateService.instant('AG_GRID.TO'),
1849
- of: this.translateService.instant('AG_GRID.OF'),
1850
- next: this.translateService.instant('AG_GRID.NEXT'),
1851
- last: this.translateService.instant('AG_GRID.LAST'),
1852
- first: this.translateService.instant('AG_GRID.FIRST'),
1853
- previous: this.translateService.instant('AG_GRID.PREVIOUS'),
1854
- pageSizeSelectorLabel: this.translateService.instant('AG_GRID.PAGE_SIZE_SELECTOR_LABEL'),
1855
- // Set Filter
1856
- selectAll: this.translateService.instant('AG_GRID.SELECT_ALL'),
1857
- selectAllSearchResults: this.translateService.instant('AG_GRID.SELECT_ALL_SEARCH_RESULTS'),
1858
- searchOoo: this.translateService.instant('AG_GRID.SEARCH_OOO'),
1859
- blanks: this.translateService.instant('AG_GRID.BLANKS'),
1860
- noMatches: this.translateService.instant('AG_GRID.NO_MATCHES'),
1861
- // Number Filter & Text Filter
1862
- filterOoo: this.translateService.instant('AG_GRID.FILTER_OOO'),
1863
- equals: this.translateService.instant('AG_GRID.EQUALS'),
1864
- notEqual: this.translateService.instant('AG_GRID.NOT_EQUAL'),
1865
- blank: this.translateService.instant('AG_GRID.BLANK'),
1866
- notBlank: this.translateService.instant('AG_GRID.NOT_BLANK'),
1867
- empty: this.translateService.instant('AG_GRID.EMPTY'),
1868
- // Number Filter
1869
- lessThan: this.translateService.instant('AG_GRID.LESS_THAN'),
1870
- greaterThan: this.translateService.instant('AG_GRID.GREATER_THAN'),
1871
- lessThanOrEqual: this.translateService.instant('AG_GRID.LESS_THAN_OR_EQUAL'),
1872
- greaterThanOrEqual: this.translateService.instant('AG_GRID.GREATER_THAN_OR_EQUAL'),
1873
- inRange: this.translateService.instant('AG_GRID.IN_RANGE'),
1874
- inRangeStart: this.translateService.instant('AG_GRID.IN_RANGE_START'),
1875
- inRangeEnd: this.translateService.instant('AG_GRID.IN_RANGE_END'),
1876
- // Text Filter
1877
- contains: this.translateService.instant('AG_GRID.CONTAINS'),
1878
- notContains: this.translateService.instant('AG_GRID.NOT_CONTAINS'),
1879
- startsWith: this.translateService.instant('AG_GRID.STARTS_WITH'),
1880
- endsWith: this.translateService.instant('AG_GRID.ENDS_WITH'),
1881
- // Date Filter
1882
- dateFormatOoo: this.translateService.instant('AG_GRID.DATE_FORMAT_OOO'),
1883
- // Filter Conditions
1884
- andCondition: this.translateService.instant('AG_GRID.AND_CONDITION'),
1885
- orCondition: this.translateService.instant('AG_GRID.OR_CONDITION'),
1886
- // Filter Buttons
1887
- applyFilter: this.translateService.instant('AG_GRID.APPLY_FILTER'),
1888
- resetFilter: this.translateService.instant('AG_GRID.RESET_FILTER'),
1889
- clearFilter: this.translateService.instant('AG_GRID.CLEAR_FILTER'),
1890
- cancelFilter: this.translateService.instant('AG_GRID.CANCEL_FILTER'),
1891
- // Filter Titles
1892
- textFilter: this.translateService.instant('AG_GRID.TEXT_FILTER'),
1893
- numberFilter: this.translateService.instant('AG_GRID.NUMBER_FILTER'),
1894
- dateFilter: this.translateService.instant('AG_GRID.DATE_FILTER'),
1895
- setFilter: this.translateService.instant('AG_GRID.SET_FILTER'),
1896
- });
1897
- }
1934
+ case 'update':
1935
+ this.updateRowInGrid(update.data);
1936
+ break;
1937
+ }
1938
+ }
1939
+ });
1940
+ effect(() => { this.onElementSelect.emit(this.selectedRows()); });
1941
+ // Manage filter expanded state
1942
+ effect(() => {
1943
+ this.isEmbedded();
1944
+ this.showHideEmbeddedColumnsAsync();
1945
+ });
1946
+ }
1947
+ onReverseIsFilterValid() {
1948
+ this.isFilterValid.update((a) => !a);
1898
1949
  }
1899
1950
  /**
1900
- * Update a single row in the grid
1901
- * @param rowData The updated row data
1902
- * @param idField The field name that serves as unique identifier (default: 'id')
1951
+ * Validates if the given value is equal to null,undefined or ''
1952
+ * @param value
1953
+ * @returns true if has a valid value
1903
1954
  */
1904
- updateRowInGrid(rowData, idField = 'id') {
1905
- const rowNode = this.gridApi.getRowNode(rowData[idField]);
1906
- if (rowNode) {
1907
- rowNode.setData(rowData);
1908
- const params = {
1909
- rowNodes: [rowNode],
1910
- force: true,
1911
- suppressFlash: false,
1912
- };
1913
- this.gridApi.refreshCells(params);
1955
+ hasValidValue(value) {
1956
+ if (value == null || value == undefined) {
1957
+ return false;
1914
1958
  }
1915
- else {
1916
- this.loadData(); // Reload all data if row not found
1959
+ if (value == '') {
1960
+ return false;
1917
1961
  }
1962
+ return true;
1963
+ }
1964
+ onFilterTextBoxVisibilityChange(isOpen) {
1965
+ this.menuValid.set(!isOpen);
1966
+ }
1967
+ setFilter() { } //override this to set a filter
1968
+ popupClose() {
1969
+ this.selectedElement.emit(null);
1970
+ }
1971
+ // *********************************************************
1972
+ // *** Data Management Functions ***
1973
+ // *********************************************************
1974
+ loadData() {
1975
+ if (this.hasFilter()) {
1976
+ this.setData([]);
1977
+ return;
1978
+ }
1979
+ this.nettyAppsProxy.select(this.record).subscribe({
1980
+ next: (data) => {
1981
+ this.setData(data);
1982
+ },
1983
+ error: (err) => this.alertService.showError('@dataLoadFailed', err),
1984
+ });
1918
1985
  }
1919
1986
  async deleteSelected() {
1920
1987
  if (!this.gridApi)
@@ -1927,7 +1994,7 @@ class NettyAgGridBase extends NettyAppsBase {
1927
1994
  const confirmed = await this.alertService.showConfirm('@confirmDeleteSelectedRecords');
1928
1995
  if (confirmed) {
1929
1996
  const selectedRows = selectedNodes.map((node) => node.data);
1930
- this.deleteRows?.(selectedRows);
1997
+ this.deleteRows(selectedRows);
1931
1998
  }
1932
1999
  }
1933
2000
  async refreshData() {
@@ -1939,84 +2006,58 @@ class NettyAgGridBase extends NettyAppsBase {
1939
2006
  this.alertService.showError(err);
1940
2007
  }
1941
2008
  }
1942
- async setAccessRights() {
1943
- this.authenticationList = await lastValueFrom(this.sysFunctionProxy.getAuthentication(this.componentName())).catch((e) => {
1944
- return throwError(() => new Error(e));
2009
+ deleteRows(rows) {
2010
+ this.nettyAppsProxy.deleteList(rows).subscribe({
2011
+ next: () => {
2012
+ this.gridApi.applyTransaction({ remove: rows });
2013
+ this.alertService.showSuccess('@recordDeletedSuccessfully');
2014
+ },
2015
+ error: (err) => this.alertService.showError(err),
1945
2016
  });
1946
- try {
1947
- this.allowRead.set(this.authenticationList.find((f) => f.action == 'read')?.allow ?? false);
1948
- if (this.allowRead() == false) {
1949
- this.commonService.userNotAllowedToRead();
1950
- return false;
1951
- }
1952
- if (this.allowRead() == true && !this.readOnly()) {
1953
- this.allowAdd.set(this.authenticationList.find((f) => f.action == 'add')?.allow ?? false);
1954
- this.allowEdit.set(this.authenticationList.find((f) => f.action == 'edit')?.allow ??
1955
- false);
1956
- this.allowDelete.set(this.authenticationList.find((f) => f.action == 'delete')?.allow ??
1957
- false);
1958
- this.allowLog.set(this.authenticationList.find((f) => f.action == 'logAccess')?.allow ??
1959
- false);
1960
- }
1961
- else {
1962
- this.allowAdd.set(false);
1963
- this.allowEdit.set(false);
1964
- this.allowDelete.set(false);
1965
- this.allowLog.set(false);
1966
- }
1967
- }
1968
- catch (error) {
1969
- this.allowAdd.set(false);
1970
- this.allowEdit.set(false);
1971
- this.allowDelete.set(false);
1972
- this.allowLog.set(false);
1973
- return false;
1974
- }
1975
- this.accessRightsProcessed.set(true);
1976
- return true;
1977
- }
1978
- onFilterTextBoxVisibilityChange(isOpen) {
1979
- this.menuValid.set(!isOpen);
1980
- }
1981
- setFilter() { } //override this to set a filter
1982
- popupClose() {
1983
- this.selectedElement.emit(null);
1984
- }
1985
- // ---------------------------------------------
1986
- // --- Functions to Show / Hide Grid Columns ---
1987
- // ---------------------------------------------
1988
- onShowHideColumns() {
1989
- this.gridColumnsVisible.update((a) => !a);
1990
- this.showHideColumnsAsync();
1991
- }
1992
- showHideColumnsAsync() {
1993
- setTimeout(() => this.showHideColumns(), 400);
1994
- }
1995
- showHideColumns() {
1996
- var fields = this.columnDefs()
1997
- .filter((columnDef) => columnDef.ntyHide === 'x')
1998
- .map((columnDef) => columnDef.field);
1999
- this.gridApi?.setColumnsVisible(fields, this.gridColumnsVisible());
2000
2017
  }
2001
- showHideEmbeddedColumnsAsync() {
2002
- setTimeout(() => this.showHideEmbeddedColumns(), 100);
2003
- }
2004
- showHideEmbeddedColumns() {
2005
- if (this.columnDefs() == undefined || this.columnDefs() == null) {
2006
- return;
2018
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAgGridListBase, deps: [], target: i0.ɵɵFactoryTarget.Component });
2019
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.6", type: NettyAgGridListBase, isStandalone: true, selector: "ntybase-ag-grid-list-base", inputs: { componantParameterGUID: { classPropertyName: "componantParameterGUID", publicName: "componantParameterGUID", isSignal: true, isRequired: false, transformFunction: null }, componantParameterType: { classPropertyName: "componantParameterType", publicName: "componantParameterType", isSignal: true, isRequired: false, transformFunction: null }, hasFilter: { classPropertyName: "hasFilter", publicName: "hasFilter", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onElementSelect: "onElementSelect", selectedElement: "selectedElement" }, host: { attributes: { "ntybase-id": "NettyAgGridListBase" } }, usesInheritance: true, ngImport: i0, template: ``, isInline: true });
2020
+ }
2021
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAgGridListBase, decorators: [{
2022
+ type: Component,
2023
+ args: [{ selector: 'ntybase-ag-grid-list-base', imports: [], template: ``, host: { 'ntybase-id': 'NettyAgGridListBase' } }]
2024
+ }], ctorParameters: () => [], propDecorators: { componantParameterGUID: [{ type: i0.Input, args: [{ isSignal: true, alias: "componantParameterGUID", required: false }] }], componantParameterType: [{ type: i0.Input, args: [{ isSignal: true, alias: "componantParameterType", required: false }] }], onElementSelect: [{ type: i0.Output, args: ["onElementSelect"] }], selectedElement: [{ type: i0.Output, args: ["selectedElement"] }], hasFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasFilter", required: false }] }] } });
2025
+
2026
+ class NettyAgGridLogBase extends NettyAgGridBase {
2027
+ // ---------------------------------------------------
2028
+ // --- RECORD LIST ---
2029
+ // ---------------------------------------------------
2030
+ nettyAppsProxy = injectNettyStandardLogProxy(this.componentName());
2031
+ /**
2032
+ * Component initialization lifecycle hook
2033
+ */
2034
+ async ngOnInit() {
2035
+ this.nettyAppsProxy = injectNettyStandardLogProxy(this.componentName());
2036
+ await this.setAccessRights();
2037
+ const savedSearchValue = sessionStorage.getItem(this.searchValueName());
2038
+ if (savedSearchValue) {
2039
+ this.searchValue.set(savedSearchValue);
2007
2040
  }
2008
- var fields = this.columnDefs()
2009
- .filter((columnDef) => columnDef.ntyEmbeddedHide == 'x')
2010
- .map((columnDef) => columnDef.field);
2011
- this.gridApi?.setColumnsVisible(fields, !this.isEmbedded());
2041
+ this.loadData();
2042
+ // Load user grid preferences
2043
+ await this.nettyAgGridService.copyGridUserPereferenceToLocal(this.preferenceType());
2044
+ await this.AfterOnInit();
2045
+ }
2046
+ loadData() {
2047
+ this.nettyAppsProxy.selectLog(this.record).subscribe({
2048
+ next: (data) => {
2049
+ this.setData(data);
2050
+ },
2051
+ error: (err) => this.alertService.showError('@dataLoadFailed', err),
2052
+ });
2012
2053
  }
2013
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAgGridBase, deps: [], target: i0.ɵɵFactoryTarget.Component });
2014
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.6", type: NettyAgGridBase, isStandalone: true, selector: "ntybase-ag-grid-base", inputs: { readOnly: { classPropertyName: "readOnly", publicName: "readOnly", isSignal: true, isRequired: false, transformFunction: null }, popupFilterValid: { classPropertyName: "popupFilterValid", publicName: "popupFilterValid", isSignal: true, isRequired: false, transformFunction: null }, popupValid: { classPropertyName: "popupValid", publicName: "popupValid", isSignal: true, isRequired: false, transformFunction: null }, isEmbedded: { classPropertyName: "isEmbedded", publicName: "isEmbedded", isSignal: true, isRequired: false, transformFunction: null }, componantParameterGUID: { classPropertyName: "componantParameterGUID", publicName: "componantParameterGUID", isSignal: true, isRequired: false, transformFunction: null }, componantParameterType: { classPropertyName: "componantParameterType", publicName: "componantParameterType", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onElementSelect: "onElementSelect", selectedElement: "selectedElement" }, host: { attributes: { "ntybase-id": "NettyAgGridBase" } }, usesInheritance: true, ngImport: i0, template: "<p>ag-grid-base works!</p>\n", styles: [""] });
2054
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAgGridLogBase, deps: null, target: i0.ɵɵFactoryTarget.Component });
2055
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: NettyAgGridLogBase, isStandalone: true, selector: "ntybase-ag-grid-log-base", host: { attributes: { "ntybase-id": "NettyAgGridLogBase" } }, usesInheritance: true, ngImport: i0, template: ``, isInline: true });
2015
2056
  }
2016
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAgGridBase, decorators: [{
2057
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAgGridLogBase, decorators: [{
2017
2058
  type: Component,
2018
- args: [{ selector: 'ntybase-ag-grid-base', imports: [], host: { 'ntybase-id': 'NettyAgGridBase' }, template: "<p>ag-grid-base works!</p>\n" }]
2019
- }], ctorParameters: () => [], propDecorators: { readOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readOnly", required: false }] }], popupFilterValid: [{ type: i0.Input, args: [{ isSignal: true, alias: "popupFilterValid", required: false }] }], popupValid: [{ type: i0.Input, args: [{ isSignal: true, alias: "popupValid", required: false }] }], isEmbedded: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEmbedded", required: false }] }], componantParameterGUID: [{ type: i0.Input, args: [{ isSignal: true, alias: "componantParameterGUID", required: false }] }], componantParameterType: [{ type: i0.Input, args: [{ isSignal: true, alias: "componantParameterType", required: false }] }], onElementSelect: [{ type: i0.Output, args: ["onElementSelect"] }], selectedElement: [{ type: i0.Output, args: ["selectedElement"] }] } });
2059
+ args: [{ selector: 'ntybase-ag-grid-log-base', imports: [], template: ``, host: { 'ntybase-id': 'NettyAgGridLogBase' } }]
2060
+ }] });
2020
2061
 
2021
2062
  class NettyAgGridSaveBase extends NettyAppsBase {
2022
2063
  // Services
@@ -2030,6 +2071,11 @@ class NettyAgGridSaveBase extends NettyAppsBase {
2030
2071
  parameters = input('', ...(ngDevMode ? [{ debugName: "parameters" }] : []));
2031
2072
  embedded = input(false, ...(ngDevMode ? [{ debugName: "embedded" }] : []));
2032
2073
  isEmbedded = input(false, ...(ngDevMode ? [{ debugName: "isEmbedded" }] : []));
2074
+ // ---------------------------------------------------
2075
+ // --- RECORD LIST ---
2076
+ // ---------------------------------------------------
2077
+ nettyAppsProxy = injectNettyStandardProxy('');
2078
+ recordType = signal('', ...(ngDevMode ? [{ debugName: "recordType" }] : []));
2033
2079
  currentItem = signal({}, ...(ngDevMode ? [{ debugName: "currentItem" }] : []));
2034
2080
  initialItem = {};
2035
2081
  // Form tracking
@@ -2038,12 +2084,26 @@ class NettyAgGridSaveBase extends NettyAppsBase {
2038
2084
  // Dialog related properties
2039
2085
  dialogRef = inject((MatDialogRef), { optional: true });
2040
2086
  dialogData = inject(MAT_DIALOG_DATA, { optional: true });
2087
+ constructor() {
2088
+ super();
2089
+ effect(() => {
2090
+ this.parameters();
2091
+ this.loadDetailData();
2092
+ });
2093
+ }
2041
2094
  // Controls the visibility of additional editable fields (e.g., password, extra settings)
2042
2095
  // When true, certain input fields become visible for editing
2043
2096
  updateValid = signal(false, ...(ngDevMode ? [{ debugName: "updateValid" }] : []));
2044
2097
  setUpdateValid(value) {
2045
2098
  this.updateValid.set(value);
2046
2099
  }
2100
+ /**
2101
+ * Initialize parameters. This method is called in ngOnInit or constructor
2102
+ */
2103
+ initParameters(urlPath) {
2104
+ this.nettyAppsProxy = injectNettyStandardProxy(urlPath);
2105
+ this.recordType.set(urlPath);
2106
+ }
2047
2107
  /**
2048
2108
  * Determine view mode based on current route
2049
2109
  */
@@ -2058,9 +2118,6 @@ class NettyAgGridSaveBase extends NettyAppsBase {
2058
2118
  this.viewMode.set('fullscreen');
2059
2119
  }
2060
2120
  }
2061
- ngOnInit() {
2062
- this.loadDetailData();
2063
- }
2064
2121
  /**
2065
2122
  * Set data to the form while preserving any unsaved changes
2066
2123
  * @param item - Data object of type T to populate the form
@@ -2081,8 +2138,9 @@ class NettyAgGridSaveBase extends NettyAppsBase {
2081
2138
  * @param data - Data to populate the new instance
2082
2139
  */
2083
2140
  createItemInstance(data) {
2084
- // Default implementation - child classes can override this
2085
- return { ...data };
2141
+ const instance = this.createNewRecord();
2142
+ Object.assign(instance, data);
2143
+ return instance;
2086
2144
  }
2087
2145
  /**
2088
2146
  * Check for form changes
@@ -2120,11 +2178,6 @@ class NettyAgGridSaveBase extends NettyAppsBase {
2120
2178
  }
2121
2179
  return '';
2122
2180
  }
2123
- ngOnChanges(changes) {
2124
- if (changes['parameters']) {
2125
- this.loadDetailData();
2126
- }
2127
- }
2128
2181
  /**
2129
2182
  * Close sidenav or navigate back
2130
2183
  */
@@ -2178,6 +2231,103 @@ class NettyAgGridSaveBase extends NettyAppsBase {
2178
2231
  }
2179
2232
  return true;
2180
2233
  }
2234
+ /**
2235
+ * Save data to API
2236
+ * Handles both create and update operations based on record existence
2237
+ */
2238
+ saveRecord() {
2239
+ if (!this.validateSaveRecord(this.currentItem().getPK())) {
2240
+ return;
2241
+ }
2242
+ if (this.currentItem().getPK()) {
2243
+ this.updateRecord();
2244
+ return;
2245
+ }
2246
+ this.insertRecord();
2247
+ }
2248
+ /**
2249
+ * Create new record
2250
+ */
2251
+ insertRecord() {
2252
+ const createData = {};
2253
+ const currentItem = this.currentItem();
2254
+ Object.keys(currentItem).forEach((key) => {
2255
+ if (currentItem[key] !== undefined && currentItem[key] !== null && currentItem[key] !== '') {
2256
+ createData[key] = currentItem[key];
2257
+ }
2258
+ });
2259
+ this.nettyAppsProxy.insert(createData).subscribe({
2260
+ next: (newRecord) => {
2261
+ this.initializeFormData(newRecord);
2262
+ this.commonService.notifyUpdate(this.recordType(), 'add', newRecord);
2263
+ this.closeSidenav();
2264
+ this.alertService.showSuccess('@recordCreatedSuccessfully');
2265
+ },
2266
+ error: (err) => console.error('@creationFailed:', err),
2267
+ });
2268
+ }
2269
+ /**
2270
+ * Update record
2271
+ */
2272
+ updateRecord() {
2273
+ const changes = this.initialItem.compare(this.currentItem());
2274
+ const updateData = this.createNewRecord();
2275
+ Object.assign(updateData, changes);
2276
+ updateData.setPK(this.currentItem().getPK());
2277
+ this.nettyAppsProxy.update(updateData).subscribe({
2278
+ next: (updatedRecord) => {
2279
+ this.initializeFormData(updatedRecord);
2280
+ this.commonService.notifyUpdate('Item', 'update', updatedRecord);
2281
+ this.closeSidenav();
2282
+ this.alertService.showSuccess('@recordUpdatedSuccessfully');
2283
+ },
2284
+ error: (err) => this.alertService.showError('@updateFailed', err),
2285
+ });
2286
+ }
2287
+ /**
2288
+ * Load data from API based on GUID
2289
+ * Handles both new record creation and existing record editing
2290
+ * guid - Unique identifier of the record
2291
+ */
2292
+ loadDetailData() {
2293
+ const guid = this.getGuidFromParameters();
2294
+ if (!guid) {
2295
+ // If no GUID provided, initialize a new record
2296
+ const newRecord = this.createNewRecord();
2297
+ this.initializeFormData(newRecord);
2298
+ this.updateValid.set(true);
2299
+ return;
2300
+ }
2301
+ // Fetch existing record from API
2302
+ this.nettyAppsProxy.selectGUID(guid).subscribe({
2303
+ next: (record) => {
2304
+ if (!record || !record.getPK()) {
2305
+ this.alertService.showError('@recordNotFound');
2306
+ const cleanPath = this.commonService.getCleanUrlPath();
2307
+ this.router.navigate([cleanPath]);
2308
+ return;
2309
+ }
2310
+ this.initializeFormData(record);
2311
+ this.alertService.showSuccess('@dataLoadSuccess');
2312
+ // Ensure sidenav is visible when in sidenav mode
2313
+ if (this.viewMode() === 'sidenav') {
2314
+ this.commonService.toggleRightSidenav(true);
2315
+ }
2316
+ },
2317
+ error: (err) => {
2318
+ this.alertService.showError('@dataLoadFailed');
2319
+ this.commonService.toggleRightSidenav(false);
2320
+ // Redirect to user list on error in fullscreen mode
2321
+ if (this.viewMode() === 'fullscreen') {
2322
+ const cleanPath = this.commonService.getCleanUrlPath();
2323
+ this.router.navigate([cleanPath]);
2324
+ }
2325
+ },
2326
+ });
2327
+ }
2328
+ // ***************************************************
2329
+ // *** gotoURL Methods ***
2330
+ // ***************************************************
2181
2331
  gotoURL(routePrefix, rightSidenav = [], parameters, type, dialogComponent = null, isNewTab = false, isPopup = this.isEmbedded()) {
2182
2332
  const baseHref = this.environment.getBaseHref().endsWith('/')
2183
2333
  ? this.environment.getBaseHref().slice(0, -1) // Sondaki / işaretini kaldır
@@ -2250,18 +2400,18 @@ class NettyAgGridSaveBase extends NettyAppsBase {
2250
2400
  },
2251
2401
  ]);
2252
2402
  }
2253
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAgGridSaveBase, deps: null, target: i0.ɵɵFactoryTarget.Component });
2254
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.6", type: NettyAgGridSaveBase, isStandalone: true, selector: "ntybase-ag-grid-save-base", inputs: { parameters: { classPropertyName: "parameters", publicName: "parameters", isSignal: true, isRequired: false, transformFunction: null }, embedded: { classPropertyName: "embedded", publicName: "embedded", isSignal: true, isRequired: false, transformFunction: null }, isEmbedded: { classPropertyName: "isEmbedded", publicName: "isEmbedded", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "saveForm", first: true, predicate: ["saveForm"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<p>ag-grid-save-base works!</p>\n", styles: [""] });
2403
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAgGridSaveBase, deps: [], target: i0.ɵɵFactoryTarget.Component });
2404
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.6", type: NettyAgGridSaveBase, isStandalone: true, selector: "ntybase-ag-grid-save-base", inputs: { parameters: { classPropertyName: "parameters", publicName: "parameters", isSignal: true, isRequired: false, transformFunction: null }, embedded: { classPropertyName: "embedded", publicName: "embedded", isSignal: true, isRequired: false, transformFunction: null }, isEmbedded: { classPropertyName: "isEmbedded", publicName: "isEmbedded", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "saveForm", first: true, predicate: ["saveForm"], descendants: true }], usesInheritance: true, ngImport: i0, template: ``, isInline: true });
2255
2405
  }
2256
2406
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NettyAgGridSaveBase, decorators: [{
2257
2407
  type: Component,
2258
- args: [{ selector: 'ntybase-ag-grid-save-base', imports: [], template: "<p>ag-grid-save-base works!</p>\n" }]
2259
- }], propDecorators: { parameters: [{ type: i0.Input, args: [{ isSignal: true, alias: "parameters", required: false }] }], embedded: [{ type: i0.Input, args: [{ isSignal: true, alias: "embedded", required: false }] }], isEmbedded: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEmbedded", required: false }] }], saveForm: [{
2408
+ args: [{ selector: 'ntybase-ag-grid-save-base', imports: [], template: `` }]
2409
+ }], ctorParameters: () => [], propDecorators: { parameters: [{ type: i0.Input, args: [{ isSignal: true, alias: "parameters", required: false }] }], embedded: [{ type: i0.Input, args: [{ isSignal: true, alias: "embedded", required: false }] }], isEmbedded: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEmbedded", required: false }] }], saveForm: [{
2260
2410
  type: ViewChild,
2261
2411
  args: ['saveForm']
2262
2412
  }] } });
2263
2413
 
2264
- class ExcelImportBase extends NettyAgGridBase {
2414
+ class ExcelImportBase extends NettyAgGridListBase {
2265
2415
  dataList = [];
2266
2416
  wopts = { bookType: 'xlsx', type: 'array' };
2267
2417
  fileName = 'PayrollJournalTrans.xlsx';
@@ -2290,11 +2440,11 @@ class ExcelImportBase extends NettyAgGridBase {
2290
2440
  reader.readAsBinaryString(target.files[0]);
2291
2441
  }
2292
2442
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ExcelImportBase, deps: null, target: i0.ɵɵFactoryTarget.Component });
2293
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: ExcelImportBase, isStandalone: true, selector: "ntybase-excel-import-base", usesInheritance: true, ngImport: i0, template: "<p>excel-import-base works!</p>\n", styles: [""] });
2443
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: ExcelImportBase, isStandalone: true, selector: "ntybase-excel-import-base", usesInheritance: true, ngImport: i0, template: ``, isInline: true });
2294
2444
  }
2295
2445
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ExcelImportBase, decorators: [{
2296
2446
  type: Component,
2297
- args: [{ selector: 'ntybase-excel-import-base', imports: [], template: "<p>excel-import-base works!</p>\n" }]
2447
+ args: [{ selector: 'ntybase-excel-import-base', imports: [], template: `` }]
2298
2448
  }] });
2299
2449
 
2300
2450
  class RangeDateTimeFilter {
@@ -2589,7 +2739,7 @@ class RangeDateTimeFilter {
2589
2739
  }
2590
2740
  }
2591
2741
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: RangeDateTimeFilter, deps: [], target: i0.ɵɵFactoryTarget.Component });
2592
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: RangeDateTimeFilter, isStandalone: true, selector: "ntybase-range-date-time-filter", host: { attributes: { "ntybase-id": "RangeDateTimeFilter" } }, ngImport: i0, template: "<div class=\"custom-filter\">\n <div class=\"custom-filter__header\">\n <label class=\"custom-filter__title\">\n {{ '@dateTimeFilter' | translate }}\n </label>\n <input\n type=\"text\"\n class=\"custom-filter__input\"\n [placeholder]=\"'@dateTimeFilterPlaceholder' | translate\"\n [value]=\"filterText\"\n (input)=\"onFilterTextChanged($event)\"\n />\n </div>\n\n <div class=\"custom-filter__help\">\n <strong class=\"custom-filter__help-title\">\n {{ '@formats' | translate }}:\n </strong>\n\n <div class=\"custom-filter__format\">\n {{ '@range' | translate }}:\n <code>start..end</code>\n <span class=\"custom-filter__example\">(today..yesterday)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@singleDate' | translate }}:\n <code>YYYY-MM-DD</code>\n <span class=\"custom-filter__example\">(2024-05-15)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@dateTime' | translate }}:\n <code>YYYY-MM-DD HH:MM</code>\n <span class=\"custom-filter__example\">(2024-05-15 14:30)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@multiple' | translate }}:\n <code>date1,date2,start..end</code>\n </div>\n\n <strong class=\"custom-filter__subtitle\">\n {{ '@specialKeywords' | translate }}:\n </strong>\n\n <div class=\"custom-filter__format\">\n {{ '@turkish' | translate }}:\n <span class=\"custom-filter__keywords\">\n <code class=\"custom-filter__keyword\">bug\u00FCn</code>\n <code class=\"custom-filter__keyword\">d\u00FCn</code>\n <code class=\"custom-filter__keyword\">bu hafta</code>\n <code class=\"custom-filter__keyword\">bu ay</code>\n </span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@english' | translate }}:\n <span class=\"custom-filter__keywords\">\n <code class=\"custom-filter__keyword\">today</code>\n <code class=\"custom-filter__keyword\">yesterday</code>\n <code class=\"custom-filter__keyword\">thisWeek</code>\n <code class=\"custom-filter__keyword\">thisMonth</code>\n </span>\n </div>\n\n <div class=\"custom-filter__note\">{{ '@filterExample' | translate }}</div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }] });
2742
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: RangeDateTimeFilter, isStandalone: true, selector: "ntybase-range-date-time-filter", host: { attributes: { "ntybase-id": "RangeDateTimeFilter" } }, ngImport: i0, template: "<div class=\"custom-filter\">\n <div class=\"custom-filter__header\">\n <label class=\"custom-filter__title\">\n {{ '@dateTimeFilter' | translate }}\n </label>\n <input\n type=\"text\"\n class=\"custom-filter__input\"\n [placeholder]=\"'@dateTimeFilterPlaceholder' | translate\"\n [value]=\"filterText\"\n (input)=\"onFilterTextChanged($event)\"\n />\n </div>\n\n <div class=\"custom-filter__help\">\n <strong class=\"custom-filter__help-title\">\n {{ '@formats' | translate }}:\n </strong>\n\n <div class=\"custom-filter__format\">\n {{ '@range' | translate }}:\n <code>start..end</code>\n <span class=\"custom-filter__example\">(today..yesterday)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@singleDate' | translate }}:\n <code>YYYY-MM-DD</code>\n <span class=\"custom-filter__example\">(2024-05-15)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@dateTime' | translate }}:\n <code>YYYY-MM-DD HH:MM</code>\n <span class=\"custom-filter__example\">(2024-05-15 14:30)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@multiple' | translate }}:\n <code>date1,date2,start..end</code>\n </div>\n\n <strong class=\"custom-filter__subtitle\">\n {{ '@specialKeywords' | translate }}:\n </strong>\n\n <div class=\"custom-filter__format\">\n {{ '@turkish' | translate }}:\n <span class=\"custom-filter__keywords\">\n <code class=\"custom-filter__keyword\">bug\u00FCn</code>\n <code class=\"custom-filter__keyword\">d\u00FCn</code>\n <code class=\"custom-filter__keyword\">bu hafta</code>\n <code class=\"custom-filter__keyword\">bu ay</code>\n </span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@english' | translate }}:\n <span class=\"custom-filter__keywords\">\n <code class=\"custom-filter__keyword\">today</code>\n <code class=\"custom-filter__keyword\">yesterday</code>\n <code class=\"custom-filter__keyword\">thisWeek</code>\n <code class=\"custom-filter__keyword\">thisMonth</code>\n </span>\n </div>\n\n <div class=\"custom-filter__note\">{{ '@filterExample' | translate }}</div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
2593
2743
  }
2594
2744
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: RangeDateTimeFilter, decorators: [{
2595
2745
  type: Component,
@@ -2788,7 +2938,7 @@ class RangeNumberFilter {
2788
2938
  }
2789
2939
  }
2790
2940
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: RangeNumberFilter, deps: [], target: i0.ɵɵFactoryTarget.Component });
2791
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: RangeNumberFilter, isStandalone: true, selector: "ntybase-range-number-filter", host: { attributes: { "ntybase-id": "RangeNumberFilter" } }, ngImport: i0, template: "<div class=\"custom-filter\">\n <div class=\"custom-filter__header\">\n <label class=\"custom-filter__title\">\n {{ '@numberFilter' | translate }}\n </label>\n <input\n type=\"text\"\n class=\"custom-filter__input\"\n [placeholder]=\"'@numberFilterPlaceholder' | translate\"\n [value]=\"filterText\"\n (input)=\"onFilterTextChanged($event)\"\n />\n </div>\n\n <div class=\"custom-filter__help\">\n <strong class=\"custom-filter__help-title\"\n >{{ '@formats' | translate }}:</strong\n >\n\n <div class=\"custom-filter__format\">\n {{ '@closedRange' | translate }}:\n <code>min..max</code>\n <span class=\"custom-filter__example\">(0..5)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@equalOrGreater' | translate }}:\n <code>min..</code>\n <span class=\"custom-filter__example\">(5..)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@equalOrLess' | translate }}:\n <code>..max</code>\n <span class=\"custom-filter__example\">(..10)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@singleValue' | translate }}:\n <code>number</code>\n <span class=\"custom-filter__example\">(10)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@exclusion' | translate }}:\n <code>!number</code>\n <span class=\"custom-filter__example\">(!5)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@rangeExclusion' | translate }}:\n <code>!min..max</code>\n <span class=\"custom-filter__example\">(!5..10)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@multiple' | translate }}:\n <code>value1,value2,range</code>\n </div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }] });
2941
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: RangeNumberFilter, isStandalone: true, selector: "ntybase-range-number-filter", host: { attributes: { "ntybase-id": "RangeNumberFilter" } }, ngImport: i0, template: "<div class=\"custom-filter\">\n <div class=\"custom-filter__header\">\n <label class=\"custom-filter__title\">\n {{ '@numberFilter' | translate }}\n </label>\n <input\n type=\"text\"\n class=\"custom-filter__input\"\n [placeholder]=\"'@numberFilterPlaceholder' | translate\"\n [value]=\"filterText\"\n (input)=\"onFilterTextChanged($event)\"\n />\n </div>\n\n <div class=\"custom-filter__help\">\n <strong class=\"custom-filter__help-title\"\n >{{ '@formats' | translate }}:</strong\n >\n\n <div class=\"custom-filter__format\">\n {{ '@closedRange' | translate }}:\n <code>min..max</code>\n <span class=\"custom-filter__example\">(0..5)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@equalOrGreater' | translate }}:\n <code>min..</code>\n <span class=\"custom-filter__example\">(5..)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@equalOrLess' | translate }}:\n <code>..max</code>\n <span class=\"custom-filter__example\">(..10)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@singleValue' | translate }}:\n <code>number</code>\n <span class=\"custom-filter__example\">(10)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@exclusion' | translate }}:\n <code>!number</code>\n <span class=\"custom-filter__example\">(!5)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@rangeExclusion' | translate }}:\n <code>!min..max</code>\n <span class=\"custom-filter__example\">(!5..10)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@multiple' | translate }}:\n <code>value1,value2,range</code>\n </div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
2792
2942
  }
2793
2943
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: RangeNumberFilter, decorators: [{
2794
2944
  type: Component,
@@ -3041,7 +3191,7 @@ class RangeStringFilter {
3041
3191
  }
3042
3192
  }
3043
3193
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: RangeStringFilter, deps: [], target: i0.ɵɵFactoryTarget.Component });
3044
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: RangeStringFilter, isStandalone: true, selector: "ntybase-range-string-filter", host: { attributes: { "ntybase-id": "RangeStringFilter" } }, ngImport: i0, template: "<div class=\"custom-filter\">\n <div class=\"custom-filter__header\">\n <label class=\"custom-filter__title\">\n {{ '@stringFilter' | translate }}\n </label>\n <input\n type=\"text\"\n class=\"custom-filter__input\"\n [placeholder]=\"'@stringFilterPlaceholder' | translate\"\n [value]=\"filterText\"\n (input)=\"onFilterTextChanged($event)\"\n />\n </div>\n\n <div class=\"custom-filter__help\">\n <strong class=\"custom-filter__help-title\">\n {{ '@formats' | translate }}:\n </strong>\n\n <div class=\"custom-filter__format\">\n {{ '@exactMatch' | translate }}:\n <code>text</code>\n <span class=\"custom-filter__example\">(ahmet)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@startsWith' | translate }}:\n <code>text*</code>\n <span class=\"custom-filter__example\">(ahmet*)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@endsWith' | translate }}:\n <code>*text</code>\n <span class=\"custom-filter__example\">(*metin)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@contains' | translate }}:\n <code>*text*</code>\n <span class=\"custom-filter__example\">(*ahmet*)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@range' | translate }}:\n <code>start..end</code>\n <span class=\"custom-filter__example\">(ali..veli)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n <span class=\"custom-filter__description\">\n {{ '@singleCharacter' | translate }}:\n </span>\n <code>?em</code>\n <span class=\"custom-filter__example\">\n (?em = 3 characters, 2nd and 3rd letters \"em\")\n </span>\n </div>\n\n <div class=\"custom-filter__format\">\n <span class=\"custom-filter__description\">\n {{ '@multipleCharacters' | translate }}:\n </span>\n <code>???in</code>\n <span class=\"custom-filter__example\">\n (5 characters, last 2 letters \"in\")\n </span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@not' | translate }}:\n <code>!condition</code>\n <span class=\"custom-filter__example\">(!*ahmet*, !?hmet)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@regex' | translate }}:\n <code>$$pattern</code>\n <span class=\"custom-filter__example\">($$^[A-Z].*, $$a.*b)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@multiple' | translate }}:\n <code>value1,value2,*end,$$pattern</code>\n </div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }] });
3194
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: RangeStringFilter, isStandalone: true, selector: "ntybase-range-string-filter", host: { attributes: { "ntybase-id": "RangeStringFilter" } }, ngImport: i0, template: "<div class=\"custom-filter\">\n <div class=\"custom-filter__header\">\n <label class=\"custom-filter__title\">\n {{ '@stringFilter' | translate }}\n </label>\n <input\n type=\"text\"\n class=\"custom-filter__input\"\n [placeholder]=\"'@stringFilterPlaceholder' | translate\"\n [value]=\"filterText\"\n (input)=\"onFilterTextChanged($event)\"\n />\n </div>\n\n <div class=\"custom-filter__help\">\n <strong class=\"custom-filter__help-title\">\n {{ '@formats' | translate }}:\n </strong>\n\n <div class=\"custom-filter__format\">\n {{ '@exactMatch' | translate }}:\n <code>text</code>\n <span class=\"custom-filter__example\">(ahmet)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@startsWith' | translate }}:\n <code>text*</code>\n <span class=\"custom-filter__example\">(ahmet*)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@endsWith' | translate }}:\n <code>*text</code>\n <span class=\"custom-filter__example\">(*metin)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@contains' | translate }}:\n <code>*text*</code>\n <span class=\"custom-filter__example\">(*ahmet*)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@range' | translate }}:\n <code>start..end</code>\n <span class=\"custom-filter__example\">(ali..veli)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n <span class=\"custom-filter__description\">\n {{ '@singleCharacter' | translate }}:\n </span>\n <code>?em</code>\n <span class=\"custom-filter__example\">\n (?em = 3 characters, 2nd and 3rd letters \"em\")\n </span>\n </div>\n\n <div class=\"custom-filter__format\">\n <span class=\"custom-filter__description\">\n {{ '@multipleCharacters' | translate }}:\n </span>\n <code>???in</code>\n <span class=\"custom-filter__example\">\n (5 characters, last 2 letters \"in\")\n </span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@not' | translate }}:\n <code>!condition</code>\n <span class=\"custom-filter__example\">(!*ahmet*, !?hmet)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@regex' | translate }}:\n <code>$$pattern</code>\n <span class=\"custom-filter__example\">($$^[A-Z].*, $$a.*b)</span>\n </div>\n\n <div class=\"custom-filter__format\">\n {{ '@multiple' | translate }}:\n <code>value1,value2,*end,$$pattern</code>\n </div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
3045
3195
  }
3046
3196
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: RangeStringFilter, decorators: [{
3047
3197
  type: Component,
@@ -3558,7 +3708,7 @@ class Login extends AuthBase {
3558
3708
  });
3559
3709
  }
3560
3710
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: Login, deps: null, target: i0.ɵɵFactoryTarget.Component });
3561
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: Login, isStandalone: true, selector: "ntybase-login", usesInheritance: true, ngImport: i0, template: "<div class=\"login-page-container\">\n <div class=\"login-image-container\"></div>\n\n <div class=\"login-container glass-effect\">\n <!-- Language Button -->\n <div class=\"language-toggle\">\n @if (icon()) {\n <button mat-icon-button [matMenuTriggerFor]=\"languageMenu\">\n <span class=\"{{ getCurrentLanguageIcon() }}\"></span>\n </button>\n } @else {\n <button\n mat-raised-button\n color=\"primary\"\n [matMenuTriggerFor]=\"languageMenu\"\n >\n {{ currentLanguage }}\n </button>\n }\n </div>\n\n <h2>{{'app_name' | translate }}</h2>\n\n <!-- Language Menu -->\n <mat-menu #languageMenu=\"matMenu\">\n @for (language of languages; track language) {\n <button mat-menu-item (click)=\"setLanguage(language)\">\n <span class=\"{{ getLanguageIcon(language) }}\"></span>\n {{ language }}\n </button>\n }\n </mat-menu>\n\n @if (!isLoading()) {\n <form (ngSubmit)=\"login()\" [formGroup]=\"loginForm\" novalidate>\n @if (error()) {\n <div class=\"error-message\">\n <span class=\"error-icon\">!</span>\n {{ error() }}\n </div>\n }\n\n <div class=\"form-group\">\n <label for=\"username\">{{'@username' | translate}}</label>\n <input\n type=\"text\"\n id=\"username\"\n formControlName=\"username\"\n [placeholder]=\"'@username' | translate\"\n required\n />\n @if (loginForm.controls['username'].invalid &&\n loginForm.controls['username'].touched) {\n <mat-error class=\"validation-error\">\n <span class=\"error-icon\">!</span>\n {{ 'username is required' | translate }}\n </mat-error>\n }\n </div>\n\n <div class=\"form-group\">\n <label for=\"password\">{{'@password' | translate}}</label>\n <input\n type=\"password\"\n id=\"password\"\n formControlName=\"password\"\n [placeholder]=\"'@password' | translate\"\n required\n />\n @if (loginForm.controls['password'].invalid &&\n loginForm.controls['password'].touched) {\n <div class=\"validation-error\">\n <span class=\"error-icon\">!</span>\n {{ 'password is required' | translate }}\n </div>\n }\n </div>\n\n <div class=\"form-group remember\">\n <input type=\"checkbox\" id=\"remember\" formControlName=\"remember\" />\n <label for=\"remember\">{{ '@rememberMe' | translate }}</label>\n <a class=\"forgot-password\" (click)=\"onForgotPassword()\"\n >{{ '@forgotPassword' | translate }}</a\n >\n </div>\n\n <button\n type=\"submit\"\n class=\"login-button\"\n [disabled]=\"loginForm.invalid || isLoading()\"\n >\n {{ '@login' | translate }}\n </button>\n </form>\n } @else {\n <div class=\"loading-spinner\">\n <span>{{ '@loggingIn' | translate }}</span>\n </div>\n }\n\n <div class=\"footer\">\n @if(version() && version() !== '?.?'){\n <div class=\"version\">{{ version() }}</div>\n }\n </div>\n </div>\n</div>\n", styles: [".login-page-container{position:relative;display:flex;height:100vh;background-image:var(--login-bg-image, url(https://images.unsplash.com/photo-1519681393784-d120267933ba?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1124&q=100));background-position:center;background-repeat:no-repeat;background-size:cover;background-attachment:fixed;justify-content:flex-end;padding-right:5%}.login-image-container{display:none}.login-container{width:100%;max-width:400px;padding:2.5rem;display:flex;flex-direction:column;justify-content:center;background:#ffffff1a;border-radius:16px;box-shadow:0 8px 32px #0003;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid rgba(255,255,255,.2);margin:20px;height:fit-content;align-self:center}.login-container h2{color:#fff;text-align:center;margin-bottom:2rem;font-size:1.8rem;font-weight:600;text-shadow:0 2px 4px rgba(0,0,0,.3)}.form-group{margin-bottom:1.5rem}.form-group label{display:block;font-weight:500;color:#fff;font-size:.9rem;text-shadow:0 1px 2px rgba(0,0,0,.3)}.form-group input[type=text],.form-group input[type=password]{width:100%;padding:.85rem 1rem;margin-top:.5rem;border:1px solid rgba(255,255,255,.3);border-radius:8px;font-size:.95rem;background-color:#ffffff26;color:#fff}.form-group input::placeholder{color:#ffffffb3}.form-group input[type=text]:focus,.form-group input[type=password]:focus{outline:none;border-color:#ffffff80;background-color:#ffffff40;box-shadow:0 0 0 3px #ffffff1a}.remember{display:flex;align-items:center;margin-bottom:1.5rem}.remember input{width:18px;height:18px;margin-right:.75rem;cursor:pointer}.remember label{color:#fff;font-size:.9rem;cursor:pointer;-webkit-user-select:none;user-select:none;text-shadow:0 1px 2px rgba(0,0,0,.3)}.forgot-password{margin-left:auto;color:#ffffffe6;font-size:.85rem;text-decoration:none}.forgot-password:hover{text-decoration:underline}.login-button{width:100%;padding:1rem;background-color:#fff3;color:#fff;border:1px solid rgba(255,255,255,.4);border-radius:8px;font-size:1rem;font-weight:500;cursor:pointer;transition:all .2s}.login-button:hover{background-color:#ffffff4d}.loading-spinner{text-align:center;padding:2rem}.loading-spinner p{margin-top:1rem;color:#fff}.footer{margin-top:2rem;text-align:center}.version{color:#ffffffb3;font-size:.8rem;display:block;text-shadow:0 1px 2px rgba(0,0,0,.3)}@media(max-width:768px){.login-page-container{justify-content:center;padding-right:0;align-items:center}.login-container{max-width:90%;margin:20px auto}}.language-toggle{position:absolute;top:20px;right:20px;z-index:10}.language-toggle button{background:#fff3;-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);border:1px solid rgba(255,255,255,.3);cursor:pointer}.language-toggle button:hover{background:#ffffff4d}.language-toggle button mat-icon{color:#fff}.login-container h2{margin-top:.5rem}.flag-icon{width:24px;height:16px;margin-right:8px;border:1px solid #ddd}.error-message{background-color:#f8d7da;color:#721c24;padding:12px 15px;border-radius:4px;margin-bottom:20px;display:flex;align-items:center;border:1px solid #f5c6cb;font-size:14px;animation:fadeIn .3s ease-in-out}.error-message .error-icon{display:inline-block;width:20px;height:20px;background-color:#dc3545;color:#fff;border-radius:50%;text-align:center;line-height:20px;margin-right:10px;font-weight:700;font-size:12px}.validation-error{color:#dc3545;font-size:12px;margin-top:5px;display:flex;align-items:center;animation:fadeIn .3s ease-in-out}.validation-error .error-icon{display:inline-block;width:16px;height:16px;background-color:#dc3545;color:#fff;border-radius:50%;text-align:center;line-height:16px;margin-right:6px;font-weight:700;font-size:10px}input.ng-invalid.ng-touched{border:1px solid #dc3545!important}@keyframes fadeIn{0%{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:translateY(0)}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.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$3.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.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$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i2$3.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: i2$3.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i2$3.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }] });
3711
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: Login, isStandalone: true, selector: "ntybase-login", usesInheritance: true, ngImport: i0, template: "<div class=\"login-page-container\">\n <div class=\"login-image-container\"></div>\n\n <div class=\"login-container glass-effect\">\n <!-- Language Button -->\n <div class=\"language-toggle\">\n @if (icon()) {\n <button mat-icon-button [matMenuTriggerFor]=\"languageMenu\">\n <span class=\"{{ getCurrentLanguageIcon() }}\"></span>\n </button>\n } @else {\n <button\n mat-raised-button\n color=\"primary\"\n [matMenuTriggerFor]=\"languageMenu\"\n >\n {{ currentLanguage }}\n </button>\n }\n </div>\n\n <h2>{{'app_name' | translate }}</h2>\n\n <!-- Language Menu -->\n <mat-menu #languageMenu=\"matMenu\">\n @for (language of languages; track language) {\n <button mat-menu-item (click)=\"setLanguage(language)\">\n <span class=\"{{ getLanguageIcon(language) }}\"></span>\n {{ language }}\n </button>\n }\n </mat-menu>\n\n @if (!isLoading()) {\n <form (ngSubmit)=\"login()\" [formGroup]=\"loginForm\" novalidate>\n @if (error()) {\n <div class=\"error-message\">\n <span class=\"error-icon\">!</span>\n {{ error() }}\n </div>\n }\n\n <div class=\"form-group\">\n <label for=\"username\">{{'@username' | translate}}</label>\n <input\n type=\"text\"\n id=\"username\"\n formControlName=\"username\"\n [placeholder]=\"'@username' | translate\"\n required\n />\n @if (loginForm.controls['username'].invalid &&\n loginForm.controls['username'].touched) {\n <mat-error class=\"validation-error\">\n <span class=\"error-icon\">!</span>\n {{ 'username is required' | translate }}\n </mat-error>\n }\n </div>\n\n <div class=\"form-group\">\n <label for=\"password\">{{'@password' | translate}}</label>\n <input\n type=\"password\"\n id=\"password\"\n formControlName=\"password\"\n [placeholder]=\"'@password' | translate\"\n required\n />\n @if (loginForm.controls['password'].invalid &&\n loginForm.controls['password'].touched) {\n <div class=\"validation-error\">\n <span class=\"error-icon\">!</span>\n {{ 'password is required' | translate }}\n </div>\n }\n </div>\n\n <div class=\"form-group remember\">\n <input type=\"checkbox\" id=\"remember\" formControlName=\"remember\" />\n <label for=\"remember\">{{ '@rememberMe' | translate }}</label>\n <a class=\"forgot-password\" (click)=\"onForgotPassword()\"\n >{{ '@forgotPassword' | translate }}</a\n >\n </div>\n\n <button\n type=\"submit\"\n class=\"login-button\"\n [disabled]=\"loginForm.invalid || isLoading()\"\n >\n {{ '@login' | translate }}\n </button>\n </form>\n } @else {\n <div class=\"loading-spinner\">\n <span>{{ '@loggingIn' | translate }}</span>\n </div>\n }\n\n <div class=\"footer\">\n @if(version() && version() !== '?.?'){\n <div class=\"version\">{{ version() }}</div>\n }\n </div>\n </div>\n</div>\n", styles: [".login-page-container{position:relative;display:flex;height:100vh;background-image:var(--login-bg-image, url(https://images.unsplash.com/photo-1519681393784-d120267933ba?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1124&q=100));background-position:center;background-repeat:no-repeat;background-size:cover;background-attachment:fixed;justify-content:flex-end;padding-right:5%}.login-image-container{display:none}.login-container{width:100%;max-width:400px;padding:2.5rem;display:flex;flex-direction:column;justify-content:center;background:#ffffff1a;border-radius:16px;box-shadow:0 8px 32px #0003;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid rgba(255,255,255,.2);margin:20px;height:fit-content;align-self:center}.login-container h2{color:#fff;text-align:center;margin-bottom:2rem;font-size:1.8rem;font-weight:600;text-shadow:0 2px 4px rgba(0,0,0,.3)}.form-group{margin-bottom:1.5rem}.form-group label{display:block;font-weight:500;color:#fff;font-size:.9rem;text-shadow:0 1px 2px rgba(0,0,0,.3)}.form-group input[type=text],.form-group input[type=password]{width:100%;padding:.85rem 1rem;margin-top:.5rem;border:1px solid rgba(255,255,255,.3);border-radius:8px;font-size:.95rem;background-color:#ffffff26;color:#fff}.form-group input::placeholder{color:#ffffffb3}.form-group input[type=text]:focus,.form-group input[type=password]:focus{outline:none;border-color:#ffffff80;background-color:#ffffff40;box-shadow:0 0 0 3px #ffffff1a}.remember{display:flex;align-items:center;margin-bottom:1.5rem}.remember input{width:18px;height:18px;margin-right:.75rem;cursor:pointer}.remember label{color:#fff;font-size:.9rem;cursor:pointer;-webkit-user-select:none;user-select:none;text-shadow:0 1px 2px rgba(0,0,0,.3)}.forgot-password{margin-left:auto;color:#ffffffe6;font-size:.85rem;text-decoration:none}.forgot-password:hover{text-decoration:underline}.login-button{width:100%;padding:1rem;background-color:#fff3;color:#fff;border:1px solid rgba(255,255,255,.4);border-radius:8px;font-size:1rem;font-weight:500;cursor:pointer;transition:all .2s}.login-button:hover{background-color:#ffffff4d}.loading-spinner{text-align:center;padding:2rem}.loading-spinner p{margin-top:1rem;color:#fff}.footer{margin-top:2rem;text-align:center}.version{color:#ffffffb3;font-size:.8rem;display:block;text-shadow:0 1px 2px rgba(0,0,0,.3)}@media(max-width:768px){.login-page-container{justify-content:center;padding-right:0;align-items:center}.login-container{max-width:90%;margin:20px auto}}.language-toggle{position:absolute;top:20px;right:20px;z-index:10}.language-toggle button{background:#fff3;-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);border:1px solid rgba(255,255,255,.3);cursor:pointer}.language-toggle button:hover{background:#ffffff4d}.language-toggle button mat-icon{color:#fff}.login-container h2{margin-top:.5rem}.flag-icon{width:24px;height:16px;margin-right:8px;border:1px solid #ddd}.error-message{background-color:#f8d7da;color:#721c24;padding:12px 15px;border-radius:4px;margin-bottom:20px;display:flex;align-items:center;border:1px solid #f5c6cb;font-size:14px;animation:fadeIn .3s ease-in-out}.error-message .error-icon{display:inline-block;width:20px;height:20px;background-color:#dc3545;color:#fff;border-radius:50%;text-align:center;line-height:20px;margin-right:10px;font-weight:700;font-size:12px}.validation-error{color:#dc3545;font-size:12px;margin-top:5px;display:flex;align-items:center;animation:fadeIn .3s ease-in-out}.validation-error .error-icon{display:inline-block;width:16px;height:16px;background-color:#dc3545;color:#fff;border-radius:50%;text-align:center;line-height:16px;margin-right:6px;font-weight:700;font-size:10px}input.ng-invalid.ng-touched{border:1px solid #dc3545!important}@keyframes fadeIn{0%{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:translateY(0)}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$4.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$4.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$4.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$4.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$4.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$4.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i2$3.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: i2$3.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i2$3.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
3562
3712
  }
3563
3713
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: Login, decorators: [{
3564
3714
  type: Component,
@@ -3670,7 +3820,7 @@ class MfaLogin extends AuthBase {
3670
3820
  clearInterval(this.countdownInterval);
3671
3821
  }
3672
3822
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: MfaLogin, deps: null, target: i0.ɵɵFactoryTarget.Component });
3673
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: MfaLogin, isStandalone: true, selector: "ntybase-mfa-login", usesInheritance: true, ngImport: i0, template: "<div class=\"login-page-container\">\n <div class=\"login-image-container\"></div>\n\n <div class=\"login-container glass-effect\">\n <!-- Language Button -->\n <div class=\"language-toggle\">\n @if (icon()) {\n <button mat-icon-button [matMenuTriggerFor]=\"languageMenu\">\n <span class=\"{{ getCurrentLanguageIcon() }}\"></span>\n </button>\n } @else {\n <button\n mat-raised-button\n color=\"primary\"\n [matMenuTriggerFor]=\"languageMenu\"\n >\n {{ currentLanguage }}\n </button>\n }\n </div>\n\n <h2>{{'app_name' | translate }}</h2>\n\n <!-- Language Menu -->\n <mat-menu #languageMenu=\"matMenu\">\n @for (language of languages; track language) {\n <button mat-menu-item (click)=\"setLanguage(language)\">\n <span class=\"{{ getLanguageIcon(language) }}\"></span>\n {{ language }}\n </button>\n }\n </mat-menu>\n\n @if (!isLoading()) {\n <form (ngSubmit)=\"login()\" [formGroup]=\"loginForm\" novalidate>\n @if (error()) {\n <div class=\"error-message\">\n <span class=\"error-icon\">!</span>\n {{ error() }}\n </div>\n }\n\n <div class=\"form-group\">\n <label for=\"mfaCode\">{{'mfaCode' | translate}}</label>\n <input\n type=\"text\"\n id=\"mfaCode\"\n formControlName=\"mfaCode\"\n [placeholder]=\"'mfaCode' | translate\"\n required\n />\n @if (loginForm.controls['mfaCode'].invalid &&\n loginForm.controls['mfaCode'].touched) {\n <div class=\"validation-error\">\n <span class=\"error-icon\">!</span>\n {{ 'mfaCode is required' | translate }}\n </div>\n }\n\n <!-- Time -->\n @if (!resendable()) {\n <div class=\"time-remaining\">\n {{ '@tokenCount' | translate }}: {{ getFormattedTime() }}\n </div>\n }\n </div>\n\n <button\n type=\"submit\"\n class=\"login-button\"\n [disabled]=\"loginForm.invalid || isLoading() || !resendable()\"\n >\n {{ '@login' | translate }}\n </button>\n\n @if (resendable()) {\n <div class=\"resend-container\">\n <span (click)=\"onResendMFACode()\" class=\"resend-link\">\n {{ 'resend MFACode' | translate }}\n </span>\n </div>\n }\n </form>\n } @else {\n <div class=\"loading-spinner\">\n <span>{{ '@loggingIn' | translate }}</span>\n </div>\n }\n\n <div class=\"footer\">\n <span class=\"version\">v{{version}}</span>\n </div>\n </div>\n</div>\n", styles: [".login-page-container{position:relative;display:flex;height:100vh;background-image:var(--mfa-login-bg-image, url(https://images.unsplash.com/photo-1519681393784-d120267933ba?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1124&q=100));background-position:center;background-repeat:no-repeat;background-size:cover;background-attachment:fixed;justify-content:flex-end;padding-right:5%}.login-image-container{display:none}.login-container{width:100%;max-width:400px;padding:2.5rem;display:flex;flex-direction:column;justify-content:center;background:#ffffff1a;border-radius:16px;box-shadow:0 8px 32px #0003;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid rgba(255,255,255,.2);margin:20px;height:fit-content;align-self:center}.login-container h2{color:#fff;text-align:center;margin-bottom:2rem;font-size:1.8rem;font-weight:600;text-shadow:0 2px 4px rgba(0,0,0,.3)}.form-group{margin-bottom:1.5rem}.form-group label{display:block;font-weight:500;color:#fff;font-size:.9rem;text-shadow:0 1px 2px rgba(0,0,0,.3)}.form-group input[type=text],.form-group input[type=password]{width:100%;padding:.85rem 1rem;margin-top:.5rem;border:1px solid rgba(255,255,255,.3);border-radius:8px;font-size:.95rem;background-color:#ffffff26;color:#fff}.form-group input::placeholder{color:#ffffffb3}.form-group input[type=text]:focus,.form-group input[type=password]:focus{outline:none;border-color:#ffffff80;background-color:#ffffff40;box-shadow:0 0 0 3px #ffffff1a}.login-button{width:100%;padding:1rem;background-color:#fff3;color:#fff;border:1px solid rgba(255,255,255,.4);border-radius:8px;font-size:1rem;font-weight:500;cursor:pointer;transition:all .2s}.login-button:hover{background-color:#ffffff4d}.loading-spinner{text-align:center;padding:2rem}.loading-spinner p{margin-top:1rem;color:#fff}.footer{margin-top:2rem;text-align:center}.version{color:#ffffffb3;font-size:.8rem;display:block;text-shadow:0 1px 2px rgba(0,0,0,.3)}.language-toggle{position:absolute;top:20px;right:20px;z-index:10}.language-toggle button{background:#fff3;-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);border:1px solid rgba(255,255,255,.3);cursor:pointer}.language-toggle button:hover{background:#ffffff4d}.language-toggle button mat-icon{color:#fff}.login-container h2{margin-top:.5rem}.flag-icon{width:24px;height:16px;margin-right:8px;border:1px solid #ddd}.error-message{background-color:#f8d7da;color:#721c24;padding:12px 15px;border-radius:4px;margin-bottom:20px;display:flex;align-items:center;border:1px solid #f5c6cb;font-size:14px;animation:fadeIn .3s ease-in-out}.error-message .error-icon{display:inline-block;width:20px;height:20px;background-color:#dc3545;color:#fff;border-radius:50%;text-align:center;line-height:20px;margin-right:10px;font-weight:700;font-size:12px}.validation-error{color:#dc3545;font-size:12px;margin-top:5px;display:flex;align-items:center;animation:fadeIn .3s ease-in-out}.validation-error .error-icon{display:inline-block;width:16px;height:16px;background-color:#dc3545;color:#fff;border-radius:50%;text-align:center;line-height:16px;margin-right:6px;font-weight:700;font-size:10px}.invalid-input{border:1px solid #dc3545!important}.invalid-input:focus{box-shadow:0 0 0 .2rem #dc354540}.resend-container{margin-top:15px;text-align:center}.resend-container .resend-link{color:#007bff;cursor:pointer;text-decoration:underline;font-size:13px}.resend-container .resend-link:hover{color:#0056b3}.time-remaining{margin-top:16px;font-size:1rem;color:#f5f5f5}@keyframes fadeIn{0%{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:translateY(0)}}@media(max-width:768px){.login-page-container{justify-content:center;padding-right:0;align-items:center}.login-container{max-width:90%;margin:20px auto}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.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$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.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$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i2$3.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: i2$3.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i2$3.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }] });
3823
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: MfaLogin, isStandalone: true, selector: "ntybase-mfa-login", usesInheritance: true, ngImport: i0, template: "<div class=\"login-page-container\">\n <div class=\"login-image-container\"></div>\n\n <div class=\"login-container glass-effect\">\n <!-- Language Button -->\n <div class=\"language-toggle\">\n @if (icon()) {\n <button mat-icon-button [matMenuTriggerFor]=\"languageMenu\">\n <span class=\"{{ getCurrentLanguageIcon() }}\"></span>\n </button>\n } @else {\n <button\n mat-raised-button\n color=\"primary\"\n [matMenuTriggerFor]=\"languageMenu\"\n >\n {{ currentLanguage }}\n </button>\n }\n </div>\n\n <h2>{{'app_name' | translate }}</h2>\n\n <!-- Language Menu -->\n <mat-menu #languageMenu=\"matMenu\">\n @for (language of languages; track language) {\n <button mat-menu-item (click)=\"setLanguage(language)\">\n <span class=\"{{ getLanguageIcon(language) }}\"></span>\n {{ language }}\n </button>\n }\n </mat-menu>\n\n @if (!isLoading()) {\n <form (ngSubmit)=\"login()\" [formGroup]=\"loginForm\" novalidate>\n @if (error()) {\n <div class=\"error-message\">\n <span class=\"error-icon\">!</span>\n {{ error() }}\n </div>\n }\n\n <div class=\"form-group\">\n <label for=\"mfaCode\">{{'mfaCode' | translate}}</label>\n <input\n type=\"text\"\n id=\"mfaCode\"\n formControlName=\"mfaCode\"\n [placeholder]=\"'mfaCode' | translate\"\n required\n />\n @if (loginForm.controls['mfaCode'].invalid &&\n loginForm.controls['mfaCode'].touched) {\n <div class=\"validation-error\">\n <span class=\"error-icon\">!</span>\n {{ 'mfaCode is required' | translate }}\n </div>\n }\n\n <!-- Time -->\n @if (!resendable()) {\n <div class=\"time-remaining\">\n {{ '@tokenCount' | translate }}: {{ getFormattedTime() }}\n </div>\n }\n </div>\n\n <button\n type=\"submit\"\n class=\"login-button\"\n [disabled]=\"loginForm.invalid || isLoading() || !resendable()\"\n >\n {{ '@login' | translate }}\n </button>\n\n @if (resendable()) {\n <div class=\"resend-container\">\n <span (click)=\"onResendMFACode()\" class=\"resend-link\">\n {{ 'resend MFACode' | translate }}\n </span>\n </div>\n }\n </form>\n } @else {\n <div class=\"loading-spinner\">\n <span>{{ '@loggingIn' | translate }}</span>\n </div>\n }\n\n <div class=\"footer\">\n <span class=\"version\">v{{version}}</span>\n </div>\n </div>\n</div>\n", styles: [".login-page-container{position:relative;display:flex;height:100vh;background-image:var(--mfa-login-bg-image, url(https://images.unsplash.com/photo-1519681393784-d120267933ba?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1124&q=100));background-position:center;background-repeat:no-repeat;background-size:cover;background-attachment:fixed;justify-content:flex-end;padding-right:5%}.login-image-container{display:none}.login-container{width:100%;max-width:400px;padding:2.5rem;display:flex;flex-direction:column;justify-content:center;background:#ffffff1a;border-radius:16px;box-shadow:0 8px 32px #0003;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid rgba(255,255,255,.2);margin:20px;height:fit-content;align-self:center}.login-container h2{color:#fff;text-align:center;margin-bottom:2rem;font-size:1.8rem;font-weight:600;text-shadow:0 2px 4px rgba(0,0,0,.3)}.form-group{margin-bottom:1.5rem}.form-group label{display:block;font-weight:500;color:#fff;font-size:.9rem;text-shadow:0 1px 2px rgba(0,0,0,.3)}.form-group input[type=text],.form-group input[type=password]{width:100%;padding:.85rem 1rem;margin-top:.5rem;border:1px solid rgba(255,255,255,.3);border-radius:8px;font-size:.95rem;background-color:#ffffff26;color:#fff}.form-group input::placeholder{color:#ffffffb3}.form-group input[type=text]:focus,.form-group input[type=password]:focus{outline:none;border-color:#ffffff80;background-color:#ffffff40;box-shadow:0 0 0 3px #ffffff1a}.login-button{width:100%;padding:1rem;background-color:#fff3;color:#fff;border:1px solid rgba(255,255,255,.4);border-radius:8px;font-size:1rem;font-weight:500;cursor:pointer;transition:all .2s}.login-button:hover{background-color:#ffffff4d}.loading-spinner{text-align:center;padding:2rem}.loading-spinner p{margin-top:1rem;color:#fff}.footer{margin-top:2rem;text-align:center}.version{color:#ffffffb3;font-size:.8rem;display:block;text-shadow:0 1px 2px rgba(0,0,0,.3)}.language-toggle{position:absolute;top:20px;right:20px;z-index:10}.language-toggle button{background:#fff3;-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);border:1px solid rgba(255,255,255,.3);cursor:pointer}.language-toggle button:hover{background:#ffffff4d}.language-toggle button mat-icon{color:#fff}.login-container h2{margin-top:.5rem}.flag-icon{width:24px;height:16px;margin-right:8px;border:1px solid #ddd}.error-message{background-color:#f8d7da;color:#721c24;padding:12px 15px;border-radius:4px;margin-bottom:20px;display:flex;align-items:center;border:1px solid #f5c6cb;font-size:14px;animation:fadeIn .3s ease-in-out}.error-message .error-icon{display:inline-block;width:20px;height:20px;background-color:#dc3545;color:#fff;border-radius:50%;text-align:center;line-height:20px;margin-right:10px;font-weight:700;font-size:12px}.validation-error{color:#dc3545;font-size:12px;margin-top:5px;display:flex;align-items:center;animation:fadeIn .3s ease-in-out}.validation-error .error-icon{display:inline-block;width:16px;height:16px;background-color:#dc3545;color:#fff;border-radius:50%;text-align:center;line-height:16px;margin-right:6px;font-weight:700;font-size:10px}.invalid-input{border:1px solid #dc3545!important}.invalid-input:focus{box-shadow:0 0 0 .2rem #dc354540}.resend-container{margin-top:15px;text-align:center}.resend-container .resend-link{color:#007bff;cursor:pointer;text-decoration:underline;font-size:13px}.resend-container .resend-link:hover{color:#0056b3}.time-remaining{margin-top:16px;font-size:1rem;color:#f5f5f5}@keyframes fadeIn{0%{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:translateY(0)}}@media(max-width:768px){.login-page-container{justify-content:center;padding-right:0;align-items:center}.login-container{max-width:90%;margin:20px auto}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$4.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$4.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$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$4.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$4.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$4.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i2$3.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: i2$3.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i2$3.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
3674
3824
  }
3675
3825
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: MfaLogin, decorators: [{
3676
3826
  type: Component,
@@ -3844,7 +3994,7 @@ class ForgotPassword extends AuthBase {
3844
3994
  });
3845
3995
  }
3846
3996
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ForgotPassword, deps: [], target: i0.ɵɵFactoryTarget.Component });
3847
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ForgotPassword, isStandalone: true, selector: "ntybase-forgot-password", usesInheritance: true, ngImport: i0, template: "<div class=\"login-page-container\">\n <div class=\"login-image-container\"></div>\n\n <div class=\"login-container glass-effect\">\n <!-- Language Button -->\n <div class=\"language-toggle\">\n @if (icon()) {\n <button mat-icon-button [matMenuTriggerFor]=\"languageMenu\">\n <span class=\"{{ getCurrentLanguageIcon() }}\"></span>\n </button>\n } @else {\n <button\n mat-raised-button\n color=\"primary\"\n [matMenuTriggerFor]=\"languageMenu\"\n >\n {{ currentLanguage }}\n </button>\n }\n </div>\n\n <h2>{{'app_name' | translate }}</h2>\n\n <!-- Language Menu -->\n <mat-menu #languageMenu=\"matMenu\">\n @for (language of languages; track language) {\n <button mat-menu-item (click)=\"setLanguage(language)\">\n <span class=\"{{ getLanguageIcon(language) }}\"></span>\n {{ language }}\n </button>\n }\n </mat-menu>\n\n @if (!isLoading()) {\n <form\n (ngSubmit)=\"updatePassword()\"\n [formGroup]=\"updatePasswordForm\"\n novalidate\n >\n @if (error()) {\n <div class=\"error-message\">\n <span class=\"error-icon\">!</span>\n {{ error() }}\n </div>\n }\n\n <div class=\"form-group\">\n <label for=\"username\">{{'@username' | translate}}</label>\n <input\n type=\"text\"\n id=\"username\"\n [placeholder]=\"'@username' | translate\"\n formControlName=\"username\"\n required\n />\n </div>\n\n <div class=\"form-group\">\n <label for=\"newPassword\">{{'@password' | translate}}</label>\n <input\n type=\"password\"\n id=\"newPassword\"\n [placeholder]=\"'@password' | translate\"\n formControlName=\"newPassword\"\n required\n />\n @if (updatePasswordForm.controls['newPassword'].invalid &&\n updatePasswordForm.controls['newPassword'].touched) {\n <mat-error class=\"validation-error\">\n <span class=\"error-icon\">!</span>\n {{ 'password is required' | translate }}\n </mat-error>\n }\n </div>\n\n <div class=\"form-group\">\n <label for=\"newPasswordCheck\">{{'@passwordCheck' | translate}}</label>\n <input\n type=\"password\"\n id=\"newPasswordCheck\"\n [placeholder]=\"'@passwordCheck' | translate\"\n formControlName=\"newPasswordCheck\"\n required\n />\n @if (updatePasswordForm.controls['newPasswordCheck'].invalid &&\n updatePasswordForm.controls['newPasswordCheck'].touched) {\n <mat-error class=\"validation-error\">\n <span class=\"error-icon\">!</span>\n {{ 'password is required' | translate }}\n </mat-error>\n }\n </div>\n\n <button\n type=\"submit\"\n class=\"login-button\"\n [disabled]=\"updatePasswordForm.invalid\"\n >\n {{ '@setPassword' | translate }}\n </button>\n </form>\n } @else {\n <!-- Burada eski #loading template'inin i\u00E7eri\u011Fi direkt olarak kullan\u0131l\u0131yor -->\n <div class=\"loading-spinner\">\n <span>{{ '@updatingPassword' | translate }}</span>\n </div>\n }\n\n <div class=\"footer\">\n <span class=\"version\">v{{version}}</span>\n </div>\n </div>\n</div>\n", styles: [".login-page-container{position:relative;display:flex;height:100vh;background-image:var(--forgot-password-bg-image, url(https://images.unsplash.com/photo-1519681393784-d120267933ba?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1124&q=100));background-position:center;background-repeat:no-repeat;background-size:cover;background-attachment:fixed;justify-content:flex-end;padding-right:5%}.login-image-container{display:none}.login-container{width:100%;max-width:400px;padding:2.5rem;display:flex;flex-direction:column;justify-content:center;background:#ffffff1a;border-radius:16px;box-shadow:0 8px 32px #0003;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid rgba(255,255,255,.2);margin:20px;height:fit-content;align-self:center}.login-container h2{color:#fff;text-align:center;margin-bottom:2rem;font-size:1.8rem;font-weight:600;text-shadow:0 2px 4px rgba(0,0,0,.3)}.form-group{margin-bottom:1.5rem}.form-group label{display:block;font-weight:500;color:#fff;font-size:.9rem;text-shadow:0 1px 2px rgba(0,0,0,.3)}.form-group input[type=text],.form-group input[type=password]{width:100%;padding:.85rem 1rem;margin-top:.5rem;border:1px solid rgba(255,255,255,.3);border-radius:8px;font-size:.95rem;background-color:#ffffff26;color:#fff}.form-group input::placeholder{color:#ffffffb3}.form-group input[type=text]:focus,.form-group input[type=password]:focus{outline:none;border-color:#ffffff80;background-color:#ffffff40;box-shadow:0 0 0 3px #ffffff1a}.remember{display:flex;align-items:center;margin-bottom:1.5rem}.remember input{width:18px;height:18px;margin-right:.75rem;cursor:pointer}.remember label{color:#fff;font-size:.9rem;cursor:pointer;-webkit-user-select:none;user-select:none;text-shadow:0 1px 2px rgba(0,0,0,.3)}.forgot-password{margin-left:auto;color:#ffffffe6;font-size:.85rem;text-decoration:none}.forgot-password:hover{text-decoration:underline}.login-button{width:100%;padding:1rem;background-color:#fff3;color:#fff;border:1px solid rgba(255,255,255,.4);border-radius:8px;font-size:1rem;font-weight:500;cursor:pointer;transition:all .2s}.login-button:hover{background-color:#ffffff4d}.loading-spinner{text-align:center;padding:2rem}.loading-spinner p{margin-top:1rem;color:#fff}.footer{margin-top:2rem;text-align:center}.version{color:#ffffffb3;font-size:.8rem;display:block;text-shadow:0 1px 2px rgba(0,0,0,.3)}@media(max-width:768px){.login-page-container{justify-content:center;padding-right:0;align-items:center}.login-container{max-width:90%;margin:20px auto}}.language-toggle{position:absolute;top:20px;right:20px;z-index:10}.language-toggle button{background:#fff3;-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);border:1px solid rgba(255,255,255,.3);cursor:pointer}.language-toggle button:hover{background:#ffffff4d}.language-toggle button mat-icon{color:#fff}.login-container h2{margin-top:.5rem}.flag-icon{width:24px;height:16px;margin-right:8px;border:1px solid #ddd}.error-message{background-color:#f8d7da;color:#721c24;padding:12px 15px;border-radius:4px;margin-bottom:20px;display:flex;align-items:center;border:1px solid #f5c6cb;font-size:14px;animation:fadeIn .3s ease-in-out}.error-message .error-icon{display:inline-block;width:20px;height:20px;background-color:#dc3545;color:#fff;border-radius:50%;text-align:center;line-height:20px;margin-right:10px;font-weight:700;font-size:12px}.validation-error{color:#dc3545;font-size:12px;margin-top:5px;display:flex;align-items:center;animation:fadeIn .3s ease-in-out}.validation-error .error-icon{display:inline-block;width:16px;height:16px;background-color:#dc3545;color:#fff;border-radius:50%;text-align:center;line-height:16px;margin-right:6px;font-weight:700;font-size:10px}input.ng-invalid.ng-touched{border:1px solid #dc3545!important}@keyframes fadeIn{0%{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:translateY(0)}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.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$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.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$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i2$3.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: i2$3.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i2$3.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }] });
3997
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ForgotPassword, isStandalone: true, selector: "ntybase-forgot-password", usesInheritance: true, ngImport: i0, template: "<div class=\"login-page-container\">\n <div class=\"login-image-container\"></div>\n\n <div class=\"login-container glass-effect\">\n <!-- Language Button -->\n <div class=\"language-toggle\">\n @if (icon()) {\n <button mat-icon-button [matMenuTriggerFor]=\"languageMenu\">\n <span class=\"{{ getCurrentLanguageIcon() }}\"></span>\n </button>\n } @else {\n <button\n mat-raised-button\n color=\"primary\"\n [matMenuTriggerFor]=\"languageMenu\"\n >\n {{ currentLanguage }}\n </button>\n }\n </div>\n\n <h2>{{'app_name' | translate }}</h2>\n\n <!-- Language Menu -->\n <mat-menu #languageMenu=\"matMenu\">\n @for (language of languages; track language) {\n <button mat-menu-item (click)=\"setLanguage(language)\">\n <span class=\"{{ getLanguageIcon(language) }}\"></span>\n {{ language }}\n </button>\n }\n </mat-menu>\n\n @if (!isLoading()) {\n <form\n (ngSubmit)=\"updatePassword()\"\n [formGroup]=\"updatePasswordForm\"\n novalidate\n >\n @if (error()) {\n <div class=\"error-message\">\n <span class=\"error-icon\">!</span>\n {{ error() }}\n </div>\n }\n\n <div class=\"form-group\">\n <label for=\"username\">{{'@username' | translate}}</label>\n <input\n type=\"text\"\n id=\"username\"\n [placeholder]=\"'@username' | translate\"\n formControlName=\"username\"\n required\n />\n </div>\n\n <div class=\"form-group\">\n <label for=\"newPassword\">{{'@password' | translate}}</label>\n <input\n type=\"password\"\n id=\"newPassword\"\n [placeholder]=\"'@password' | translate\"\n formControlName=\"newPassword\"\n required\n />\n @if (updatePasswordForm.controls['newPassword'].invalid &&\n updatePasswordForm.controls['newPassword'].touched) {\n <mat-error class=\"validation-error\">\n <span class=\"error-icon\">!</span>\n {{ 'password is required' | translate }}\n </mat-error>\n }\n </div>\n\n <div class=\"form-group\">\n <label for=\"newPasswordCheck\">{{'@passwordCheck' | translate}}</label>\n <input\n type=\"password\"\n id=\"newPasswordCheck\"\n [placeholder]=\"'@passwordCheck' | translate\"\n formControlName=\"newPasswordCheck\"\n required\n />\n @if (updatePasswordForm.controls['newPasswordCheck'].invalid &&\n updatePasswordForm.controls['newPasswordCheck'].touched) {\n <mat-error class=\"validation-error\">\n <span class=\"error-icon\">!</span>\n {{ 'password is required' | translate }}\n </mat-error>\n }\n </div>\n\n <button\n type=\"submit\"\n class=\"login-button\"\n [disabled]=\"updatePasswordForm.invalid\"\n >\n {{ '@setPassword' | translate }}\n </button>\n </form>\n } @else {\n <!-- Burada eski #loading template'inin i\u00E7eri\u011Fi direkt olarak kullan\u0131l\u0131yor -->\n <div class=\"loading-spinner\">\n <span>{{ '@updatingPassword' | translate }}</span>\n </div>\n }\n\n <div class=\"footer\">\n <span class=\"version\">v{{version}}</span>\n </div>\n </div>\n</div>\n", styles: [".login-page-container{position:relative;display:flex;height:100vh;background-image:var(--forgot-password-bg-image, url(https://images.unsplash.com/photo-1519681393784-d120267933ba?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1124&q=100));background-position:center;background-repeat:no-repeat;background-size:cover;background-attachment:fixed;justify-content:flex-end;padding-right:5%}.login-image-container{display:none}.login-container{width:100%;max-width:400px;padding:2.5rem;display:flex;flex-direction:column;justify-content:center;background:#ffffff1a;border-radius:16px;box-shadow:0 8px 32px #0003;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid rgba(255,255,255,.2);margin:20px;height:fit-content;align-self:center}.login-container h2{color:#fff;text-align:center;margin-bottom:2rem;font-size:1.8rem;font-weight:600;text-shadow:0 2px 4px rgba(0,0,0,.3)}.form-group{margin-bottom:1.5rem}.form-group label{display:block;font-weight:500;color:#fff;font-size:.9rem;text-shadow:0 1px 2px rgba(0,0,0,.3)}.form-group input[type=text],.form-group input[type=password]{width:100%;padding:.85rem 1rem;margin-top:.5rem;border:1px solid rgba(255,255,255,.3);border-radius:8px;font-size:.95rem;background-color:#ffffff26;color:#fff}.form-group input::placeholder{color:#ffffffb3}.form-group input[type=text]:focus,.form-group input[type=password]:focus{outline:none;border-color:#ffffff80;background-color:#ffffff40;box-shadow:0 0 0 3px #ffffff1a}.remember{display:flex;align-items:center;margin-bottom:1.5rem}.remember input{width:18px;height:18px;margin-right:.75rem;cursor:pointer}.remember label{color:#fff;font-size:.9rem;cursor:pointer;-webkit-user-select:none;user-select:none;text-shadow:0 1px 2px rgba(0,0,0,.3)}.forgot-password{margin-left:auto;color:#ffffffe6;font-size:.85rem;text-decoration:none}.forgot-password:hover{text-decoration:underline}.login-button{width:100%;padding:1rem;background-color:#fff3;color:#fff;border:1px solid rgba(255,255,255,.4);border-radius:8px;font-size:1rem;font-weight:500;cursor:pointer;transition:all .2s}.login-button:hover{background-color:#ffffff4d}.loading-spinner{text-align:center;padding:2rem}.loading-spinner p{margin-top:1rem;color:#fff}.footer{margin-top:2rem;text-align:center}.version{color:#ffffffb3;font-size:.8rem;display:block;text-shadow:0 1px 2px rgba(0,0,0,.3)}@media(max-width:768px){.login-page-container{justify-content:center;padding-right:0;align-items:center}.login-container{max-width:90%;margin:20px auto}}.language-toggle{position:absolute;top:20px;right:20px;z-index:10}.language-toggle button{background:#fff3;-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);border:1px solid rgba(255,255,255,.3);cursor:pointer}.language-toggle button:hover{background:#ffffff4d}.language-toggle button mat-icon{color:#fff}.login-container h2{margin-top:.5rem}.flag-icon{width:24px;height:16px;margin-right:8px;border:1px solid #ddd}.error-message{background-color:#f8d7da;color:#721c24;padding:12px 15px;border-radius:4px;margin-bottom:20px;display:flex;align-items:center;border:1px solid #f5c6cb;font-size:14px;animation:fadeIn .3s ease-in-out}.error-message .error-icon{display:inline-block;width:20px;height:20px;background-color:#dc3545;color:#fff;border-radius:50%;text-align:center;line-height:20px;margin-right:10px;font-weight:700;font-size:12px}.validation-error{color:#dc3545;font-size:12px;margin-top:5px;display:flex;align-items:center;animation:fadeIn .3s ease-in-out}.validation-error .error-icon{display:inline-block;width:16px;height:16px;background-color:#dc3545;color:#fff;border-radius:50%;text-align:center;line-height:16px;margin-right:6px;font-weight:700;font-size:10px}input.ng-invalid.ng-touched{border:1px solid #dc3545!important}@keyframes fadeIn{0%{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:translateY(0)}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$4.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$4.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$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$4.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$4.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$4.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i2$3.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: i2$3.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i2$3.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
3848
3998
  }
3849
3999
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ForgotPassword, decorators: [{
3850
4000
  type: Component,
@@ -3935,193 +4085,93 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
3935
4085
  args: [{ selector: 'ntybase-netty-base-app', imports: [], template: "" }]
3936
4086
  }] });
3937
4087
 
3938
- const ENVIRONMENT_CONFIG = new InjectionToken('ENVIRONMENT_CONFIG');
3939
- class EnvironmentInfoService {
3940
- config;
3941
- constructor(config) {
3942
- this.config = config;
3943
- }
3944
- getEnvironmentInfo() {
3945
- return this.config;
3946
- }
3947
- getApiUrl() {
3948
- return this.config?.nettyUrls?.apiUrl || '';
3949
- }
3950
- getAdminUrl() {
3951
- return this.config?.nettyUrls?.adminUrl || '';
3952
- }
3953
- isProduction() {
3954
- return this.config?.production || false;
3955
- }
3956
- getVersion() {
3957
- return this.config?.version || 'Unknown';
3958
- }
3959
- getSupportedLanguages() {
3960
- return this.config?.supportedLanguages || [];
3961
- }
3962
- getDefaultLanguage() {
3963
- return this.config?.defaultLanguage || '';
3964
- }
3965
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EnvironmentInfoService, deps: [{ token: ENVIRONMENT_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
3966
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EnvironmentInfoService, providedIn: 'root' });
3967
- }
3968
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EnvironmentInfoService, decorators: [{
3969
- type: Injectable,
3970
- args: [{
3971
- providedIn: 'root',
3972
- }]
3973
- }], ctorParameters: () => [{ type: undefined, decorators: [{
3974
- type: Optional
3975
- }, {
3976
- type: Inject,
3977
- args: [ENVIRONMENT_CONFIG]
3978
- }] }] });
3979
-
3980
4088
  class EnvironmentInfo {
3981
- environmentService;
3982
4089
  showNettyInfo = true;
3983
- environmentConfig = null;
4090
+ environmentProxy = inject(EnvironmentProxy);
3984
4091
  get hasConfig() {
3985
- return this.environmentConfig !== null;
4092
+ return this.environmentProxy.config() !== undefined;
3986
4093
  }
3987
4094
  get version() {
3988
- return this.environmentService.getVersion();
4095
+ return this.environmentProxy.version() ?? "";
3989
4096
  }
3990
4097
  get isProduction() {
3991
- return this.environmentService.isProduction();
4098
+ return false;
3992
4099
  }
3993
4100
  get defaultLanguage() {
3994
- return this.environmentService.getDefaultLanguage();
4101
+ return "tr";
3995
4102
  }
3996
4103
  get supportedLanguages() {
3997
- return this.environmentService.getSupportedLanguages();
4104
+ return [];
3998
4105
  }
3999
4106
  get apiUrl() {
4000
- return this.environmentService.getApiUrl();
4107
+ return this.environmentProxy.apiUrl();
4001
4108
  }
4002
4109
  get adminUrl() {
4003
- return this.environmentService.getAdminUrl();
4110
+ return this.environmentProxy.adminUrl();
4004
4111
  }
4005
4112
  get baseHref() {
4006
- return this.environmentConfig?.nettyUrls?.baseHref || '';
4113
+ return this.environmentProxy.baseHref();
4007
4114
  }
4008
4115
  get application() {
4009
- return this.environmentConfig?.nettyUrls?.application || '';
4010
- }
4011
- constructor(environmentService) {
4012
- this.environmentService = environmentService;
4116
+ return this.environmentProxy.application();
4013
4117
  }
4014
4118
  ngOnInit() {
4015
- this.environmentConfig = this.environmentService.getEnvironmentInfo();
4016
4119
  if (!this.hasConfig) {
4017
4120
  console.warn("Environment konfigürasyonu bulunamadı. ENVIRONMENT_CONFIG token'ı sağlandı mı?");
4018
4121
  }
4019
4122
  }
4020
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EnvironmentInfo, deps: [{ token: EnvironmentInfoService }], target: i0.ɵɵFactoryTarget.Component });
4021
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: EnvironmentInfo, isStandalone: true, selector: "ntybase-environment-info", inputs: { showNettyInfo: "showNettyInfo" }, ngImport: i0, template: "<div class=\"environment-info\" [class.production]=\"isProduction\">\n <div class=\"info-card\">\n <div class=\"card-header\">\n <h3>{{ 'ENVIRONMENT_INFO.applicationInfo' | translate }}</h3>\n <span class=\"env-badge\" [class.prod]=\"isProduction\">\n {{ isProduction ? ('ENVIRONMENT_INFO.prod' | translate) :\n ('ENVIRONMENT_INFO.dev' | translate) }}\n </span>\n </div>\n\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"label\">{{ 'ENVIRONMENT_INFO.version' | translate }}</span>\n <span class=\"value\">{{ version }}</span>\n </div>\n\n <div class=\"info-item\">\n <span class=\"label\"\n >{{ 'ENVIRONMENT_INFO.defaultLanguage' | translate }}</span\n >\n <span class=\"value\">{{ defaultLanguage }}</span>\n </div>\n\n <div class=\"info-item\">\n <span class=\"label\"\n >{{ 'ENVIRONMENT_INFO.supportedLanguages' | translate }}</span\n >\n <span class=\"value\">{{ supportedLanguages.join(', ') }}</span>\n </div>\n </div>\n\n @if (showNettyInfo) {\n <div class=\"netty-info\">\n <h4>{{ 'ENVIRONMENT_INFO.nettyConnections' | translate }}</h4>\n\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"label\">{{ 'ENVIRONMENT_INFO.apiUrl' | translate }}</span>\n <span class=\"value\">{{ apiUrl }}</span>\n </div>\n\n <div class=\"info-item\">\n <span class=\"label\"\n >{{ 'ENVIRONMENT_INFO.adminUrl' | translate }}</span\n >\n <span class=\"value\">{{ adminUrl }}</span>\n </div>\n\n <div class=\"info-item\">\n <span class=\"label\"\n >{{ 'ENVIRONMENT_INFO.baseHref' | translate }}</span\n >\n <span class=\"value\">{{ baseHref }}</span>\n </div>\n\n <div class=\"info-item\">\n <span class=\"label\"\n >{{ 'ENVIRONMENT_INFO.application' | translate }}</span\n >\n <span class=\"value\">{{ application }}</span>\n </div>\n </div>\n </div>\n } @if (!hasConfig) {\n <div class=\"no-config\">{{ 'ENVIRONMENT_INFO.noConfig' | translate }}</div>\n }\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.environment-info{padding:24px;font-family:Inter,Arial,sans-serif;display:flex;justify-content:center}.info-card{width:100%;max-width:720px;background:var(--mat-sys-on-primary);border-radius:12px;padding:24px;box-shadow:0 8px 24px #0000000f;transition:all .3s ease;border:2px solid var(--mat-sys-on-primary-container)}.card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:24px}.card-header h3{margin:0;font-size:20px;font-weight:600;color:var(--mat-sys-on-primary-container)}.env-badge{padding:6px 12px;border-radius:999px;font-size:12px;font-weight:600;background:var(--mat-sys-on-primary-container);color:var(--mat-sys-surface)}.env-badge.prod{background:var(--mat-sys-on-primary-container);color:var(--mat-sys-surface)}.info-grid{display:grid;grid-template-columns:1fr 2fr;gap:14px 20px;margin-bottom:20px}.info-item{display:contents}.label{color:var(--mat-sys-on-primary-container);font-size:13px;font-weight:500}.value{color:var(--mat-sys-on-primary-container);font-size:14px;font-weight:500;word-break:break-word}.netty-info{margin-top:24px;padding-top:20px;border-top:1px solid var(--mat-sys-primary)}.netty-info h4{margin:0 0 16px;font-size:20px;font-weight:600;color:var(--mat-sys-on-primary-container)}.production .info-card{border-left:6px solid #ef4444}.no-config{margin-top:20px;padding:14px;background:var(--mat-sys-primary-fixed);border:1px solid #fed7aa;border-radius:8px;color:#c2410c;font-weight:600;text-align:center}\n"], dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }] });
4123
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EnvironmentInfo, deps: [], target: i0.ɵɵFactoryTarget.Component });
4124
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: EnvironmentInfo, isStandalone: true, selector: "ntybase-environment-info", inputs: { showNettyInfo: "showNettyInfo" }, ngImport: i0, template: "<div class=\"environment-info\" [class.production]=\"isProduction\">\n <div class=\"info-card\">\n <div class=\"card-header\">\n <h3>{{ 'ENVIRONMENT_INFO.applicationInfo' | translate }}</h3>\n <span class=\"env-badge\" [class.prod]=\"isProduction\">\n {{ isProduction ? ('ENVIRONMENT_INFO.prod' | translate) :\n ('ENVIRONMENT_INFO.dev' | translate) }}\n </span>\n </div>\n\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"label\">{{ 'ENVIRONMENT_INFO.version' | translate }}</span>\n <span class=\"value\">{{ version }}</span>\n </div>\n\n <div class=\"info-item\">\n <span class=\"label\"\n >{{ 'ENVIRONMENT_INFO.defaultLanguage' | translate }}</span\n >\n <span class=\"value\">{{ defaultLanguage }}</span>\n </div>\n\n <div class=\"info-item\">\n <span class=\"label\"\n >{{ 'ENVIRONMENT_INFO.supportedLanguages' | translate }}</span\n >\n <span class=\"value\">{{ supportedLanguages.join(', ') }}</span>\n </div>\n </div>\n\n @if (showNettyInfo) {\n <div class=\"netty-info\">\n <h4>{{ 'ENVIRONMENT_INFO.nettyConnections' | translate }}</h4>\n\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"label\">{{ 'ENVIRONMENT_INFO.apiUrl' | translate }}</span>\n <span class=\"value\">{{ apiUrl }}</span>\n </div>\n\n <div class=\"info-item\">\n <span class=\"label\"\n >{{ 'ENVIRONMENT_INFO.adminUrl' | translate }}</span\n >\n <span class=\"value\">{{ adminUrl }}</span>\n </div>\n\n <div class=\"info-item\">\n <span class=\"label\"\n >{{ 'ENVIRONMENT_INFO.baseHref' | translate }}</span\n >\n <span class=\"value\">{{ baseHref }}</span>\n </div>\n\n <div class=\"info-item\">\n <span class=\"label\"\n >{{ 'ENVIRONMENT_INFO.application' | translate }}</span\n >\n <span class=\"value\">{{ application }}</span>\n </div>\n </div>\n </div>\n } @if (!hasConfig) {\n <div class=\"no-config\">{{ 'ENVIRONMENT_INFO.noConfig' | translate }}</div>\n }\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.environment-info{padding:24px;font-family:Inter,Arial,sans-serif;display:flex;justify-content:center}.info-card{width:100%;max-width:720px;background:var(--mat-sys-on-primary);border-radius:12px;padding:24px;box-shadow:0 8px 24px #0000000f;transition:all .3s ease;border:2px solid var(--mat-sys-on-primary-container)}.card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:24px}.card-header h3{margin:0;font-size:20px;font-weight:600;color:var(--mat-sys-on-primary-container)}.env-badge{padding:6px 12px;border-radius:999px;font-size:12px;font-weight:600;background:var(--mat-sys-on-primary-container);color:var(--mat-sys-surface)}.env-badge.prod{background:var(--mat-sys-on-primary-container);color:var(--mat-sys-surface)}.info-grid{display:grid;grid-template-columns:1fr 2fr;gap:14px 20px;margin-bottom:20px}.info-item{display:contents}.label{color:var(--mat-sys-on-primary-container);font-size:13px;font-weight:500}.value{color:var(--mat-sys-on-primary-container);font-size:14px;font-weight:500;word-break:break-word}.netty-info{margin-top:24px;padding-top:20px;border-top:1px solid var(--mat-sys-primary)}.netty-info h4{margin:0 0 16px;font-size:20px;font-weight:600;color:var(--mat-sys-on-primary-container)}.production .info-card{border-left:6px solid #ef4444}.no-config{margin-top:20px;padding:14px;background:var(--mat-sys-primary-fixed);border:1px solid #fed7aa;border-radius:8px;color:#c2410c;font-weight:600;text-align:center}\n"], dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
4022
4125
  }
4023
4126
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EnvironmentInfo, decorators: [{
4024
4127
  type: Component,
4025
4128
  args: [{ selector: 'ntybase-environment-info', imports: [TranslateModule], template: "<div class=\"environment-info\" [class.production]=\"isProduction\">\n <div class=\"info-card\">\n <div class=\"card-header\">\n <h3>{{ 'ENVIRONMENT_INFO.applicationInfo' | translate }}</h3>\n <span class=\"env-badge\" [class.prod]=\"isProduction\">\n {{ isProduction ? ('ENVIRONMENT_INFO.prod' | translate) :\n ('ENVIRONMENT_INFO.dev' | translate) }}\n </span>\n </div>\n\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"label\">{{ 'ENVIRONMENT_INFO.version' | translate }}</span>\n <span class=\"value\">{{ version }}</span>\n </div>\n\n <div class=\"info-item\">\n <span class=\"label\"\n >{{ 'ENVIRONMENT_INFO.defaultLanguage' | translate }}</span\n >\n <span class=\"value\">{{ defaultLanguage }}</span>\n </div>\n\n <div class=\"info-item\">\n <span class=\"label\"\n >{{ 'ENVIRONMENT_INFO.supportedLanguages' | translate }}</span\n >\n <span class=\"value\">{{ supportedLanguages.join(', ') }}</span>\n </div>\n </div>\n\n @if (showNettyInfo) {\n <div class=\"netty-info\">\n <h4>{{ 'ENVIRONMENT_INFO.nettyConnections' | translate }}</h4>\n\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"label\">{{ 'ENVIRONMENT_INFO.apiUrl' | translate }}</span>\n <span class=\"value\">{{ apiUrl }}</span>\n </div>\n\n <div class=\"info-item\">\n <span class=\"label\"\n >{{ 'ENVIRONMENT_INFO.adminUrl' | translate }}</span\n >\n <span class=\"value\">{{ adminUrl }}</span>\n </div>\n\n <div class=\"info-item\">\n <span class=\"label\"\n >{{ 'ENVIRONMENT_INFO.baseHref' | translate }}</span\n >\n <span class=\"value\">{{ baseHref }}</span>\n </div>\n\n <div class=\"info-item\">\n <span class=\"label\"\n >{{ 'ENVIRONMENT_INFO.application' | translate }}</span\n >\n <span class=\"value\">{{ application }}</span>\n </div>\n </div>\n </div>\n } @if (!hasConfig) {\n <div class=\"no-config\">{{ 'ENVIRONMENT_INFO.noConfig' | translate }}</div>\n }\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.environment-info{padding:24px;font-family:Inter,Arial,sans-serif;display:flex;justify-content:center}.info-card{width:100%;max-width:720px;background:var(--mat-sys-on-primary);border-radius:12px;padding:24px;box-shadow:0 8px 24px #0000000f;transition:all .3s ease;border:2px solid var(--mat-sys-on-primary-container)}.card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:24px}.card-header h3{margin:0;font-size:20px;font-weight:600;color:var(--mat-sys-on-primary-container)}.env-badge{padding:6px 12px;border-radius:999px;font-size:12px;font-weight:600;background:var(--mat-sys-on-primary-container);color:var(--mat-sys-surface)}.env-badge.prod{background:var(--mat-sys-on-primary-container);color:var(--mat-sys-surface)}.info-grid{display:grid;grid-template-columns:1fr 2fr;gap:14px 20px;margin-bottom:20px}.info-item{display:contents}.label{color:var(--mat-sys-on-primary-container);font-size:13px;font-weight:500}.value{color:var(--mat-sys-on-primary-container);font-size:14px;font-weight:500;word-break:break-word}.netty-info{margin-top:24px;padding-top:20px;border-top:1px solid var(--mat-sys-primary)}.netty-info h4{margin:0 0 16px;font-size:20px;font-weight:600;color:var(--mat-sys-on-primary-container)}.production .info-card{border-left:6px solid #ef4444}.no-config{margin-top:20px;padding:14px;background:var(--mat-sys-primary-fixed);border:1px solid #fed7aa;border-radius:8px;color:#c2410c;font-weight:600;text-align:center}\n"] }]
4026
- }], ctorParameters: () => [{ type: EnvironmentInfoService }], propDecorators: { showNettyInfo: [{
4129
+ }], propDecorators: { showNettyInfo: [{
4027
4130
  type: Input
4028
4131
  }] } });
4029
4132
 
4030
- // Library: @nettyapps/ntybase
4031
- function ntyEnvironmentConfigFactory(envService) {
4032
- // SSR Kontrolü (Node.js tarafında window yoktur)
4033
- if (typeof window !== 'undefined') {
4034
- const cachedConfig = window.__env?.fullConfig;
4035
- if (cachedConfig) {
4036
- return cachedConfig;
4037
- }
4133
+ const ENVIRONMENT_CONFIG = new InjectionToken('ENVIRONMENT_CONFIG');
4134
+ class EnvironmentInfoService {
4135
+ config;
4136
+ constructor(config) {
4137
+ this.config = config;
4038
4138
  }
4039
- // Bulamazsa servisten al (servis de token'dan aldığı default'u döndürecek)
4040
- return envService.getEnvironment();
4041
- }
4042
-
4043
- function ntyInitializeEnvironment(envLoader) {
4044
- return () => {
4045
- return envLoader.loadEnvironment().then((config) => {
4046
- // Global erişim için (window) ataması
4047
- if (typeof window !== 'undefined') {
4048
- window.__env = window.__env || {};
4049
- window.__env.fullConfig = config;
4050
- }
4051
- return config;
4052
- });
4053
- };
4054
- }
4055
-
4056
- // 1. Bir Token Tanımlayın
4057
- const NETTY_APP_ENVIRONMENT = new InjectionToken('NETTY_APP_ENVIRONMENT');
4058
- class NtyEnvironmentService {
4059
- defaultEnv;
4060
- // 2. Token'ı Inject Edin
4061
- constructor(defaultEnv) {
4062
- this.defaultEnv = defaultEnv;
4063
- }
4064
- async loadEnvironment() {
4065
- if (!window.__env?.nettyUrls) {
4066
- await this.loadEnvScript();
4067
- if (!window.__env?.nettyUrls) {
4068
- throw new Error('env.js not found!');
4069
- }
4070
- }
4071
- return { ...this.defaultEnv, nettyUrls: window.__env.nettyUrls };
4139
+ getEnvironmentInfo() {
4140
+ return this.config;
4072
4141
  }
4073
- loadEnvScript() {
4074
- return new Promise((resolve, reject) => {
4075
- const script = document.createElement('script');
4076
- script.src = 'assets/env.js';
4077
- script.onload = () => resolve();
4078
- script.onerror = () => reject(new Error('Failed to load env.js'));
4079
- document.head.appendChild(script);
4080
- });
4142
+ getApiUrl() {
4143
+ return this.config?.nettyUrls?.apiUrl || '';
4144
+ }
4145
+ getAdminUrl() {
4146
+ return this.config?.nettyUrls?.adminUrl || '';
4147
+ }
4148
+ isProduction() {
4149
+ return this.config?.production || false;
4150
+ }
4151
+ getVersion() {
4152
+ return this.config?.version || 'Unknown';
4081
4153
  }
4082
- getEnvironment() {
4083
- return { ...this.defaultEnv, nettyUrls: window.__env.nettyUrls };
4154
+ getSupportedLanguages() {
4155
+ return this.config?.supportedLanguages || [];
4156
+ }
4157
+ getDefaultLanguage() {
4158
+ return this.config?.defaultLanguage || '';
4084
4159
  }
4085
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtyEnvironmentService, deps: [{ token: NETTY_APP_ENVIRONMENT }], target: i0.ɵɵFactoryTarget.Injectable });
4086
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtyEnvironmentService, providedIn: 'root' });
4160
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EnvironmentInfoService, deps: [{ token: ENVIRONMENT_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
4161
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EnvironmentInfoService, providedIn: 'root' });
4087
4162
  }
4088
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtyEnvironmentService, decorators: [{
4163
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EnvironmentInfoService, decorators: [{
4089
4164
  type: Injectable,
4090
4165
  args: [{
4091
4166
  providedIn: 'root',
4092
4167
  }]
4093
4168
  }], ctorParameters: () => [{ type: undefined, decorators: [{
4169
+ type: Optional
4170
+ }, {
4094
4171
  type: Inject,
4095
- args: [NETTY_APP_ENVIRONMENT]
4172
+ args: [ENVIRONMENT_CONFIG]
4096
4173
  }] }] });
4097
4174
 
4098
- /**
4099
- * Uygulamanın environment altyapısını kurar.
4100
- *
4101
- * @usage
4102
- * providers: [
4103
- * provideNettyEnvironment()
4104
- * // Not: { provide: NETTY_APP_ENVIRONMENT, useValue: environment } dışarıdan verilmelidir.
4105
- * ]
4106
- */
4107
- function provideNtyEnvironment() {
4108
- return makeEnvironmentProviders([
4109
- // 1. EnvironmentService'in kendisi (providedIn: 'root' varsa buraya gerek yok ama zararı da yok)
4110
- NtyEnvironmentService,
4111
- // 2. ENVIRONMENT_CONFIG provider'ı
4112
- {
4113
- provide: ENVIRONMENT_CONFIG,
4114
- useFactory: ntyEnvironmentConfigFactory,
4115
- deps: [NtyEnvironmentService],
4116
- },
4117
- // 3. APP_INITIALIZER (Uygulama başlamadan önce env yüklemesi)
4118
- provideAppInitializer(() => {
4119
- const initializerFn = ntyInitializeEnvironment(inject(NtyEnvironmentService));
4120
- return initializerFn();
4121
- }),
4122
- ]);
4123
- }
4124
-
4125
4175
  class NtyLoadingService {
4126
4176
  requestCount = 0;
4127
4177
  isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
@@ -4158,7 +4208,7 @@ class NtyLoadingComponent {
4158
4208
  loadingService = inject(NtyLoadingService);
4159
4209
  isLoading = this.loadingService.isLoading;
4160
4210
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtyLoadingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4161
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: NtyLoadingComponent, isStandalone: true, selector: "app-nty-loading", host: { attributes: { "ntybase-id": "NtyLoadingComponent" } }, ngImport: i0, template: "@if (isLoading()) {\n<div class=\"loading-overlay\" (click)=\"$event.stopPropagation(); $event.preventDefault()\">\n <div class=\"spinner\">\n <i class=\"fas fa-spinner\"></i>\n </div>\n <div style=\"margin-top: 10px;\">{{'@loading' | translate}}</div>\n</div>\n}", styles: [".loading-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;z-index:2147483647;display:flex;justify-content:center;align-items:center;color:#fff;flex-direction:column;pointer-events:all;cursor:wait;-webkit-user-select:none;user-select:none}.spinner{font-size:3rem}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.fa-spinner{animation:spin 1s linear infinite}\n"], dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }] });
4211
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: NtyLoadingComponent, isStandalone: true, selector: "app-nty-loading", host: { attributes: { "ntybase-id": "NtyLoadingComponent" } }, ngImport: i0, template: "@if (isLoading()) {\n<div class=\"loading-overlay\" (click)=\"$event.stopPropagation(); $event.preventDefault()\">\n <div class=\"spinner\">\n <i class=\"fas fa-spinner\"></i>\n </div>\n <div style=\"margin-top: 10px;\">{{'@loading' | translate}}</div>\n</div>\n}", styles: [".loading-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;z-index:2147483647;display:flex;justify-content:center;align-items:center;color:#fff;flex-direction:column;pointer-events:all;cursor:wait;-webkit-user-select:none;user-select:none}.spinner{font-size:3rem}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.fa-spinner{animation:spin 1s linear infinite}\n"], dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
4162
4212
  }
4163
4213
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtyLoadingComponent, decorators: [{
4164
4214
  type: Component,
@@ -4214,5 +4264,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
4214
4264
  * Generated bundle index. Do not edit.
4215
4265
  */
4216
4266
 
4217
- export { AlertService, AuthenticationGuard, AuthenticationInterceptor, AuthenticationService, ButtonRenderer, CanDeactivateGuard, CheckboxRenderer, CommonService, ConfirmDialog, CredentialsService, CurrentUserPreference, ENVIRONMENT_CONFIG, EnvironmentInfo, EnvironmentInfoService, ExcelImportBase, ForgotPassword, Login, LoginDto, MFACodeDto, MfaLogin, NETTY_APP_ENVIRONMENT, NettyAgGridBase, NettyAgGridSaveBase, NettyAgGridService, NettyAppsBase, NettyBaseApp, NettyHelper, NettyImageService, NettyMenuService, NtyEnvironmentService, NtyLoadingComponent, NtyLoadingInterceptor, Ntybase, NtybaseModule, RangeDateTimeFilter, RangeNumberFilter, RangeStringFilter, UrlHelperService, ntyAuthenticationInterceptor, ntyEnvironmentConfigFactory, ntyInitializeEnvironment, provideNtyEnvironment };
4267
+ export { AlertService, AuthenticationGuard, AuthenticationInterceptor, AuthenticationService, ButtonRenderer, CanDeactivateGuard, CheckboxRenderer, CommonService, ConfirmDialog, CredentialsService, CurrentUserPreference, ENVIRONMENT_CONFIG, EnvironmentInfo, EnvironmentInfoService, ExcelImportBase, ForgotPassword, Login, LoginDto, MFACodeDto, MfaLogin, NettyAgGridListBase, NettyAgGridLogBase, NettyAgGridSaveBase, NettyAgGridService, NettyAppsBase, NettyBaseApp, NettyHelper, NettyImageService, NettyMenuService, NtyLoadingComponent, NtyLoadingInterceptor, Ntybase, NtybaseModule, RangeDateTimeFilter, RangeNumberFilter, RangeStringFilter, UrlHelperService, ntyAuthenticationInterceptor };
4218
4268
  //# sourceMappingURL=nettyapps-ntybase.mjs.map