@nettyapps/ntybase 21.1.24 → 21.1.26

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.
@@ -21,9 +21,9 @@ import * as i1$1 from '@ngx-translate/core';
21
21
  import { TranslateModule, TranslateService } from '@ngx-translate/core';
22
22
  import { Title } from '@angular/platform-browser';
23
23
  import { Mutex } from 'async-mutex';
24
- import { themeQuartz, StatusBarModule, ClipboardModule, ExcelExportModule, ColumnMenuModule, ContextMenuModule, CellSelectionModule, RowSelectionModule } from 'ag-grid-enterprise';
24
+ import { themeQuartz, StatusBarModule, ClipboardModule, ExcelExportModule, ColumnMenuModule, ContextMenuModule, CellSelectionModule, RowSelectionModule, SetFilterModule, MultiFilterModule } from 'ag-grid-enterprise';
25
25
  import { toSignal } from '@angular/core/rxjs-interop';
26
- import { ModuleRegistry, AllCommunityModule, ClientSideRowModelModule, HighlightChangesModule } from 'ag-grid-community';
26
+ import { ModuleRegistry, AllCommunityModule, ClientSideRowModelModule, HighlightChangesModule, TextFilterModule, NumberFilterModule, DateFilterModule } from 'ag-grid-community';
27
27
  import * as i2$2 from '@angular/material/tooltip';
28
28
  import { MatTooltipModule } from '@angular/material/tooltip';
29
29
  import * as i2$3 from '@angular/material/menu';
@@ -319,13 +319,7 @@ class ConfirmDialog {
319
319
  }
320
320
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ConfirmDialog, decorators: [{
321
321
  type: Component,
322
- args: [{ selector: 'ntybase-confirm-dialog', imports: [
323
- MatDialogModule,
324
- MatSnackBarModule,
325
- MatIconModule,
326
- MatDividerModule,
327
- TranslateModule,
328
- ], 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 | translate}}</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 | translate}}</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"] }]
322
+ args: [{ selector: 'ntybase-confirm-dialog', imports: [MatDialogModule, MatSnackBarModule, MatIconModule, MatDividerModule, TranslateModule], 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 | translate}}</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 | translate}}</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"] }]
329
323
  }] });
330
324
 
331
325
  class ErrorAlert {
@@ -510,7 +504,7 @@ class NettyAppsBase {
510
504
  }
511
505
  // Check if header is present
512
506
  if (!base64Data.startsWith('data:')) {
513
- console.error('Provided data is not in base64 format (missing header)');
507
+ this.alertService.showError('Provided data is not in base64 format (missing header)');
514
508
  return;
515
509
  }
516
510
  const contentType = base64Data.split(';')[0].split(':')[1];
@@ -1935,7 +1929,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
1935
1929
  }] });
1936
1930
 
1937
1931
  ModuleRegistry.registerModules([AllCommunityModule, StatusBarModule, ClientSideRowModelModule, ClipboardModule, ExcelExportModule, ColumnMenuModule,
1938
- ContextMenuModule, CellSelectionModule, HighlightChangesModule, RowSelectionModule,]);
1932
+ ContextMenuModule, CellSelectionModule, HighlightChangesModule, RowSelectionModule, SetFilterModule, MultiFilterModule, TextFilterModule, NumberFilterModule, DateFilterModule]);
1939
1933
  // AgGrid Dark Mode Row Style
1940
1934
  class NettyAgGridListBase extends NettyAgGridBase {
1941
1935
  // ********************************************
@@ -2593,7 +2587,7 @@ class NettyAgGridSaveBase extends NettyAppsBase {
2593
2587
  this.closeSidenav();
2594
2588
  this.alertService.showSuccess('@recordCreatedSuccessfully');
2595
2589
  },
2596
- error: (err) => console.error('@creationFailed:', err),
2590
+ error: (err) => this.alertService.showError('@creationFailed:', err),
2597
2591
  });
2598
2592
  }
