@flusys/ng-auth 9.1.0 → 9.1.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.
Files changed (37) hide show
  1. package/README.md +2 -0
  2. package/fesm2022/flusys-ng-auth-administration-page.component-DmN4KqiR.mjs +146 -0
  3. package/fesm2022/flusys-ng-auth-administration-page.component-DmN4KqiR.mjs.map +1 -0
  4. package/fesm2022/flusys-ng-auth-branch-form.component-Df_sMC2G.mjs +743 -0
  5. package/fesm2022/flusys-ng-auth-branch-form.component-Df_sMC2G.mjs.map +1 -0
  6. package/fesm2022/flusys-ng-auth-branch-list.component-CWat6QWN.mjs +775 -0
  7. package/fesm2022/flusys-ng-auth-branch-list.component-CWat6QWN.mjs.map +1 -0
  8. package/fesm2022/flusys-ng-auth-company-form.component-BvZ4Pn8j.mjs +198 -0
  9. package/fesm2022/flusys-ng-auth-company-form.component-BvZ4Pn8j.mjs.map +1 -0
  10. package/fesm2022/flusys-ng-auth-company-list.component-Corh9AIh.mjs +241 -0
  11. package/fesm2022/flusys-ng-auth-company-list.component-Corh9AIh.mjs.map +1 -0
  12. package/fesm2022/flusys-ng-auth-extension-order.util-2XWSLqii.mjs +6 -0
  13. package/fesm2022/flusys-ng-auth-extension-order.util-2XWSLqii.mjs.map +1 -0
  14. package/fesm2022/flusys-ng-auth-forgot-password-page.component-BRTVZPX6.mjs +384 -0
  15. package/fesm2022/flusys-ng-auth-forgot-password-page.component-BRTVZPX6.mjs.map +1 -0
  16. package/fesm2022/flusys-ng-auth-login-page.component-DQl52Qau.mjs +1074 -0
  17. package/fesm2022/flusys-ng-auth-login-page.component-DQl52Qau.mjs.map +1 -0
  18. package/fesm2022/flusys-ng-auth-profile-page.component-b-8rPEXQ.mjs +1792 -0
  19. package/fesm2022/flusys-ng-auth-profile-page.component-b-8rPEXQ.mjs.map +1 -0
  20. package/fesm2022/flusys-ng-auth-register-page.component-D99y1jiA.mjs +1513 -0
  21. package/fesm2022/flusys-ng-auth-register-page.component-D99y1jiA.mjs.map +1 -0
  22. package/fesm2022/flusys-ng-auth-reset-password-page.component-C0tN_AW1.mjs +538 -0
  23. package/fesm2022/flusys-ng-auth-reset-password-page.component-C0tN_AW1.mjs.map +1 -0
  24. package/fesm2022/flusys-ng-auth-social-callback-page.component-gTD7_LJY.mjs +217 -0
  25. package/fesm2022/flusys-ng-auth-social-callback-page.component-gTD7_LJY.mjs.map +1 -0
  26. package/fesm2022/flusys-ng-auth-social-config-page.component-DpGmcb9n.mjs +541 -0
  27. package/fesm2022/flusys-ng-auth-social-config-page.component-DpGmcb9n.mjs.map +1 -0
  28. package/fesm2022/flusys-ng-auth-user-form.component-CM9UYc0q.mjs +1171 -0
  29. package/fesm2022/flusys-ng-auth-user-form.component-CM9UYc0q.mjs.map +1 -0
  30. package/fesm2022/flusys-ng-auth-user-list.component-Bew7gz-H.mjs +1046 -0
  31. package/fesm2022/flusys-ng-auth-user-list.component-Bew7gz-H.mjs.map +1 -0
  32. package/fesm2022/flusys-ng-auth-verify-email-page.component-DB9iKvt3.mjs +545 -0
  33. package/fesm2022/flusys-ng-auth-verify-email-page.component-DB9iKvt3.mjs.map +1 -0
  34. package/fesm2022/flusys-ng-auth.mjs +3030 -10735
  35. package/fesm2022/flusys-ng-auth.mjs.map +1 -1
  36. package/package.json +5 -5
  37. package/types/flusys-ng-auth.d.ts +978 -1558
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flusys-ng-auth-profile-page.component-b-8rPEXQ.mjs","names":[],"sources":["../../../projects/ng-auth/pages/profile/profile-page.component.ts"],"sourcesContent":["import {\n Component,\n computed,\n DestroyRef,\n effect,\n inject,\n Injector,\n signal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { NgComponentOutlet, NgTemplateOutlet } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { form, FormField, required } from '@angular/forms/signals';\nimport {\n APP_CONFIG,\n getPermissionMode,\n isCompanyFeatureEnabled,\n isServiceEnabled,\n} from '@flusys/ng-core';\nimport {\n FILE_PROVIDER,\n FileUploaderComponent,\n FileUrlService,\n HasPermissionDirective,\n IProfileActionInfo,\n IProfileRoleInfo,\n PROFILE_PERMISSION_PROVIDER,\n TranslatePipe,\n TranslateService,\n} from '@flusys/ng-shared';\nimport {\n AvatarComponent,\n CheckboxComponent,\n FButtonDirective,\n InputTextDirective,\n MessageService,\n PasswordComponent,\n SelectComponent,\n SkeletonComponent,\n TagComponent,\n TextareaDirective,\n UiIconComponent,\n} from '@flusys/ng-ui';\nimport { catchError, finalize, forkJoin, of } from 'rxjs';\nimport { IUpdateUserRequest } from '../../interfaces/user.interface';\nimport {\n AUTH_PROFILE_EXTENSION,\n AUTH_USER_FORM_EXTENSION,\n IProfileExtraField,\n IProfileExtraSection,\n IProfileFieldTemplateContext,\n IUserFormExtraField,\n PROFILE_FIELD_CONTEXT,\n} from '../../providers/auth-extension.providers';\nimport { sortByOrder } from '../../providers/extension-order.util';\nimport { AuthApiService } from '../../services/auth-api.service';\nimport { AuthStateService } from '../../services/auth-state.service';\nimport { PasswordPolicyService } from '../../services/password-policy.service';\nimport { UserApiService } from '../../services/user-api.service';\n\ninterface IProfileFormModel {\n name: string;\n phone: string;\n}\n\ninterface IPasswordFormModel {\n currentPassword: string;\n newPassword: string;\n confirmPassword: string;\n}\n\n@Component({\n selector: 'lib-profile-page',\n imports: [\n AvatarComponent,\n CheckboxComponent,\n FButtonDirective,\n InputTextDirective,\n PasswordComponent,\n SelectComponent,\n SkeletonComponent,\n TagComponent,\n TextareaDirective,\n UiIconComponent,\n FormsModule,\n NgComponentOutlet,\n NgTemplateOutlet,\n FormField,\n FileUploaderComponent,\n HasPermissionDirective,\n TranslatePipe,\n ],\n template: `\n <div class=\"mb-4 md:mb-6\">\n <h1 class=\"text-2xl font-bold text-color mb-2\">\n {{ 'profile.title' | translate }}\n </h1>\n <p class=\"text-muted-color\">{{ 'profile.subtitle' | translate }}</p>\n </div>\n\n <div class=\"card mb-2 md:mb-4\">\n <div class=\"flex flex-col md:flex-row gap-4 md:gap-6\">\n <div\n class=\"flex flex-col items-center gap-4 md:w-72 lg:w-80 md:border-r md:border-surface md:pr-6\"\n >\n @if (profilePictureUrl()) {\n <f-avatar\n [image]=\"profilePictureUrl()!\"\n size=\"xlarge\"\n shape=\"circle\"\n styleClass=\"w-28 h-28\"\n />\n } @else {\n <f-avatar\n [label]=\"userInitials()\"\n size=\"xlarge\"\n shape=\"circle\"\n styleClass=\"w-28 h-28 text-3xl bg-primary text-primary-contrast\"\n />\n }\n <div class=\"text-center\">\n <div class=\"font-semibold text-color\">{{ userName() }}</div>\n <div class=\"text-muted-color text-sm\">{{ userEmail() }}</div>\n </div>\n @if (showUploadSection()) {\n <lib-file-uploader\n [acceptTypes]=\"['image/*']\"\n [multiple]=\"false\"\n [maxSizeMb]=\"5\"\n [showPreview]=\"false\"\n [uploadOptions]=\"profileUploadOptions\"\n (fileUploaded)=\"onProfilePictureUploaded($event)\"\n class=\"w-full\"\n />\n } @else {\n <div class=\"w-full p-3 bg-emphasis rounded-lg text-center\">\n <ui-icon\n name=\"info-circle\"\n class=\"text-muted-color mr-2\"\n ></ui-icon>\n <span class=\"text-sm text-muted-color\">{{\n 'profile.storage.not.enabled' | translate\n }}</span>\n </div>\n }\n </div>\n\n <div class=\"flex-1 min-w-0\">\n <form (ngSubmit)=\"onSubmit()\" class=\"flex flex-col gap-4\">\n <div class=\"flex flex-col gap-2\">\n <label class=\"font-medium text-color\">{{\n 'auth.email.label' | translate\n }}</label>\n <input\n fInputText\n [value]=\"userEmail()\"\n disabled\n class=\"bg-(--f-form-field-filled-background)\"\n [placeholder]=\"'auth.email.placeholder' | translate\"\n />\n </div>\n\n <div class=\"flex flex-col gap-2\">\n <label for=\"name\" class=\"font-medium text-color\"\n >{{ 'profile.name.label' | translate }} *</label\n >\n <input\n fInputText\n id=\"name\"\n [formField]=\"formTree.name\"\n [placeholder]=\"'profile.name.placeholder' | translate\"\n />\n </div>\n\n <div class=\"flex flex-col gap-2\">\n <label for=\"phone\" class=\"font-medium text-color\">{{\n 'profile.phone.label' | translate\n }}</label>\n <input\n fInputText\n id=\"phone\"\n [formField]=\"formTree.phone\"\n [placeholder]=\"'profile.phone.placeholder' | translate\"\n />\n </div>\n\n @if (editableFields().length > 0) {\n <div class=\"border-t border-surface pt-4 mt-2\">\n <div class=\"text-sm font-medium text-muted-color mb-4\">\n <ui-icon name=\"pencil\" class=\"mr-2\"></ui-icon\n >{{ 'profile.additional.info' | translate }}\n </div>\n @if (isLoadingExtraFields()) {\n <f-skeleton height=\"2rem\" class=\"mb-2\" />\n <f-skeleton height=\"2rem\" />\n } @else {\n <div class=\"flex flex-col gap-4\">\n @for (field of editableFields(); track field.key) {\n <div class=\"flex flex-col gap-2\">\n <label [for]=\"field.key\" class=\"font-medium text-color\">\n {{ field.labelKey | translate: null : field.label\n }}{{ field.required ? ' *' : '' }}\n </label>\n @if (field.component) {\n <ng-container\n [ngComponentOutlet]=\"field.component\"\n [ngComponentOutletInjector]=\"getFieldInjector(field)\"\n />\n } @else if (field.template) {\n <ng-container\n [ngTemplateOutlet]=\"field.template\"\n [ngTemplateOutletContext]=\"\n getFieldTemplateContext(field)\n \"\n />\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"fieldTemplate\"\n [ngTemplateOutletContext]=\"{ field: field }\"\n />\n }\n </div>\n }\n </div>\n @if (extraFieldsValidationError()) {\n <small class=\"text-danger block mt-2\">{{\n extraFieldsValidationError()\n }}</small>\n }\n }\n </div>\n }\n\n @if (viewOnlyFields().length > 0) {\n <div class=\"border-t border-surface pt-4 mt-2\">\n <div class=\"flex items-center justify-between mb-4\">\n <div class=\"text-sm font-medium text-muted-color\">\n <ui-icon name=\"eye\" class=\"mr-2\"></ui-icon\n >{{ 'profile.employment.info' | translate }}\n </div>\n <f-tag\n [value]=\"'profile.managed.by.admin' | translate\"\n severity=\"secondary\"\n />\n </div>\n @if (isLoadingExtraFields()) {\n <f-skeleton height=\"2rem\" class=\"mb-2\" />\n <f-skeleton height=\"2rem\" />\n } @else {\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n @for (field of viewOnlyFields(); track field.key) {\n <div class=\"flex flex-col gap-1\">\n <label class=\"text-sm text-muted-color\">{{\n field.labelKey | translate: null : field.label\n }}</label>\n <span class=\"text-color font-medium\">\n @if (field.type === 'select') {\n {{\n getSelectLabel(\n field,\n getAdminFieldValue(field.key)\n )\n }}\n } @else {\n {{ getAdminFieldValue(field.key) || '-' }}\n }\n </span>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <ng-template #fieldTemplate let-field=\"field\">\n @switch (field.type) {\n @case ('text') {\n <input\n fInputText\n [id]=\"field.key\"\n [placeholder]=\"\n field.placeholderKey\n | translate: null : field.placeholder ?? ''\n \"\n [value]=\"getExtraFieldValue(field.key) ?? ''\"\n [disabled]=\"field.editable === false\"\n (input)=\"\n updateExtraField(field.key, $any($event.target).value)\n \"\n class=\"w-full\"\n />\n }\n @case ('number') {\n <input\n fInputText\n type=\"number\"\n [id]=\"field.key\"\n [placeholder]=\"\n field.placeholderKey\n | translate: null : field.placeholder ?? ''\n \"\n [value]=\"getExtraFieldValue(field.key) ?? ''\"\n [disabled]=\"field.editable === false\"\n (input)=\"\n updateExtraField(\n field.key,\n $any($event.target).valueAsNumber\n )\n \"\n class=\"w-full\"\n />\n }\n @case ('textarea') {\n <textarea\n fTextarea\n [id]=\"field.key\"\n [placeholder]=\"\n field.placeholderKey\n | translate: null : field.placeholder ?? ''\n \"\n [value]=\"getExtraFieldValue(field.key) ?? ''\"\n [disabled]=\"field.editable === false\"\n (input)=\"\n updateExtraField(field.key, $any($event.target).value)\n \"\n class=\"w-full\"\n rows=\"3\"\n ></textarea>\n }\n @case ('select') {\n <f-select\n [id]=\"field.key\"\n class=\"w-full\"\n [options]=\"field.options ?? []\"\n optionValue=\"value\"\n [disabled]=\"field.editable === false\"\n [ngModel]=\"getExtraFieldValue(field.key) ?? ''\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"updateExtraField(field.key, $event)\"\n [placeholder]=\"\n field.placeholderKey\n | translate\n : null\n : field.placeholder ?? ('shared.select' | translate)\n \"\n >\n <ng-template #item let-opt>{{\n opt.labelKey | translate: null : opt.label\n }}</ng-template>\n <ng-template #selectedItem let-opt>{{\n opt.labelKey | translate: null : opt.label\n }}</ng-template>\n </f-select>\n }\n @case ('checkbox') {\n <f-checkbox\n [inputId]=\"field.key\"\n [checked]=\"$any(getExtraFieldValue(field.key) ?? false)\"\n [disabled]=\"field.editable === false\"\n (onChange)=\"updateExtraField(field.key, $event.checked)\"\n [label]=\"\n field.placeholderKey\n | translate\n : null\n : field.placeholder ??\n (field.labelKey | translate: null : field.label)\n \"\n />\n }\n @case ('date') {\n <input\n fInputText\n type=\"date\"\n [id]=\"field.key\"\n [value]=\"getExtraFieldValue(field.key) ?? ''\"\n [disabled]=\"field.editable === false\"\n (input)=\"\n updateExtraField(field.key, $any($event.target).value)\n \"\n class=\"w-full\"\n />\n }\n }\n </ng-template>\n\n <div class=\"flex justify-end pt-4\">\n <button\n fButton\n type=\"submit\"\n [disabled]=\"!isFormValid() || !isFormDirty() || isLoading()\"\n >\n @if (isLoading()) {\n <ui-icon pButtonIcon name=\"spinner\" [spin]=\"true\"></ui-icon>\n } @else {\n <ui-icon pButtonIcon name=\"check\"></ui-icon>\n }\n <span pButtonLabel>{{\n 'shared.save.changes' | translate\n }}</span>\n </button>\n </div>\n </form>\n </div>\n </div>\n </div>\n\n <div class=\"card mb-2 md:mb-4\">\n <div class=\"flex items-center gap-2 mb-4\">\n <ui-icon name=\"lock\" class=\"text-primary\"></ui-icon>\n <span class=\"font-semibold text-color\">{{\n 'profile.security' | translate\n }}</span>\n </div>\n <form (ngSubmit)=\"onChangePassword()\" class=\"flex flex-col gap-4\">\n <div class=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\n <div class=\"flex flex-col gap-2\">\n <label for=\"currentPassword\" class=\"font-medium text-color\"\n >{{ 'profile.current.password' | translate }} *</label\n >\n <f-password\n [inputId]=\"'currentPassword'\"\n [formField]=\"passwordForm.currentPassword\"\n [placeholder]=\"'profile.current.password.placeholder' | translate\"\n class=\"w-full\"\n autocomplete=\"current-password\"\n />\n </div>\n\n <div class=\"flex flex-col gap-2\">\n <label for=\"newPassword\" class=\"font-medium text-color\"\n >{{ 'profile.new.password' | translate }} *</label\n >\n <f-password\n [inputId]=\"'newPassword'\"\n [formField]=\"passwordForm.newPassword\"\n [placeholder]=\"'shared.min.characters' | translate: { count: passwordPolicy.minLength }\"\n class=\"w-full\"\n autocomplete=\"new-password\"\n />\n @if (newPasswordError()) {\n <small class=\"text-danger\">{{ newPasswordError() }}</small>\n }\n </div>\n\n <div class=\"flex flex-col gap-2\">\n <label for=\"confirmPassword\" class=\"font-medium text-color\"\n >{{ 'profile.confirm.password' | translate }} *</label\n >\n <f-password\n [inputId]=\"'confirmPassword'\"\n [formField]=\"passwordForm.confirmPassword\"\n [placeholder]=\"'profile.confirm.password.placeholder' | translate\"\n class=\"w-full\"\n autocomplete=\"new-password\"\n />\n @if (!passwordsMatch()) {\n <small class=\"text-danger\">{{\n 'auth.register.passwords.do.not.match' | translate\n }}</small>\n }\n </div>\n </div>\n\n <div class=\"flex justify-end\">\n <button\n fButton\n type=\"submit\"\n [disabled]=\"!isPasswordFormValid() || isPasswordLoading()\"\n >\n @if (isPasswordLoading()) {\n <ui-icon pButtonIcon name=\"spinner\" [spin]=\"true\"></ui-icon>\n } @else {\n <ui-icon pButtonIcon name=\"key\"></ui-icon>\n }\n <span pButtonLabel>{{\n 'profile.change.password' | translate\n }}</span>\n </button>\n </div>\n </form>\n </div>\n\n @for (section of extraSections(); track section.key) {\n @if (section.editPermission) {\n <div *hasPermission=\"section.editPermission\" class=\"card mb-2 md:mb-4\">\n <div class=\"flex items-center gap-2 mb-4\">\n @if (section.icon) {\n <ui-icon [name]=\"section.icon\" class=\"text-primary\"></ui-icon>\n }\n <span class=\"font-semibold text-color\">{{\n section.titleKey | translate: null : section.title\n }}</span>\n </div>\n <div class=\"section-content\">\n @if (section.component) {\n <ng-container [ngComponentOutlet]=\"section.component\" />\n }\n </div>\n </div>\n } @else {\n <div class=\"card mb-2 md:mb-4\">\n <div class=\"flex items-center gap-2 mb-4\">\n @if (section.icon) {\n <ui-icon [name]=\"section.icon\" class=\"text-primary\"></ui-icon>\n }\n <span class=\"font-semibold text-color\">{{\n section.titleKey | translate: null : section.title\n }}</span>\n </div>\n <div class=\"section-content\">\n @if (section.component) {\n <ng-container [ngComponentOutlet]=\"section.component\" />\n }\n </div>\n </div>\n }\n }\n\n @if (showBottomRow()) {\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-2 md:gap-4 flex-1\">\n @if (showCompanySection()) {\n <div class=\"card h-48 md:h-56 flex flex-col\">\n <div class=\"flex items-center gap-2 mb-4\">\n <ui-icon name=\"building\" class=\"text-primary\"></ui-icon>\n <span class=\"font-semibold text-color\">{{\n 'profile.company.branch' | translate\n }}</span>\n </div>\n <div class=\"flex flex-col gap-4 flex-1 overflow-auto\">\n <div class=\"flex items-center gap-3\">\n <div\n class=\"w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center flex-shrink-0\"\n >\n <ui-icon name=\"briefcase\" class=\"text-primary\"></ui-icon>\n </div>\n <div>\n <div class=\"text-sm text-muted-color\">\n {{ 'shared.company' | translate }}\n </div>\n <div class=\"font-medium text-color\">\n {{ companyName() || ('shared.not.assigned' | translate) }}\n </div>\n </div>\n </div>\n <div class=\"flex items-center gap-3\">\n <div\n class=\"w-10 h-10 rounded-lg bg-success/10 flex items-center justify-center flex-shrink-0\"\n >\n <ui-icon name=\"map-marker\" class=\"text-success\"></ui-icon>\n </div>\n <div>\n <div class=\"text-sm text-muted-color\">\n {{ 'profile.branch.label' | translate }}\n </div>\n <div class=\"font-medium text-color\">\n {{ branchName() || ('shared.not.assigned' | translate) }}\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n\n @if (showPermissionsSection()) {\n <div class=\"card h-48 md:h-56 flex flex-col\">\n <div class=\"flex items-center justify-between mb-4\">\n <div class=\"flex items-center gap-2\">\n <ui-icon name=\"shield\" class=\"text-primary\"></ui-icon>\n <span class=\"font-semibold text-color\">{{\n 'profile.permissions.label' | translate\n }}</span>\n </div>\n <f-tag\n [value]=\"'shared.read.only' | translate\"\n severity=\"secondary\"\n />\n </div>\n <div class=\"flex flex-col gap-4 flex-1 overflow-auto\">\n @if (showRoles()) {\n <div>\n <div\n class=\"text-sm text-muted-color mb-2 flex items-center gap-2\"\n >\n <ui-icon name=\"users\"></ui-icon>\n {{ 'profile.roles.label' | translate }}\n </div>\n @if (isLoadingPermissions()) {\n <f-skeleton height=\"1.5rem\" class=\"mb-2\" />\n } @else if (userRoles().length === 0) {\n <span class=\"text-muted-color text-sm\">{{\n 'profile.roles.none.assigned' | translate\n }}</span>\n } @else {\n <div class=\"flex flex-wrap gap-2\">\n @for (role of userRoles(); track role.id) {\n <f-tag [value]=\"role.name\" severity=\"info\" />\n }\n </div>\n }\n </div>\n }\n\n @if (showActions()) {\n <div>\n <div\n class=\"text-sm text-muted-color mb-2 flex items-center gap-2\"\n >\n <ui-icon name=\"bolt\"></ui-icon>\n {{ 'profile.actions.label' | translate }}\n </div>\n @if (isLoadingPermissions()) {\n <f-skeleton height=\"1.5rem\" class=\"mb-2\" />\n } @else if (userActions().length === 0) {\n <span class=\"text-muted-color text-sm\">{{\n 'profile.actions.none.assigned' | translate\n }}</span>\n } @else {\n <div class=\"flex flex-wrap gap-2\">\n @for (action of userActions(); track action.id) {\n <f-tag [value]=\"action.name\" severity=\"success\" />\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n `,\n})\nexport class ProfilePageComponent {\n private readonly destroyRef = inject(DestroyRef);\n private readonly appConfig = inject(APP_CONFIG);\n private readonly messageService = inject(MessageService);\n private readonly authState = inject(AuthStateService);\n private readonly userService = inject(UserApiService);\n private readonly authApiService = inject(AuthApiService);\n protected readonly passwordPolicy = inject(PasswordPolicyService);\n private readonly fileUrlService = inject(FileUrlService);\n private readonly fileProvider = inject(FILE_PROVIDER, { optional: true });\n private readonly permissionProvider = inject(PROFILE_PERMISSION_PROVIDER, {\n optional: true,\n });\n private readonly profileExtension = inject(AUTH_PROFILE_EXTENSION, {\n optional: true,\n });\n private readonly userFormExtension = inject(AUTH_USER_FORM_EXTENSION, {\n optional: true,\n });\n private readonly translateAdapter = inject(TranslateService, {\n optional: true,\n });\n\n private translate(\n key: string,\n vars?: Record<string, unknown>,\n ): string {\n return this.translateAdapter?.translate(key, vars) ?? key;\n }\n\n readonly isLoading = signal(false);\n readonly isLoadingPermissions = signal(false);\n readonly isLoadingExtraFields = signal(false);\n private readonly _profilePictureUrl = signal<string | null>(null);\n readonly profilePictureUrl = this._profilePictureUrl.asReadonly();\n\n private readonly _userRoles = signal<IProfileRoleInfo[]>([]);\n readonly userRoles = this._userRoles.asReadonly();\n private readonly _userActions = signal<IProfileActionInfo[]>([]);\n readonly userActions = this._userActions.asReadonly();\n\n readonly extraSections = computed<IProfileExtraSection[]>(() => {\n if (!this.profileExtension?.getExtraSections) return [];\n return sortByOrder(this.profileExtension.getExtraSections());\n });\n\n readonly editableFields = computed<IProfileExtraField[]>(() => {\n if (!this.profileExtension?.getExtraFields) return [];\n return sortByOrder(this.profileExtension.getExtraFields());\n });\n\n readonly viewOnlyFields = computed<IUserFormExtraField[]>(() => {\n if (!this.userFormExtension?.getExtraFields) return [];\n return sortByOrder(this.userFormExtension.getExtraFields());\n });\n\n readonly hasExtraContent = computed(\n () =>\n this.extraSections().length > 0 ||\n this.editableFields().length > 0 ||\n this.viewOnlyFields().length > 0,\n );\n\n readonly extraFieldsModel = signal<Record<string, unknown>>({});\n readonly originalExtraFieldsModel = signal<Record<string, unknown>>({});\n readonly adminFieldsModel = signal<Record<string, unknown>>({});\n\n readonly isExtraFieldsDirty = computed(() => {\n const current = this.extraFieldsModel();\n const original = this.originalExtraFieldsModel();\n return JSON.stringify(current) !== JSON.stringify(original);\n });\n\n readonly extraFieldsValidationError = computed(() => {\n if (!this.profileExtension?.validateExtraFields) return null;\n return this.profileExtension.validateExtraFields(this.extraFieldsModel());\n });\n\n readonly userEmail = computed(() => this.authState.user()?.email ?? '');\n readonly userName = computed(() => this.authState.userName());\n readonly userInitials = computed(() => {\n const name = this.authState.user()?.name ?? '';\n return name\n .split(' ')\n .map((n) => n[0])\n .join('')\n .toUpperCase()\n .slice(0, 2);\n });\n readonly companyName = computed(() => this.authState.companyName());\n readonly branchName = computed(() => this.authState.branchName());\n\n readonly showUploadSection = computed(\n () =>\n isServiceEnabled(this.appConfig, 'storage') && this.fileProvider !== null,\n );\n readonly showCompanySection = computed(() =>\n isCompanyFeatureEnabled(this.appConfig),\n );\n readonly showPermissionsSection = computed(\n () =>\n isServiceEnabled(this.appConfig, 'iam') &&\n this.permissionProvider !== null,\n );\n readonly permissionMode = computed(() => getPermissionMode(this.appConfig));\n readonly showRoles = computed(() => {\n const mode = this.permissionMode();\n return mode === 'rbac' || mode === 'full';\n });\n readonly showActions = computed(() => {\n const mode = this.permissionMode();\n return mode === 'direct' || mode === 'full';\n });\n readonly showBottomRow = computed(\n () => this.showCompanySection() || this.showPermissionsSection(),\n );\n\n private readonly originalFormModel = signal<IProfileFormModel>({\n name: '',\n phone: '',\n });\n readonly formModel = signal<IProfileFormModel>({ name: '', phone: '' });\n\n readonly formTree = form(this.formModel, (f) => {\n required(f.name, {\n message: this.translate('shared.name.required'),\n });\n });\n\n readonly isFormValid = computed(\n () => this.formModel().name.trim().length > 0,\n );\n\n readonly isFormDirty = computed(() => {\n const current = this.formModel();\n const original = this.originalFormModel();\n const basicDirty =\n current.name !== original.name || current.phone !== original.phone;\n return basicDirty || this.isExtraFieldsDirty();\n });\n\n updateExtraField(key: string, value: unknown): void {\n this.extraFieldsModel.update((model) => ({ ...model, [key]: value }));\n }\n\n getExtraFieldValue(key: string): unknown {\n return this.extraFieldsModel()[key];\n }\n\n getAdminFieldValue(key: string): unknown {\n return this.adminFieldsModel()[key];\n }\n\n getSelectLabel(\n field: IProfileExtraField | IUserFormExtraField,\n value: unknown,\n ): string {\n if (!value || !field.options) return '-';\n const option = field.options.find((opt) => opt.value === value);\n return option?.label ?? String(value);\n }\n\n getFieldTemplateContext(\n field: IProfileExtraField,\n ): IProfileFieldTemplateContext {\n return {\n field,\n value: this.extraFieldsModel()[field.key],\n updateValue: (value: unknown) => this.updateExtraField(field.key, value),\n };\n }\n\n private readonly parentInjector = inject(Injector);\n\n private readonly fieldInjectors = new Map<\n string,\n { injector: Injector; setField: (field: IProfileExtraField) => void }\n >();\n\n getFieldInjector(field: IProfileExtraField): Injector {\n const cached = this.fieldInjectors.get(field.key);\n if (cached) {\n cached.setField(field);\n return cached.injector;\n }\n\n let currentField = field;\n const extraFieldsModel = this.extraFieldsModel;\n const context: IProfileFieldTemplateContext = {\n get field() {\n return currentField;\n },\n get value() {\n return extraFieldsModel()[currentField.key];\n },\n updateValue: (value: unknown) =>\n this.updateExtraField(currentField.key, value),\n };\n\n const injector = Injector.create({\n providers: [{ provide: PROFILE_FIELD_CONTEXT, useValue: context }],\n parent: field.injector ?? this.parentInjector,\n });\n this.fieldInjectors.set(field.key, {\n injector,\n setField: (next) => (currentField = next),\n });\n return injector;\n }\n\n readonly passwordModel = signal<IPasswordFormModel>({\n currentPassword: '',\n newPassword: '',\n confirmPassword: '',\n });\n\n readonly passwordForm = form(this.passwordModel, (f) => {\n required(f.currentPassword, {\n message: this.translate('auth.password.change.current.required'),\n });\n required(f.newPassword, {\n message: this.translate('auth.validation.password.required'),\n });\n });\n\n readonly isPasswordLoading = signal(false);\n\n readonly newPasswordError = computed(() =>\n this.passwordPolicy.validate(this.passwordModel().newPassword),\n );\n\n readonly isPasswordFormValid = computed(() => {\n const model = this.passwordModel();\n return (\n model.currentPassword.length > 0 &&\n model.newPassword.length > 0 &&\n !this.newPasswordError() &&\n model.newPassword === model.confirmPassword\n );\n });\n\n readonly passwordsMatch = computed(() => {\n const model = this.passwordModel();\n return (\n model.confirmPassword.length === 0 ||\n model.newPassword === model.confirmPassword\n );\n });\n\n readonly profileUploadOptions = {\n folderPath: 'profile-pictures',\n compress: true,\n maxWidth: 400,\n maxHeight: 400,\n isPrivate: true,\n };\n\n constructor() {\n this.loadUserData();\n\n effect(() => {\n if (this.showPermissionsSection()) this.loadPermissions();\n });\n\n effect(() => {\n const user = this.authState.user();\n if (user && this.hasExtraContent()) this.loadExtraFields();\n });\n }\n\n private loadUserData(): void {\n const user = this.authState.user();\n if (user) {\n const initialValues: IProfileFormModel = {\n name: user.name ?? '',\n phone: user.phone ?? '',\n };\n this.originalFormModel.set(initialValues);\n this.formModel.set(initialValues);\n\n if (\n user.profilePictureId &&\n isServiceEnabled(this.appConfig, 'storage')\n ) {\n this.fileUrlService\n .fetchSingleFileUrl(user.profilePictureId)\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe((file) => this._profilePictureUrl.set(file?.url ?? null));\n }\n }\n }\n\n private loadPermissions(): void {\n const user = this.authState.user();\n const branch = this.authState.branch();\n\n if (!user || !this.permissionProvider) return;\n\n const loadRoles = this.showRoles();\n const loadActions = this.showActions();\n\n if (!loadRoles && !loadActions) return;\n\n this.isLoadingPermissions.set(true);\n\n const roles$ = loadRoles\n ? this.permissionProvider\n .getUserRoles(user.id, branch?.id)\n .pipe(catchError(() => of({ data: [] as IProfileRoleInfo[] })))\n : of({ data: [] as IProfileRoleInfo[] });\n\n const actions$ = loadActions\n ? this.permissionProvider\n .getUserActions(user.id, branch?.id)\n .pipe(catchError(() => of({ data: [] as IProfileActionInfo[] })))\n : of({ data: [] as IProfileActionInfo[] });\n\n forkJoin([roles$, actions$])\n .pipe(\n takeUntilDestroyed(this.destroyRef),\n finalize(() => this.isLoadingPermissions.set(false)),\n )\n .subscribe(([rolesResponse, actionsResponse]) => {\n this._userRoles.set(rolesResponse.data ?? []);\n this._userActions.set(actionsResponse.data ?? []);\n });\n }\n\n private loadExtraFields(): void {\n const user = this.authState.user();\n if (!user) return;\n\n const hasProfileFields = !!this.profileExtension?.getExtraFieldValues;\n const hasAdminFields = !!this.userFormExtension?.getExtraFieldValues;\n\n if (!hasProfileFields && !hasAdminFields) return;\n\n this.isLoadingExtraFields.set(true);\n\n const profileFields$ = hasProfileFields\n ? this.profileExtension!.getExtraFieldValues!(user.id).pipe(\n catchError(() => {\n const defaults: Record<string, unknown> = {};\n for (const field of this.editableFields()) {\n if (field.key) defaults[field.key] = undefined;\n }\n return of(defaults);\n }),\n )\n : of({} as Record<string, unknown>);\n\n const adminFields$ = hasAdminFields\n ? this.userFormExtension!.getExtraFieldValues!(user.id).pipe(\n catchError(() => {\n const defaults: Record<string, unknown> = {};\n for (const field of this.viewOnlyFields()) {\n if (field.key) defaults[field.key] = undefined;\n }\n return of(defaults);\n }),\n )\n : of({} as Record<string, unknown>);\n\n forkJoin([profileFields$, adminFields$])\n .pipe(\n takeUntilDestroyed(this.destroyRef),\n finalize(() => this.isLoadingExtraFields.set(false)),\n )\n .subscribe(([profileValues, adminValues]) => {\n this.extraFieldsModel.set(profileValues);\n this.originalExtraFieldsModel.set(profileValues);\n this.adminFieldsModel.set(adminValues);\n });\n }\n\n onProfilePictureUploaded(file: {\n id?: string;\n name: string;\n key: string;\n size: number;\n contentType: string;\n }): void {\n const user = this.authState.user();\n if (!user || !file.id) return;\n\n const fileManagerId = file.id;\n\n this.userService\n .updateProfile({ id: user.id, profilePictureId: fileManagerId })\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe({\n next: (response) => {\n if (response.success && response.data) {\n this.authState.setUser({\n ...user,\n profilePictureId: fileManagerId,\n });\n this.fileUrlService\n .fetchSingleFileUrl(fileManagerId, true)\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe((fileInfo) =>\n this._profilePictureUrl.set(fileInfo?.url ?? null),\n );\n this.messageService.add({\n severity: 'success',\n summary: this.translate('shared.success'),\n detail: response.messageKey\n ? this.translate(\n response.messageKey,\n response.messageVariables as Record<\n string,\n string | number\n >,\n )\n : response.message,\n });\n }\n },\n error: () => {},\n });\n }\n\n onSubmit(): void {\n if (!this.isFormValid()) return;\n\n const extraFieldsError = this.extraFieldsValidationError();\n if (extraFieldsError) {\n this.messageService.add({\n severity: 'error',\n summary: this.translate('shared.validation.error'),\n detail: extraFieldsError,\n });\n return;\n }\n\n const user = this.authState.user();\n if (!user) return;\n\n this.isLoading.set(true);\n const model = this.formModel();\n\n const updateData: IUpdateUserRequest = {\n id: user.id,\n name: model.name,\n phone: model.phone || undefined,\n };\n\n const profileUpdate$ = this.userService.updateProfile(updateData);\n const extraFieldsUpdate$ =\n this.isExtraFieldsDirty() && this.profileExtension?.saveExtraFieldValues\n ? this.profileExtension.saveExtraFieldValues(\n user.id,\n this.extraFieldsModel(),\n )\n : of(undefined);\n\n forkJoin([profileUpdate$, extraFieldsUpdate$])\n .pipe(\n takeUntilDestroyed(this.destroyRef),\n finalize(() => this.isLoading.set(false)),\n )\n .subscribe({\n next: ([response]) => {\n if (response.success && response.data) {\n this.authState.setUser({\n ...user,\n name: response.data.name,\n phone: response.data.phone ?? null,\n });\n this.originalFormModel.set({\n name: response.data.name,\n phone: response.data.phone ?? '',\n });\n this.originalExtraFieldsModel.set({ ...this.extraFieldsModel() });\n this.messageService.add({\n severity: 'success',\n summary: this.translate('shared.success'),\n detail: response.messageKey\n ? this.translate(\n response.messageKey,\n response.messageVariables as Record<\n string,\n string | number\n >,\n )\n : response.message,\n });\n }\n },\n error: () => {},\n });\n }\n\n updatePasswordField(field: keyof IPasswordFormModel, value: string): void {\n this.passwordModel.update((model) => ({ ...model, [field]: value }));\n }\n\n onChangePassword(): void {\n if (!this.isPasswordFormValid()) return;\n\n this.isPasswordLoading.set(true);\n const model = this.passwordModel();\n\n this.authApiService\n .changePassword({\n currentPassword: model.currentPassword,\n newPassword: model.newPassword,\n })\n .pipe(\n takeUntilDestroyed(this.destroyRef),\n finalize(() => this.isPasswordLoading.set(false)),\n )\n .subscribe({\n next: (response) => {\n this.messageService.add({\n severity: 'success',\n summary: this.translate('shared.success'),\n detail: response?.messageKey\n ? this.translate(response.messageKey, response.messageVariables)\n : response?.message,\n });\n this.passwordModel.set({\n currentPassword: '',\n newPassword: '',\n confirmPassword: '',\n });\n },\n error: () => {},\n });\n }\n}\n"],"mappings":"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"}