@skysoftware-co/bayan-core-widgets-ui 0.0.6 → 0.0.9

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.
Files changed (47) hide show
  1. package/README.md +183 -0
  2. package/fesm2022/skysoftware-co-bayan-core-widgets-ui.mjs +1232 -0
  3. package/fesm2022/skysoftware-co-bayan-core-widgets-ui.mjs.map +1 -0
  4. package/index.d.ts +5 -0
  5. package/lib/shared/common-methods/navigation.utils.d.ts +3 -0
  6. package/lib/shared/menu.dtos.d.ts +90 -0
  7. package/lib/shared/menu.service.d.ts +23 -0
  8. package/lib/top-menu-widget/components/about-dialog-widget/about-dialog-widget.component.d.ts +36 -0
  9. package/lib/top-menu-widget/components/change-password-widget/change-password-widget.component.d.ts +33 -0
  10. package/lib/top-menu-widget/components/global-search-widget/global-search-widget.component.d.ts +58 -0
  11. package/lib/top-menu-widget/components/item-widget/item-widget.component.d.ts +28 -0
  12. package/lib/top-menu-widget/components/notifications-widget/notifications-widget.component.d.ts +22 -0
  13. package/lib/top-menu-widget/components/settings-widget/settings-widget.component.d.ts +73 -0
  14. package/lib/top-menu-widget/components/user-panel-widget/user-panel-widget.component.d.ts +42 -0
  15. package/lib/top-menu-widget/top-menu-widget.component.d.ts +57 -0
  16. package/lib/top-menu-widget/top-menu-widget.models.d.ts +24 -0
  17. package/package.json +48 -36
  18. package/public-api.d.ts +10 -0
  19. package/ng-package.json +0 -7
  20. package/src/assets/i18n/ar.json +0 -725
  21. package/src/assets/i18n/en.json +0 -683
  22. package/src/assets/i18n/fr.json +0 -687
  23. package/src/lib/shared/common-methods/navigation.utils.ts +0 -21
  24. package/src/lib/shared/menu.dtos.ts +0 -107
  25. package/src/lib/shared/menu.service.ts +0 -157
  26. package/src/lib/top-menu-widget/components/about-dialog-widget/about-dialog-widget.component.html +0 -37
  27. package/src/lib/top-menu-widget/components/about-dialog-widget/about-dialog-widget.component.ts +0 -68
  28. package/src/lib/top-menu-widget/components/change-password-widget/change-password-widget.component.html +0 -56
  29. package/src/lib/top-menu-widget/components/change-password-widget/change-password-widget.component.ts +0 -158
  30. package/src/lib/top-menu-widget/components/global-search-widget/global-search-widget.component.html +0 -39
  31. package/src/lib/top-menu-widget/components/global-search-widget/global-search-widget.component.ts +0 -153
  32. package/src/lib/top-menu-widget/components/item-widget/item-widget.component.html +0 -39
  33. package/src/lib/top-menu-widget/components/item-widget/item-widget.component.ts +0 -95
  34. package/src/lib/top-menu-widget/components/notifications-widget/notifications-widget.component.html +0 -10
  35. package/src/lib/top-menu-widget/components/notifications-widget/notifications-widget.component.ts +0 -89
  36. package/src/lib/top-menu-widget/components/settings-widget/settings-widget.component.html +0 -119
  37. package/src/lib/top-menu-widget/components/settings-widget/settings-widget.component.ts +0 -233
  38. package/src/lib/top-menu-widget/components/user-panel-widget/user-panel-widget.component.html +0 -53
  39. package/src/lib/top-menu-widget/components/user-panel-widget/user-panel-widget.component.ts +0 -140
  40. package/src/lib/top-menu-widget/top-menu-widget.component.html +0 -103
  41. package/src/lib/top-menu-widget/top-menu-widget.component.ts +0 -148
  42. package/src/lib/top-menu-widget/top-menu-widget.models.ts +0 -29
  43. package/src/lib/top-menu-widget/top-menu-widget.styles.css +0 -576
  44. package/src/public-api.ts +0 -7
  45. package/tsconfig.lib.json +0 -16
  46. package/tsconfig.lib.prod.json +0 -9
  47. package/tsconfig.spec.json +0 -13