2599
2593
  /**
@@ -2622,7 +2616,7 @@ class NettyAgGridSaveBase extends NettyAppsBase {
2622
2616
  let newRecord = this.createNewRecord();
2623
2617
  newRecord = await lastValueFrom(this.nettyAppsProxy.initRecord(newRecord))
2624
2618
  .catch((er) => {
2625
- console.error('@initRecordFailed:', er);
2619
+ this.alertService.showError('@initRecordFailed:', er);
2626
2620
  return this.createNewRecord();
2627
2621
  });
2628
2622
  this.initializeFormData(newRecord);
@@ -3864,7 +3858,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
3864
3858
  }] });
3865
3859
 
3866
3860
  class AuthBase {
3867
- // Inject dependencies
3861
+ // Services
3868
3862
  router = inject(Router);
3869
3863
  route = inject(ActivatedRoute);
3870
3864
  environmentProxy = inject(EnvironmentProxy);
@@ -3873,8 +3867,6 @@ class AuthBase {
3873
3867
  urlHelperService = inject(UrlHelperService);
3874
3868
  onDestroy$ = new Subject();
3875
3869
  ngOnDestroy() {
3876
- //Called once, before the instance is destroyed.
3877
- //Add 'implements OnDestroy' to the class.
3878
3870
  this.onDestroy$.next();
3879
3871
  this.onDestroy$.complete();
3880
3872
  }
@@ -3980,7 +3972,7 @@ class Login extends AuthBase {
3980
3972
  }
3981
3973
  }
3982
3974
  catch (error) {
3983
- console.error('Error handling remember me:', error);
3975
+ this.alertService.showError('Error handling remember me:', error);
3984
3976
  }
3985
3977
  }
3986
3978
  loadRememberedUsername() {
@@ -3995,7 +3987,7 @@ class Login extends AuthBase {
3995
3987
  }
3996
3988
  }
3997
3989
  catch (error) {
3998
- console.error('Error loading remembered username:', error);
3990
+ this.alertService.showError('Error loading remembered username:', error);
3999
3991
  }
4000
3992
  }
4001
3993
  login() {
@@ -4340,15 +4332,7 @@ class ForgotPassword extends AuthBase {
4340
4332
  }
4341
4333
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ForgotPassword, decorators: [{
4342
4334
  type: Component,
4343
- args: [{ selector: 'ntybase-forgot-password', imports: [
4344
- FormsModule,
4345
- ReactiveFormsModule,
4346
- MatMenuModule,
4347
- MatIconModule,
4348
- MatInputModule,
4349
- MatFormFieldModule,
4350
- TranslateModule
4351
- ], 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"] }]
4335
+ args: [{ selector: 'ntybase-forgot-password', imports: [FormsModule, ReactiveFormsModule, MatMenuModule, MatIconModule, MatInputModule, MatFormFieldModule, TranslateModule], 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"] }]
4352
4336
  }], ctorParameters: () => [] });
4353
4337
 
4354
4338
  // text-image.service.ts
@@ -4407,6 +4391,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
4407
4391
 
4408
4392
  class NettyBaseApp {
4409
4393
  i18nService = inject(I18nService);
4394
+ alertService = inject(AlertService);
4410
4395
  async loadBaseTranslations() {
4411
4396
  try {
4412
4397
  const enUSBase = await import('./nettyapps-ntybase-en-USbase-DV4K7MNJ.mjs');
@@ -4415,7 +4400,7 @@ class NettyBaseApp {
4415
4400
  this.i18nService.addTranslations('Türkçe', trTRBase.default);
4416
4401
  }
4417
4402
  catch (error) {
4418
- console.error('Error loading base translations in component:', error);
4403
+ this.alertService.showError('Error loading base translations in component:', error);
4419
4404
  throw error;
4420
4405
  }
4421
4406
  }
@@ -4561,6 +4546,7 @@ class NettyMenuService {
4561
4546
  http = inject(HttpClient);
4562
4547
  environmentProxy = inject(EnvironmentProxy);
4563
4548
  i18nService = inject(I18nService);
4549
+ alertService = inject(AlertService);
4564
4550
  menuName = signal('', ...(ngDevMode ? [{ debugName: "menuName" }] : []));
4565
4551
  menu = signal(null, ...(ngDevMode ? [{ debugName: "menu" }] : []));
4566
4552
  setMenuName(name) {
@@ -4582,7 +4568,7 @@ class NettyMenuService {
4582
4568
  this.http.get(functionUrl).subscribe({
4583
4569
  next: (data) => this.menu.set(data),
4584
4570
  error: (err) => {
4585
- console.error('Failed to fetch menu:', err);
4571
+ this.alertService.showError('Failed to fetch menu:', err);
4586
4572
  this.menu.set(null);
4587
4573
  },
4588
4574
  });