@@ -1,21 +0,0 @@
1
- export function resolveUrl(baseUrl: string | null | undefined, url: string | null | undefined): string | null {
2
- if (!url) {
3
- return null;
4
- }
5
-
6
- return baseUrl ? joinUrl(baseUrl, url) : url;
7
- }
8
-
9
- export function isExternalNavigation(baseUrl: string | null | undefined, url: string): boolean {
10
- return isAbsoluteUrl(url) || (!!baseUrl && isAbsoluteUrl(baseUrl));
11
- }
12
-
13
- export function joinUrl(baseUrl: string, url: string): string {
14
- const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
15
- const normalizedUrl = url.startsWith('/') ? url : `/${url}`;
16
- return `${normalizedBaseUrl}${normalizedUrl}`;
17
- }
18
-
19
- function isAbsoluteUrl(url: string): boolean {
20
- return /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i.test(url);
21
- }
@@ -1,107 +0,0 @@
1
- export interface ApiEnvelope<T> {
2
- ResponseData: T;
3
- ApiVersion: number;
4
- }
5
-
6
- export interface TopMenuShortcut {
7
- MenuName: string;
8
- MenuUrl: string | null;
9
- Children: TopMenuShortcut[];
10
- }
11
-
12
- export interface SystemMenu {
13
- MenuName: string;
14
- MenuUrl: string | null;
15
- IconClass: string | null;
16
- Expanded: boolean;
17
- Children: SystemMenu[];
18
- }
19
-
20
- export interface GlobalSearchMenu {
21
- MenuTitle: string;
22
- MenuSubTitle: string;
23
- IconClass: string;
24
- MenuUrl: string;
25
- IsTranslatable: boolean;
26
- }
27
-
28
- export interface PropertyOption {
29
- PropertyId: number;
30
- PropertyName: string;
31
- }
32
-
33
- export interface UserPanel {
34
- UserDisplayName: string;
35
- ActivePropertyId: number;
36
- ActivePropertyName: string;
37
- PhotoPath: string | null;
38
- NameInitials: string;
39
- IsSSOLogin: boolean;
40
- Properties: PropertyOption[];
41
- }
42
-
43
- export interface SwitchPropertyRequest {
44
- PropertyId: number;
45
- }
46
-
47
- export interface SwitchPropertyResult {
48
- PropertyId: number;
49
- }
50
-
51
- export enum EmployeeNamesModeOption {
52
- ShortNames = 1,
53
- StandardNames = 2,
54
- FullNames = 3,
55
- }
56
-
57
- export interface AppFramePreferences {
58
- UseAlternateNames: boolean;
59
- DisplayAlternateNames: boolean;
60
- EmployeeNamesMode: EmployeeNamesModeOption;
61
- VersionNumber: string;
62
- }
63
-
64
- export interface SetDisplayAlternateNamesRequest {
65
- DisplayAlternateNames: boolean;
66
- }
67
-
68
- export interface SetEmployeeNamesModeRequest {
69
- EmployeeNamesMode: EmployeeNamesModeOption;
70
- }
71
-
72
- export enum BlockableModule {
73
- HumanResources = 4,
74
- Timekeeping = 5,
75
- }
76
-
77
- export interface ModuleBlockState {
78
- IsBlocked: boolean;
79
- UserCanBlockModule: boolean;
80
- }
81
-
82
- export interface BlockReleaseModuleRequest {
83
- Module: BlockableModule;
84
- }
85
-
86
- export interface NotificationsSummary {
87
- TotalNotificationsCount: number;
88
- NotificationsUrl: string;
89
- }
90
-
91
- export interface ChangePasswordRequest {
92
- CurrentPassword: string;
93
- NewPassword: string;
94
- }
95
-
96
- export enum SystemModule {
97
- Corporate = 1,
98
- Cluster = 2,
99
- Setup = 3,
100
- HumanResources = 4,
101
- Timekeeping = 5,
102
- Payroll = 6,
103
- Training = 7,
104
- Workflow = 8,
105
- Appraisal = 9,
106
- BusinessIntelligence = 10,
107
- }
@@ -1,157 +0,0 @@
1
- import { HttpClient, HttpParams } from '@angular/common/http';
2
- import { Injectable, inject } from '@angular/core';
3
- import { catchError, map, Observable, throwError } from 'rxjs';
4
- import {
5
- ApiEnvelope,
6
- AppFramePreferences,
7
- BlockableModule,
8
- BlockReleaseModuleRequest,
9
- ChangePasswordRequest,
10
- GlobalSearchMenu,
11
- ModuleBlockState,
12
- NotificationsSummary,
13
- SetDisplayAlternateNamesRequest,
14
- SetEmployeeNamesModeRequest,
15
- SwitchPropertyRequest,
16
- SwitchPropertyResult,
17
- SystemMenu,
18
- SystemModule,
19
- TopMenuShortcut,
20
- UserPanel,
21
- } from './menu.dtos';
22
-
23
- @Injectable({
24
- providedIn: 'root',
25
- })
26
- export class BayanCoreTopMenuService {
27
- private readonly http = inject(HttpClient);
28
-
29
- private unwrap<T>(obs: Observable<ApiEnvelope<T>>): Observable<T> {
30
- return obs.pipe(
31
- map((env) => {
32
- if (!env.ResponseData) {
33
- throw new Error('No data received');
34
- }
35
-
36
- return env.ResponseData;
37
- }),
38
- catchError((error) => throwError(() => error)),
39
- );
40
- }
41
-
42
- private getBaseUrl(baseUrl: string): string {
43
- let url = baseUrl.replace('/api','');
44
- return `${url.replace(/\/$/, '')}/api/app-frame`;
45
- }
46
-
47
- getMicroserviceMenusByProperty(
48
- baseUrl: string,
49
- propertyId: number | string,
50
- systemModule: SystemModule,
51
- ): Observable<SystemMenu[]> {
52
- const params = new HttpParams()
53
- .set('PropertyId', propertyId)
54
- .set('SystemModule', systemModule);
55
-
56
- return this.unwrap(
57
- this.http.get<ApiEnvelope<SystemMenu[]>>(`${this.getBaseUrl(baseUrl)}/left-menu`, { params }),
58
- );
59
- }
60
-
61
- getMicroserviceTopMenusShortcut(
62
- baseUrl: string,
63
- propertyId: number | string,
64
- systemModule: SystemModule,
65
- ): Observable<TopMenuShortcut[]> {
66
- const params = new HttpParams()
67
- .set('PropertyId', propertyId)
68
- .set('SystemModule', systemModule);
69
-
70
- return this.unwrap(
71
- this.http.get<ApiEnvelope<TopMenuShortcut[]>>(`${this.getBaseUrl(baseUrl)}/top-shortcuts`, {
72
- params,
73
- }),
74
- );
75
- }
76
-
77
- getGlobalSearchMenus(baseUrl: string, propertyId?: number): Observable<GlobalSearchMenu[]> {
78
- let params = new HttpParams();
79
-
80
- if (propertyId != null) {
81
- params = params.set('PropertyId', propertyId);
82
- }
83
-
84
- return this.unwrap(
85
- this.http.get<ApiEnvelope<GlobalSearchMenu[]>>(
86
- `${this.getBaseUrl(baseUrl)}/global-search-menu`,
87
- { params },
88
- ),
89
- );
90
- }
91
-
92
- getUserPanel(baseUrl: string): Observable<UserPanel> {
93
- return this.unwrap(this.http.get<ApiEnvelope<UserPanel>>(`${this.getBaseUrl(baseUrl)}/user-panel`));
94
- }
95
-
96
- switchProperty(baseUrl: string, request: SwitchPropertyRequest): Observable<SwitchPropertyResult> {
97
- return this.unwrap(
98
- this.http.post<ApiEnvelope<SwitchPropertyResult>>(
99
- `${this.getBaseUrl(baseUrl)}/switch-property`,
100
- request,
101
- ),
102
- );
103
- }
104
-
105
- getPreferences(baseUrl: string): Observable<AppFramePreferences> {
106
- return this.unwrap(
107
- this.http.get<ApiEnvelope<AppFramePreferences>>(`${this.getBaseUrl(baseUrl)}/preferences`),
108
- );
109
- }
110
-
111
- setDisplayAlternateNames(
112
- baseUrl: string,
113
- request: SetDisplayAlternateNamesRequest,
114
- ): Observable<void> {
115
- return this.http.post<void>(`${this.getBaseUrl(baseUrl)}/preferences/alternate-names`, request);
116
- }
117
-
118
- setEmployeeNamesMode(baseUrl: string, request: SetEmployeeNamesModeRequest): Observable<void> {
119
- return this.http.post<void>(
120
- `${this.getBaseUrl(baseUrl)}/preferences/employee-names-mode`,
121
- request,
122
- );
123
- }
124
-
125
- getModuleBlockState(
126
- baseUrl: string,
127
- systemModule: SystemModule | BlockableModule,
128
- ): Observable<ModuleBlockState> {
129
- const params = new HttpParams().set('SystemModule', systemModule);
130
-
131
- return this.unwrap(
132
- this.http.get<ApiEnvelope<ModuleBlockState>>(`${this.getBaseUrl(baseUrl)}/module-block-state`, {
133
- params,
134
- }),
135
- );
136
- }
137
-
138
- blockModule(baseUrl: string, request: BlockReleaseModuleRequest): Observable<void> {
139
- return this.http.post<void>(`${this.getBaseUrl(baseUrl)}/block-module`, request);
140
- }
141
-
142
- releaseModule(baseUrl: string, request: BlockReleaseModuleRequest): Observable<void> {
143
- return this.http.post<void>(`${this.getBaseUrl(baseUrl)}/release-module`, request);
144
- }
145
-
146
- getNotificationsSummary(baseUrl: string): Observable<NotificationsSummary> {
147
- return this.unwrap(
148
- this.http.get<ApiEnvelope<NotificationsSummary>>(
149
- `${this.getBaseUrl(baseUrl)}/notifications-summary`,
150
- ),
151
- );
152
- }
153
-
154
- changePassword(baseUrl: string, request: ChangePasswordRequest): Observable<boolean> {
155
- return this.http.post<boolean>(`${this.getBaseUrl(baseUrl)}/change-password`, request);
156
- }
157
- }
@@ -1,37 +0,0 @@
1
- @if (visible) {
2
- <div [class]="backdropClass" (click)="onBackdropClick($event)">
3
- <div [class]="modalClass" role="dialog" aria-labelledby="topMenuAboutDialogTitle" aria-modal="true">
4
- <div [class]="headerClass">
5
- <h4 [class]="titleClass" id="topMenuAboutDialogTitle">{{ config.title || 'AboutSkyBayan' | translate }}</h4>
6
- <button type="button" [class]="closeBtnClass" (click)="closeDialog()" [attr.aria-label]="(config.closeButtonLabel || 'Close') | translate">
7
- <span aria-hidden="true">&times;</span>
8
- </button>
9
- </div>
10
-
11
- <div [class]="bodyClass">
12
- <div class="row align-items-start">
13
- <div class="col-4">
14
- @if (config.logoUrl) {
15
- <img [src]="config.logoUrl" alt="Logo" [class]="logoClass">
16
- }
17
- </div>
18
- <div class="col-8">
19
- <h3 [class]="productNameClass">{{ (config.title || 'AboutSkyBayan') | translate }}</h3>
20
- <p [class]="versionTextClass">{{ (config.versionLabel || 'Version') | translate }} {{ config.version || '' }}</p>
21
- <p [class]="upToDateClass">
22
- <fa-icon [icon]="checkCircleIcon" class="text-info me-1"></fa-icon>
23
- <small class="text-muted">{{ (config.statusLabel || 'SkyBayanUpToDate') | translate }}</small>
24
- </p>
25
- <p [class]="copyrightClass">{{ (config.copyright || '') | translate }}</p>
26
- </div>
27
- </div>
28
- </div>
29
-
30
- <div [class]="actionsClass">
31
- <button type="button" [class]="actionBtnClass" (click)="openLicense()">{{ (config.licenseButtonLabel || 'LicenseInformation') | translate }}</button>
32
- <button type="button" [class]="actionBtnClass" (click)="openReleaseNotes()">{{ (config.releaseNotesButtonLabel || 'ReleaseNotes') | translate }}</button>
33
- <button type="button" [class]="actionBtnClass" (click)="openSupport()">{{ (config.supportButtonLabel || 'TechnicalSupport') | translate }}</button>
34
- </div>
35
- </div>
36
- </div>
37
- }
@@ -1,68 +0,0 @@
1
- import { CommonModule } from '@angular/common';
2
- import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
3
- import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
4
- import { faCheckCircle } from '@fortawesome/pro-solid-svg-icons';
5
- import { TranslatePipe } from '@skysoftware-co/sky-components-ui';
6
- import { TopMenuWidgetAboutDialogConfig } from '../../top-menu-widget.models';
7
-
8
- @Component({
9
- selector: 'bayan-core-about-dialog-widget',
10
- standalone: true,
11
- imports: [CommonModule, FontAwesomeModule, TranslatePipe],
12
- templateUrl: './about-dialog-widget.component.html',
13
- styleUrls: ['../../top-menu-widget.styles.css'],
14
- changeDetection: ChangeDetectionStrategy.OnPush,
15
- })
16
- export class BayanCoreAboutDialogWidgetComponent {
17
-
18
- @Input() baseUrl = '';
19
- @Input() visible = false;
20
- @Input({ required: true }) config!: TopMenuWidgetAboutDialogConfig;
21
- @Input() licenseUrl = '';
22
- @Input() releaseNotesUrl = '';
23
- @Input() supportUrl = 'https://skyits.com/contact';
24
-
25
- // CSS class attributes as @Input with defaults
26
- @Input() backdropClass: string = 'about-backdrop';
27
- @Input() modalClass: string = 'about-modal';
28
- @Input() headerClass: string = 'about-modal-header';
29
- @Input() titleClass: string = 'about-modal-title';
30
- @Input() closeBtnClass: string = 'about-close-btn';
31
- @Input() bodyClass: string = 'about-modal-body';
32
- @Input() logoClass: string = 'img-fluid about-logo';
33
- @Input() productNameClass: string = 'about-product-name';
34
- @Input() versionTextClass: string = 'about-version-text mb-1';
35
- @Input() upToDateClass: string = 'about-up-to-date mb-2';
36
- @Input() copyrightClass: string = 'about-copyright mb-0';
37
- @Input() actionsClass: string = 'about-modal-actions';
38
- @Input() actionBtnClass: string = 'about-action-btn';
39
-
40
- @Output() visibleChange = new EventEmitter<boolean>();
41
- @Output() licenseClick = new EventEmitter<void>();
42
- @Output() releaseNotesClick = new EventEmitter<void>();
43
- @Output() supportClick = new EventEmitter<void>();
44
-
45
- readonly checkCircleIcon = faCheckCircle;
46
-
47
- onBackdropClick(event: MouseEvent): void {
48
- if ((event.target as HTMLElement).classList.contains('about-backdrop')) {
49
- this.closeDialog();
50
- }
51
- }
52
-
53
- closeDialog(): void {
54
- this.visibleChange.emit(false);
55
- }
56
-
57
- openLicense() {
58
- window.open(this.licenseUrl, '_blank');
59
- }
60
-
61
- openReleaseNotes() {
62
- window.open(this.releaseNotesUrl, '_blank');
63
- }
64
-
65
- openSupport() {
66
- window.open(this.supportUrl, '_blank');
67
- }
68
- }
@@ -1,56 +0,0 @@
1
- <dx-popup
2
- [visible]="visible"
3
- (onHiding)="closeDialog()"
4
- [title]="config.title | translate"
5
- [showCloseButton]="true"
6
- [width]="450"
7
- [height]="'auto'"
8
- [dragEnabled]="false"
9
- [shading]="true"
10
- shadingColor="rgba(0,0,0,0.4)">
11
- <div *dxTemplate="let data of 'content'">
12
- <dx-form
13
- #changePasswordForm
14
- [formData]="formData"
15
- labelLocation="top"
16
- [showColonAfterLabel]="false"
17
- class="mb-3 mx-2">
18
- <dxi-item
19
- dataField="currentPassword"
20
- editorType="dxTextBox"
21
- [editorOptions]="getCurrentPasswordEditorOptions()">
22
- <dxo-label [text]="config.currentPasswordLabel | translate"></dxo-label>
23
- <dxi-validation-rule type="required"></dxi-validation-rule>
24
- </dxi-item>
25
-
26
- <dxi-item
27
- dataField="newPassword"
28
- editorType="dxTextBox"
29
- [editorOptions]="getNewPasswordEditorOptions()">
30
- <dxo-label [text]="config.newPasswordLabel | translate"></dxo-label>
31
- <dxi-validation-rule type="required"></dxi-validation-rule>
32
- </dxi-item>
33
-
34
- <dxi-item
35
- dataField="confirmNewPassword"
36
- editorType="dxTextBox"
37
- [editorOptions]="getConfirmPasswordEditorOptions()">
38
- <dxo-label [text]="config.confirmNewPasswordLabel | translate"></dxo-label>
39
- <dxi-validation-rule type="required"></dxi-validation-rule>
40
- <dxi-validation-rule
41
- type="compare"
42
- [comparisonTarget]="passwordComparison">
43
- </dxi-validation-rule>
44
- </dxi-item>
45
- </dx-form>
46
-
47
- <sky-footer-actions
48
- [primaryButtonText]="config.primaryButtonText | translate"
49
- [showSecondaryButton]="false"
50
- [isLoading]="isSubmitting"
51
- [disabledPrimaryButton]="isSubmitting || !isChangePasswordValid()"
52
- (PrimaryButtonClick)="onSaveButtonClick()"
53
- [errorMessage]="errorMessage">
54
- </sky-footer-actions>
55
- </div>
56
- </dx-popup>
@@ -1,158 +0,0 @@
1
- import { CommonModule } from '@angular/common';
2
- import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, ViewChild, signal, WritableSignal, inject } from '@angular/core';
3
- import { DxFormComponent, DxFormModule, DxPopupModule } from 'devextreme-angular';
4
- import { SkyFooterActionsComponent, TranslatePipe } from '@skysoftware-co/sky-components-ui';
5
- import {
6
- TopMenuWidgetChangePasswordDialogConfig,
7
- TopMenuWidgetChangePasswordPayload,
8
- } from '../../top-menu-widget.models';
9
- import { BayanCoreTopMenuService } from '../../../shared/menu.service';
10
- import { SkyAlertToastService } from '@skysoftware-co/sky-components-ui';
11
- // import { SkyAlertType } from '@skysoftware-co/sky-components-ui/lib/constants/constants';
12
-
13
-
14
- @Component({
15
- selector: 'bayan-core-change-password-widget',
16
- standalone: true,
17
- imports: [CommonModule, DxPopupModule, DxFormModule, SkyFooterActionsComponent, TranslatePipe],
18
- templateUrl: './change-password-widget.component.html',
19
- changeDetection: ChangeDetectionStrategy.OnPush,
20
- })
21
- export class BayanCoreChangePasswordWidgetComponent {
22
- private readonly menuService = inject(BayanCoreTopMenuService);
23
- private readonly alertToastService = inject(SkyAlertToastService);
24
- private readonly translate = inject(TranslatePipe);
25
-
26
- @Input() baseUrl = '';
27
- @Input() visible = false;
28
- @Input({ required: true }) config!: TopMenuWidgetChangePasswordDialogConfig;
29
- @Input() isSubmitting = false;
30
- @Output() visibleChange = new EventEmitter<boolean>();
31
-
32
- @ViewChild('changePasswordForm') changePasswordForm?: DxFormComponent;
33
-
34
- readonly currentPasswordMode = signal<'password' | 'text'>('password');
35
- readonly newPasswordMode = signal<'password' | 'text'>('password');
36
- readonly confirmNewPasswordMode = signal<'password' | 'text'>('password');
37
-
38
- formData: TopMenuWidgetChangePasswordPayload = {
39
- currentPassword: '',
40
- newPassword: '',
41
- confirmNewPassword: '',
42
- };
43
- errorMessage: WritableSignal<string> = signal('');
44
-
45
- closeDialog(): void {
46
- this.visible = false;
47
- this.visibleChange.emit(false);
48
- this.resetForm();
49
- this.errorMessage.set('');
50
- }
51
-
52
- resetForm(): void {
53
- this.formData = {
54
- currentPassword: '',
55
- newPassword: '',
56
- confirmNewPassword: '',
57
- };
58
- this.errorMessage.set('');
59
- }
60
-
61
- onSaveButtonClick(): void {
62
- const isValid = this.changePasswordForm?.instance.validate().isValid ?? false;
63
- if (!isValid) {
64
- return;
65
- }
66
- this.isSubmitting = true;
67
- this.menuService.changePassword(this.baseUrl, {
68
- CurrentPassword: this.formData.currentPassword,
69
- NewPassword: this.formData.newPassword
70
- }).subscribe({
71
- next: () => {
72
- this.isSubmitting = false;
73
- this.closeDialog();
74
- this.showAlert('PasswordChangedSuccessfully');
75
- },
76
- error: (e: any) => {
77
- this.isSubmitting = false;
78
- this.errorMessage.set(this.translate.transform("FailedToChangePassword"));
79
- // Optionally show error notification here
80
- }
81
- });
82
- }
83
- togglePasswordMode(field: 'currentPasswordMode' | 'newPasswordMode' | 'confirmNewPasswordMode'): void {
84
- const current = this[field]();
85
- this[field].set(current === 'text' ? 'password' : 'text');
86
- }
87
-
88
- updateField(field: keyof TopMenuWidgetChangePasswordPayload, value: string): void {
89
- this.formData = {
90
- ...this.formData,
91
- [field]: value,
92
- };
93
- }
94
-
95
- isChangePasswordValid(): boolean {
96
- return !!this.formData.currentPassword && !!this.formData.newPassword && !!this.formData.confirmNewPassword && this.formData.newPassword === this.formData.confirmNewPassword;
97
- }
98
-
99
- getCurrentPasswordEditorOptions(): object {
100
- return {
101
- maxLength: 256,
102
- disabled: this.isSubmitting,
103
- mode: this.currentPasswordMode(),
104
- onValueChanged: (event: { value?: string }) => this.updateField('currentPassword', event.value ?? ''),
105
- buttons: [{
106
- name: 'password',
107
- location: 'after',
108
- options: {
109
- stylingMode: 'text',
110
- icon: this.currentPasswordMode() === 'text' ? 'eyeopen' : 'eyeclose',
111
- onClick: () => this.togglePasswordMode('currentPasswordMode'),
112
- },
113
- }],
114
- };
115
- }
116
-
117
- getNewPasswordEditorOptions(): object {
118
- return {
119
- maxLength: 256,
120
- disabled: this.isSubmitting,
121
- mode: this.newPasswordMode(),
122
- onValueChanged: (event: { value?: string }) => this.updateField('newPassword', event.value ?? ''),
123
- buttons: [{
124
- name: 'password',
125
- location: 'after',
126
- options: {
127
- stylingMode: 'text',
128
- icon: this.newPasswordMode() === 'text' ? 'eyeopen' : 'eyeclose',
129
- onClick: () => this.togglePasswordMode('newPasswordMode'),
130
- },
131
- }],
132
- };
133
- }
134
-
135
- getConfirmPasswordEditorOptions(): object {
136
- return {
137
- maxLength: 256,
138
- disabled: this.isSubmitting,
139
- mode: this.confirmNewPasswordMode(),
140
- onValueChanged: (event: { value?: string }) => this.updateField('confirmNewPassword', event.value ?? ''),
141
- buttons: [{
142
- name: 'password',
143
- location: 'after',
144
- options: {
145
- stylingMode: 'text',
146
- icon: this.confirmNewPasswordMode() === 'text' ? 'eyeopen' : 'eyeclose',
147
- onClick: () => this.togglePasswordMode('confirmNewPasswordMode'),
148
- },
149
- }],
150
- };
151
- }
152
-
153
- passwordComparison = (): string => this.formData.newPassword;
154
-
155
- showAlert(message: string, type: string = 'success') {
156
- this.alertToastService.toastInformation(message, type as any);
157
- }
158
- }
@@ -1,39 +0,0 @@
1
- <div [class]="searchWrapperClass">
2
- <dx-autocomplete
3
- #searchAutoComplete
4
- [placeholder]="placeholder | translate"
5
- [dataSource]="dataSource"
6
- valueExpr="menuSubTitle"
7
- [searchExpr]="['menuSubTitle']"
8
- [showClearButton]="false"
9
- [showDropDownButton]="false"
10
- [searchMode]="searchMode"
11
- [width]="'100%'"
12
- [stylingMode]="stylingMode"
13
- [wrapItemText]="true"
14
- [searchTimeout]="100"
15
- (onInput)="onInput($event)"
16
- (onEnterKey)="onEnterKey($event)">
17
- <div class="w-100" *dxTemplate="let item of 'item'">
18
- <a
19
- [class]="searchItemClass"
20
- href="{{item.MenuUrl}}" >
21
- <div [class]="searchItemTitleClass">
22
- <fa-icon [icon]="getIconForClass(item.iconClass)" [class]="iconClass"></fa-icon>
23
- @if (item.isTranslatable) {
24
- {{ item.menuTitle | translate }}
25
- } @else {
26
- {{ item.menuTitle }}
27
- }
28
- </div>
29
- <div [class]="searchItemSubtitleClass">
30
- @if (item.isTranslatable) {
31
- {{ item.menuSubTitle | translate }}
32
- } @else {
33
- {{ item.menuSubTitle }}
34
- }
35
- </div>
36
- </a>
37
- </div>
38
- </dx-autocomplete>
39
- </div>