verben-authentication-ui 1.1.0 → 1.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 (159) hide show
  1. package/README.md +23 -1
  2. package/esm2022/src/lib/base/core/base-data-page.facade.mjs +215 -0
  3. package/esm2022/src/lib/base/core/base-data-page.service.mjs +103 -0
  4. package/esm2022/src/lib/base/core/base-data-page.state.mjs +203 -0
  5. package/esm2022/src/lib/base/handlers/filter-handler.service.mjs +53 -0
  6. package/esm2022/src/lib/base/handlers/search-handler.service.mjs +31 -0
  7. package/esm2022/src/lib/base/handlers/sort-handler.service.mjs +49 -0
  8. package/esm2022/src/lib/base/models/api-payload.mjs +4 -0
  9. package/esm2022/src/lib/base/models/page-config.interface.mjs +2 -0
  10. package/esm2022/src/lib/base/public-api.mjs +14 -6
  11. package/esm2022/src/lib/base/utils/column-helpers.mjs +45 -0
  12. package/esm2022/src/lib/components/button/button.component.mjs +3 -3
  13. package/esm2022/src/lib/components/forgot-password/forgot-password.component.mjs +2 -2
  14. package/esm2022/src/lib/components/mail/mail.component.mjs +3 -3
  15. package/esm2022/src/lib/components/mail-validation/mail-validation.component.mjs +5 -5
  16. package/esm2022/src/lib/components/o-auth/o-auth.component.mjs +3 -3
  17. package/esm2022/src/lib/components/otp-input/otp-input.component.mjs +2 -2
  18. package/esm2022/src/lib/components/reset-password/reset-password.component.mjs +2 -2
  19. package/esm2022/src/lib/components/role-control/base-table-style.mjs +6 -6
  20. package/esm2022/src/lib/components/role-control/role-control.component.mjs +3 -3
  21. package/esm2022/src/lib/components/sign-in/sign-in.component.mjs +4 -4
  22. package/esm2022/src/lib/components/sign-up/sign-up.component.mjs +6 -6
  23. package/esm2022/src/lib/components/sso/base-table-style.mjs +6 -6
  24. package/esm2022/src/lib/components/sso/sso-form/sso-form.component.mjs +3 -3
  25. package/esm2022/src/lib/components/sso/sso.component.mjs +3 -3
  26. package/esm2022/src/lib/components/two-factor-auth-otp/two-factor-auth-otp.component.mjs +4 -4
  27. package/esm2022/src/lib/components/two-factor-auth-setup/two-factor-auth-setup.component.mjs +5 -5
  28. package/esm2022/src/lib/components/user-management/public-api.mjs +2 -1
  29. package/esm2022/src/lib/components/user-management/user-management-card/user-management-card.component.mjs +23 -0
  30. package/esm2022/src/lib/components/user-management/user-management-form/user-management-form.component.mjs +53 -91
  31. package/esm2022/src/lib/components/user-management/user-management-table/user-management-table.component.mjs +68 -0
  32. package/esm2022/src/lib/components/user-management/user-management.component.mjs +98 -509
  33. package/esm2022/src/lib/components/user-management/user-management.module.mjs +11 -80
  34. package/esm2022/src/lib/components/user-management/user-status-badge/user-status-badge.component.mjs +8 -6
  35. package/esm2022/src/lib/components/user-management/user.config.mjs +94 -0
  36. package/esm2022/src/lib/components/user-management/user.facade.mjs +118 -0
  37. package/esm2022/src/lib/components/user-management/user.service.mjs +60 -0
  38. package/esm2022/src/lib/components/user-management/user.state.mjs +33 -0
  39. package/esm2022/src/lib/components/user-request/user-request.component.mjs +8 -8
  40. package/esm2022/src/lib/components/user-request-approval/public-api.mjs +2 -2
  41. package/esm2022/src/lib/components/user-request-approval/user-access-request-status-badge/user-access-request-status-badge.component.mjs +8 -6
  42. package/esm2022/src/lib/components/user-request-approval/user-access-request.config.mjs +79 -0
  43. package/esm2022/src/lib/components/user-request-approval/user-access-request.facade.mjs +123 -0
  44. package/esm2022/src/lib/components/user-request-approval/user-access-request.service.mjs +74 -0
  45. package/esm2022/src/lib/components/user-request-approval/user-access-request.state.mjs +26 -0
  46. package/esm2022/src/lib/components/user-request-approval/user-request-approval-card/user-request-approval-card.component.mjs +23 -0
  47. package/esm2022/src/lib/components/user-request-approval/user-request-approval-form/user-request-approval-form.component.mjs +124 -0
  48. package/esm2022/src/lib/components/user-request-approval/user-request-approval-table/user-request-approval-table.component.mjs +44 -0
  49. package/esm2022/src/lib/components/user-request-approval/user-request-approval.component.mjs +101 -273
  50. package/esm2022/src/lib/components/user-request-approval/user-request-approval.module.mjs +10 -74
  51. package/fesm2022/verben-authentication-ui-src-lib-base.mjs +596 -214
  52. package/fesm2022/verben-authentication-ui-src-lib-base.mjs.map +1 -1
  53. package/fesm2022/verben-authentication-ui-src-lib-components-button.mjs +2 -2
  54. package/fesm2022/verben-authentication-ui-src-lib-components-button.mjs.map +1 -1
  55. package/fesm2022/verben-authentication-ui-src-lib-components-forgot-password.mjs +2 -2
  56. package/fesm2022/verben-authentication-ui-src-lib-components-forgot-password.mjs.map +1 -1
  57. package/fesm2022/verben-authentication-ui-src-lib-components-mail-validation.mjs +4 -4
  58. package/fesm2022/verben-authentication-ui-src-lib-components-mail-validation.mjs.map +1 -1
  59. package/fesm2022/verben-authentication-ui-src-lib-components-mail.mjs +2 -2
  60. package/fesm2022/verben-authentication-ui-src-lib-components-mail.mjs.map +1 -1
  61. package/fesm2022/verben-authentication-ui-src-lib-components-o-auth.mjs +2 -2
  62. package/fesm2022/verben-authentication-ui-src-lib-components-o-auth.mjs.map +1 -1
  63. package/fesm2022/verben-authentication-ui-src-lib-components-otp-input.mjs +2 -2
  64. package/fesm2022/verben-authentication-ui-src-lib-components-otp-input.mjs.map +1 -1
  65. package/fesm2022/verben-authentication-ui-src-lib-components-reset-password.mjs +2 -2
  66. package/fesm2022/verben-authentication-ui-src-lib-components-reset-password.mjs.map +1 -1
  67. package/fesm2022/verben-authentication-ui-src-lib-components-role-control.mjs +7 -7
  68. package/fesm2022/verben-authentication-ui-src-lib-components-role-control.mjs.map +1 -1
  69. package/fesm2022/verben-authentication-ui-src-lib-components-sign-in.mjs +3 -3
  70. package/fesm2022/verben-authentication-ui-src-lib-components-sign-in.mjs.map +1 -1
  71. package/fesm2022/verben-authentication-ui-src-lib-components-sign-up.mjs +5 -5
  72. package/fesm2022/verben-authentication-ui-src-lib-components-sign-up.mjs.map +1 -1
  73. package/fesm2022/verben-authentication-ui-src-lib-components-sso.mjs +9 -9
  74. package/fesm2022/verben-authentication-ui-src-lib-components-sso.mjs.map +1 -1
  75. package/fesm2022/verben-authentication-ui-src-lib-components-two-factor-auth-otp.mjs +3 -3
  76. package/fesm2022/verben-authentication-ui-src-lib-components-two-factor-auth-otp.mjs.map +1 -1
  77. package/fesm2022/verben-authentication-ui-src-lib-components-two-factor-auth-setup.mjs +4 -4
  78. package/fesm2022/verben-authentication-ui-src-lib-components-two-factor-auth-setup.mjs.map +1 -1
  79. package/fesm2022/verben-authentication-ui-src-lib-components-user-management.mjs +468 -831
  80. package/fesm2022/verben-authentication-ui-src-lib-components-user-management.mjs.map +1 -1
  81. package/fesm2022/verben-authentication-ui-src-lib-components-user-request-approval.mjs +509 -952
  82. package/fesm2022/verben-authentication-ui-src-lib-components-user-request-approval.mjs.map +1 -1
  83. package/fesm2022/verben-authentication-ui-src-lib-components-user-request.mjs +7 -7
  84. package/fesm2022/verben-authentication-ui-src-lib-components-user-request.mjs.map +1 -1
  85. package/package.json +42 -48
  86. package/src/lib/base/README.md +99 -0
  87. package/src/lib/base/core/base-data-page.facade.d.ts +65 -0
  88. package/src/lib/base/core/base-data-page.service.d.ts +43 -0
  89. package/src/lib/base/core/base-data-page.state.d.ts +68 -0
  90. package/src/lib/base/handlers/filter-handler.service.d.ts +13 -0
  91. package/src/lib/base/handlers/search-handler.service.d.ts +20 -0
  92. package/src/lib/base/handlers/sort-handler.service.d.ts +13 -0
  93. package/src/lib/base/models/api-payload.d.ts +2 -0
  94. package/src/lib/base/models/page-config.interface.d.ts +21 -0
  95. package/src/lib/base/public-api.d.ts +9 -5
  96. package/src/lib/base/utils/column-helpers.d.ts +16 -0
  97. package/src/lib/components/user-management/public-api.d.ts +1 -0
  98. package/src/lib/components/user-management/user-management-card/user-management-card.component.d.ts +11 -0
  99. package/src/lib/components/user-management/user-management-form/user-management-form.component.d.ts +12 -14
  100. package/src/lib/components/user-management/user-management-table/user-management-table.component.d.ts +30 -0
  101. package/src/lib/components/user-management/user-management.component.d.ts +28 -124
  102. package/src/lib/components/user-management/user-management.module.d.ts +8 -8
  103. package/src/lib/components/user-management/user-status-badge/user-status-badge.component.d.ts +1 -1
  104. package/src/lib/components/user-management/user.config.d.ts +13 -0
  105. package/src/lib/components/user-management/user.facade.d.ts +42 -0
  106. package/src/lib/components/user-management/user.service.d.ts +26 -0
  107. package/src/lib/components/user-management/user.state.d.ts +19 -0
  108. package/src/lib/components/user-request-approval/public-api.d.ts +1 -1
  109. package/src/lib/components/user-request-approval/user-access-request-status-badge/user-access-request-status-badge.component.d.ts +1 -1
  110. package/src/lib/components/user-request-approval/user-access-request.config.d.ts +13 -0
  111. package/src/lib/components/user-request-approval/user-access-request.facade.d.ts +36 -0
  112. package/src/lib/components/user-request-approval/user-access-request.service.d.ts +30 -0
  113. package/src/lib/components/user-request-approval/user-access-request.state.d.ts +16 -0
  114. package/src/lib/components/user-request-approval/user-request-approval-card/user-request-approval-card.component.d.ts +11 -0
  115. package/src/lib/components/user-request-approval/user-request-approval-form/user-request-approval-form.component.d.ts +47 -0
  116. package/src/lib/components/user-request-approval/user-request-approval-table/user-request-approval-table.component.d.ts +20 -0
  117. package/src/lib/components/user-request-approval/user-request-approval.component.d.ts +29 -68
  118. package/src/lib/components/user-request-approval/user-request-approval.module.d.ts +7 -6
  119. package/esm2022/src/lib/base/base-data.component.mjs +0 -80
  120. package/esm2022/src/lib/base/base-data.facade.mjs +0 -130
  121. package/esm2022/src/lib/base/base-data.service.mjs +0 -21
  122. package/esm2022/src/lib/base/base-data.state.mjs +0 -74
  123. package/esm2022/src/lib/base/models.mjs +0 -2
  124. package/esm2022/src/lib/components/user-management/base-table-style.mjs +0 -53
  125. package/esm2022/src/lib/components/user-management/services/user-management.service.mjs +0 -110
  126. package/esm2022/src/lib/components/user-management/user-management.columns.mjs +0 -53
  127. package/esm2022/src/lib/components/user-request-approval/access-request.columns.mjs +0 -29
  128. package/esm2022/src/lib/components/user-request-approval/base-table-style.mjs +0 -53
  129. package/esm2022/src/lib/components/user-request-approval/facades/user-access-request.facade.mjs +0 -260
  130. package/esm2022/src/lib/components/user-request-approval/helper.mjs +0 -56
  131. package/esm2022/src/lib/components/user-request-approval/services/user-access-request.service.mjs +0 -92
  132. package/esm2022/src/lib/components/user-request-approval/states/user-access-request.state.mjs +0 -92
  133. package/esm2022/src/lib/components/user-request-approval/user-request-form/user-request-form.component.mjs +0 -105
  134. package/esm2022/src/lib/components/user-request-process/index.mjs +0 -2
  135. package/esm2022/src/lib/components/user-request-process/public-api.mjs +0 -3
  136. package/esm2022/src/lib/components/user-request-process/user-request-process.component.mjs +0 -11
  137. package/esm2022/src/lib/components/user-request-process/user-request-process.module.mjs +0 -18
  138. package/esm2022/src/lib/components/user-request-process/verben-authentication-ui-src-lib-components-user-request-process.mjs +0 -5
  139. package/fesm2022/verben-authentication-ui-src-lib-components-user-request-process.mjs +0 -34
  140. package/fesm2022/verben-authentication-ui-src-lib-components-user-request-process.mjs.map +0 -1
  141. package/src/lib/base/base-data.component.d.ts +0 -32
  142. package/src/lib/base/base-data.facade.d.ts +0 -27
  143. package/src/lib/base/base-data.service.d.ts +0 -14
  144. package/src/lib/base/base-data.state.d.ts +0 -28
  145. package/src/lib/base/models.d.ts +0 -11
  146. package/src/lib/components/user-management/base-table-style.d.ts +0 -1
  147. package/src/lib/components/user-management/services/user-management.service.d.ts +0 -44
  148. package/src/lib/components/user-management/user-management.columns.d.ts +0 -3
  149. package/src/lib/components/user-request-approval/access-request.columns.d.ts +0 -3
  150. package/src/lib/components/user-request-approval/base-table-style.d.ts +0 -1
  151. package/src/lib/components/user-request-approval/facades/user-access-request.facade.d.ts +0 -39
  152. package/src/lib/components/user-request-approval/helper.d.ts +0 -7
  153. package/src/lib/components/user-request-approval/services/user-access-request.service.d.ts +0 -64
  154. package/src/lib/components/user-request-approval/states/user-access-request.state.d.ts +0 -35
  155. package/src/lib/components/user-request-approval/user-request-form/user-request-form.component.d.ts +0 -34
  156. package/src/lib/components/user-request-process/index.d.ts +0 -1
  157. package/src/lib/components/user-request-process/public-api.d.ts +0 -2
  158. package/src/lib/components/user-request-process/user-request-process.component.d.ts +0 -5
  159. package/src/lib/components/user-request-process/user-request-process.module.d.ts +0 -7
@@ -1,23 +1,69 @@
1
+ import * as i2 from '@angular/common';
2
+ import { CommonModule } from '@angular/common';
1
3
  import * as i0 from '@angular/core';
2
- import { Injectable, EventEmitter, Component, Input, Output, signal, ViewChild, NgModule } from '@angular/core';
3
- import { ErrorResponse, SearchOperator, SearchPropertySign, SortDirection, Status, ObjectState, ConditionOptions } from 'verben-authentication-ui/src/lib/models';
4
- import { Subject } from 'rxjs';
5
- import * as i7 from 'verben-ng-ui';
6
- import { DataFilterType, ConditionalOptions, DataTableModule, CardModule, SvgModule, DataViewModule, CardDataViewModule, SortTableModule, VisibleColumnModule, TableFilterModule, DataExportModule, DataXportModule, VerbenaInputModule, VerbenaButtonModule, VerbenaBadgeModule, DropDownModule, VerbenaSwitchModule } from 'verben-ng-ui';
4
+ import { Component, Input, input, EventEmitter, effect, Output, Injectable, viewChild, inject, DestroyRef, ViewChild, NgModule } from '@angular/core';
5
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
+ import * as i2$1 from 'verben-authentication-ui/src/lib/base';
7
+ import { BaseDataPageState, BaseDataPageService, BaseDataPageFacade, SearchHandlerService } from 'verben-authentication-ui/src/lib/base';
8
+ import * as i3 from 'verben-ng-ui';
9
+ import { VerbenaBadgeModule, VerbenaInputModule, VerbenaButtonModule, DropDownModule, DataTableComponent, DataTableModule, SvgModule, DataViewModule, DataColumnsModule, DataFilterModule, DataSortModule, DataXportModule, CardDataViewModule } from 'verben-ng-ui';
10
+ import { Status, ObjectState, ErrorResponse, OAuthType } from 'verben-authentication-ui/src/lib/models';
7
11
  import * as i1 from '@angular/forms';
8
- import { FormsModule, ReactiveFormsModule } from '@angular/forms';
9
- import * as i4 from 'verben-authentication-ui/src/lib/services';
10
- import * as i1$1 from '@angular/router';
11
- import * as i3 from 'verben-authentication-ui/src/lib/components/user-request-approval';
12
- import { LibUserRequestApprovalModule } from 'verben-authentication-ui/src/lib/components/user-request-approval';
13
- import * as i6 from '@angular/common';
14
- import { CommonModule } from '@angular/common';
15
- import { HttpClientModule } from '@angular/common/http';
12
+ import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
13
+ import { BehaviorSubject } from 'rxjs';
14
+ import * as i1$1 from 'verben-authentication-ui/src/lib/services';
15
+
16
+ class UserStatusBadgeComponent {
17
+ status = Status.Active;
18
+ badgeConfig() {
19
+ switch (this.status) {
20
+ case Status.Active:
21
+ return { bgColor: 'var(--vbn-color-success-bg)', textColor: 'var(--vbn-color-success)', label: 'Active' };
22
+ case Status.InActive:
23
+ return { bgColor: 'var(--vbn-color-error-bg)', textColor: 'var(--vbn-color-error)', label: 'InActive' };
24
+ default:
25
+ return { bgColor: 'var(--vbn-color-text-muted)', textColor: 'var(--vbn-color-border)', label: 'Unknown' };
26
+ }
27
+ }
28
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserStatusBadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
29
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: UserStatusBadgeComponent, isStandalone: true, selector: "lib-user-status-badge", inputs: { status: "status" }, ngImport: i0, template: "<verbena-badge\n borderRadius=\"9px\"\n [bgColor]=\"badgeConfig().bgColor\"\n [textColor]=\"badgeConfig().textColor\"\n fontSize=\"12px\"\n [text]=\"badgeConfig().label\"\n [pd]=\"'2px 6px'\"\n></verbena-badge>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: VerbenaBadgeModule }, { kind: "component", type: i3.VerbenaBadgeComponent, selector: "verbena-badge", inputs: ["text", "bgColor", "textColor", "borderRadius", "pd", "fontSize", "width", "height"] }] });
30
+ }
31
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserStatusBadgeComponent, decorators: [{
32
+ type: Component,
33
+ args: [{ selector: 'lib-user-status-badge', standalone: true, imports: [CommonModule, VerbenaBadgeModule], template: "<verbena-badge\n borderRadius=\"9px\"\n [bgColor]=\"badgeConfig().bgColor\"\n [textColor]=\"badgeConfig().textColor\"\n fontSize=\"12px\"\n [text]=\"badgeConfig().label\"\n [pd]=\"'2px 6px'\"\n></verbena-badge>\n" }]
34
+ }], propDecorators: { status: [{
35
+ type: Input
36
+ }] } });
16
37
 
17
- const columns = [
38
+ /**
39
+ * Presentational card for a single user in the card view.
40
+ */
41
+ class UserManagementCardComponent {
42
+ user;
43
+ selected = false;
44
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserManagementCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
45
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: UserManagementCardComponent, isStandalone: true, selector: "lib-user-management-card", inputs: { user: "user", selected: "selected" }, ngImport: i0, template: "<div class=\"flex cursor-pointer w-full bg-secondary rounded-xl\">\n <div class=\"w-3 rounded-xl rounded-tr-none rounded-br-none\"\n [ngClass]=\"selected ? 'bg-primary' : 'bg-secondary-200'\"></div>\n <div class=\"flex-1 flex items-end gap-y-2 gap-x-4 p-4\">\n <div class=\"flex-1 space-y-2\">\n <span class=\"font-semibold text-[var(--vbn-color-text)] flex-1 truncate\">\n {{ user.FirstName }} {{ user.LastName }}\n </span>\n <p class=\"flex items-center my-1 gap-1\">\n <label class=\"text-[10px] font-light\">E-Mail:</label>\n <span class=\"text-sm truncate\">{{ user.MailAddress }}</span>\n </p>\n </div>\n <div class=\"grid gap-y-1\">\n <lib-user-status-badge [status]=\"user.Status\"></lib-user-status-badge>\n </div>\n </div>\n</div>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: UserStatusBadgeComponent, selector: "lib-user-status-badge", inputs: ["status"] }] });
46
+ }
47
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserManagementCardComponent, decorators: [{
48
+ type: Component,
49
+ args: [{ selector: 'lib-user-management-card', standalone: true, imports: [CommonModule, UserStatusBadgeComponent], template: "<div class=\"flex cursor-pointer w-full bg-secondary rounded-xl\">\n <div class=\"w-3 rounded-xl rounded-tr-none rounded-br-none\"\n [ngClass]=\"selected ? 'bg-primary' : 'bg-secondary-200'\"></div>\n <div class=\"flex-1 flex items-end gap-y-2 gap-x-4 p-4\">\n <div class=\"flex-1 space-y-2\">\n <span class=\"font-semibold text-[var(--vbn-color-text)] flex-1 truncate\">\n {{ user.FirstName }} {{ user.LastName }}\n </span>\n <p class=\"flex items-center my-1 gap-1\">\n <label class=\"text-[10px] font-light\">E-Mail:</label>\n <span class=\"text-sm truncate\">{{ user.MailAddress }}</span>\n </p>\n </div>\n <div class=\"grid gap-y-1\">\n <lib-user-status-badge [status]=\"user.Status\"></lib-user-status-badge>\n </div>\n </div>\n</div>\n", styles: [":host{display:block}\n"] }]
50
+ }], propDecorators: { user: [{
51
+ type: Input
52
+ }], selected: [{
53
+ type: Input
54
+ }] } });
55
+
56
+ const fb = new FormBuilder();
57
+ /**
58
+ * Column definitions for the user table.
59
+ * Single source of truth for table, filter, sort, and export.
60
+ * The role column keys on `RoleID`; the table renders it as the role name.
61
+ */
62
+ const USER_COLUMNS = [
18
63
  {
19
64
  id: 'select',
20
65
  header: '',
66
+ canExport: false,
21
67
  },
22
68
  {
23
69
  id: 'createdAt',
@@ -36,12 +82,6 @@ const columns = [
36
82
  accessorKey: 'MailAddress',
37
83
  formControlName: 'MailAddress',
38
84
  },
39
- // {
40
- // id: 'address',
41
- // header: 'ADDRESS',
42
- // accessorKey: 'Address',
43
- // formControlName: 'Address',
44
- // },
45
85
  {
46
86
  id: 'phone',
47
87
  header: 'PHONE NUMBER',
@@ -51,7 +91,7 @@ const columns = [
51
91
  {
52
92
  id: 'role',
53
93
  header: 'ROLE',
54
- accessorKey: 'Role',
94
+ accessorKey: 'RoleID',
55
95
  formControlName: 'RoleID',
56
96
  },
57
97
  {
@@ -63,890 +103,487 @@ const columns = [
63
103
  {
64
104
  id: 'actions',
65
105
  header: 'ACTIONS',
66
- accessorKey: 'MailAddress',
106
+ canExport: false,
67
107
  },
68
108
  ];
69
-
70
- const baseStyle = {
71
- width: "100%",
72
- fontFamily: '"Fraunces", serif',
73
- fontSize: '125%',
74
- whiteSpace: 'nowrap',
75
- margin: '0',
76
- border: '1px solid #D4A007',
77
- borderRadius: '16px',
78
- borderCollapse: 'separate',
79
- borderSpacing: '0',
80
- // tableLayout: 'fixed',
81
- overflow: 'hidden',
82
- rows: {
83
- even: {
84
- backgroundColor: '#FDFDFD',
85
- },
86
- odd: {
87
- backgroundColor: '#F1F4FB',
109
+ /**
110
+ * Page configuration for user management.
111
+ */
112
+ const USER_CONFIG = {
113
+ endpoint: 'User',
114
+ pageSize: 20,
115
+ columns: USER_COLUMNS,
116
+ cardDataMapper: (user) => ({
117
+ selected: false,
118
+ title: `${user.FirstName} ${user.LastName}`,
119
+ data: user,
120
+ body: [
121
+ { title: 'Name', value: `${user.FirstName} ${user.LastName}` },
122
+ { title: 'E-Mail Address', value: user.MailAddress },
123
+ { title: 'Phone Number', value: user.PhoneNumber || 'N/A' },
124
+ ],
125
+ children: [],
126
+ }),
127
+ searchDebounceTime: 500,
128
+ formGroupConfig: {
129
+ controls: {
130
+ MailAddress: fb.control(''),
131
+ FirstName: fb.control(''),
132
+ LastName: fb.control(''),
133
+ PhoneNumber: fb.control(''),
134
+ RoleID: fb.control(''),
135
+ Tags: fb.control([]),
136
+ Status: fb.control(''),
88
137
  },
89
- height: '68px',
90
- },
91
- cells: {
92
- padding: '0.5rem 1rem',
93
- },
94
- header: {
95
- stickyTop: true,
96
- zIndex: 2,
97
- backgroundColor: '#EFF2FB',
98
- fontWeight: 'bold',
99
- textAlign: 'left',
100
- padding: '12px 16px',
101
- height: '30px',
102
- },
103
- footer: {
104
- // stickyBottom: true,
105
- // zIndex: 2,
106
- padding: '3px',
107
- },
108
- // body: {
109
- // background: '#fff',
110
- // padding: '4px 5px',
111
- // textAlign: 'center',
112
- // },
113
- // firstColumn: {
114
- // stickyLeft: true,
115
- // zIndex: 1,
116
- // },
117
- lastColumn: {
118
- // stickyRight: true,
119
- // zIndex: 1,
120
138
  },
139
+ enableCreate: false,
140
+ enableImport: false,
141
+ enableExport: true,
142
+ enableFilter: true,
143
+ enableSort: true,
144
+ enableSearch: true,
145
+ enableCardView: true,
146
+ enableTableRowEdit: true,
121
147
  };
122
148
 
123
- class UserManagementService {
124
- httpService;
125
- // private readonly BASE_URL = 'https://auth.white360.net/User';
126
- constructor(httpService) {
127
- this.httpService = httpService;
128
- }
129
- /**
130
- * Get users with pagination and sorting
131
- * @param skip Number of records to skip
132
- * @param limit Number of records to take
133
- * @param sortParam Sort parameter
134
- * @param sortOrder Sort order ('asc' or 'desc')
135
- * @returns Promise containing the list of users
136
- */
137
- async getUsers(skip, limit, sortParam, sortOrder) {
138
- // var response : User[] | ErrorResponse;
139
- const url = `GetUsers/${skip}/${limit}/${sortParam}/${sortOrder}`;
140
- const res = await this.httpService.get(url);
141
- if (res instanceof ErrorResponse) {
142
- return res;
143
- }
144
- else {
145
- return res.Result;
146
- }
147
- }
148
- /**
149
- * Get users with an additional search parameter, pagination, and sorting
150
- * @param param Search parameter
151
- * @param skip Number of records to skip
152
- * @param limit Number of records to take
153
- * @param sortParam Sort parameter
154
- * @param sortOrder Sort order ('asc' or 'desc')
155
- * @returns Promise containing the filtered list of users
156
- */
157
- async getUsersWithParam(param, skip, limit, sortParam, sortOrder) {
158
- const url = `GetUserWithParam/${param}/${skip}/${limit}/${sortParam}/${sortOrder}`;
159
- return (await this.httpService.get(url));
160
- }
161
- async getRealUsers(role, skip, limit, sortParam, sortOrder) {
162
- let url;
163
- if (role) {
164
- // Role is provided, use the "GetUserWithParam" endpoint
165
- url = `GetUserWithParam/${role}/${skip}/${limit}/${sortParam}/${sortOrder}`;
166
- }
167
- else {
168
- // Role is null, use the "GetUsers" endpoint
169
- url = `GetUsers/${skip}/${limit}/${sortParam}/${sortOrder}`;
170
- }
171
- const res = await this.httpService.get(url);
172
- if (res instanceof ErrorResponse) {
173
- return res;
174
- }
175
- else {
176
- return res;
177
- }
178
- }
179
- /**
180
- * Save multiple users
181
- * @param users Array of users to save
182
- * @returns Promise containing the save operation result
183
- */
184
- saveUsers(users) {
185
- const url = `SaveUsers`;
186
- return this.httpService.post(url, users);
187
- }
188
- /**
189
- * Delete multiple users
190
- * @param userIds Array of user IDs to delete
191
- * @returns Observable containing the delete operation result
192
- */
193
- deleteUsers(userIds) {
194
- const url = `DeleteUsers`;
195
- return this.httpService.delete(`${url}?data=${userIds.join(',')}`);
196
- }
197
- async loadEntities(entity, fields, env, event = null) {
198
- var payload = {
199
- Fields: fields,
200
- SearchKeyValues: [
201
- {
202
- PropertyName: 'Code',
203
- EntityValue: '',
204
- Operator: SearchOperator.And,
205
- Sign: SearchPropertySign.EQ,
206
- Sort: SortDirection.Asc,
207
- },
208
- ],
209
- };
210
- const res = await this.httpService.post(`SearchDynamic${entity}/0/0`, payload, env);
211
- if (res instanceof ErrorResponse) {
212
- return [];
213
- }
214
- else {
215
- var result = res.Result;
216
- return result;
217
- }
218
- }
219
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserManagementService, deps: [{ token: i4.HttpWebRequestService }], target: i0.ɵɵFactoryTarget.Injectable });
220
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserManagementService, providedIn: 'root' });
221
- }
222
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserManagementService, decorators: [{
223
- type: Injectable,
224
- args: [{
225
- providedIn: 'root',
226
- }]
227
- }], ctorParameters: () => [{ type: i4.HttpWebRequestService }] });
228
-
149
+ /**
150
+ * Form for editing a user's role, tags, and status.
151
+ * Identity fields are read-only.
152
+ */
229
153
  class UserManagementFormComponent {
230
154
  fb;
231
- userManagementService;
232
- envService;
233
- // @Input() roles: Role[] = [];
234
- // @Input() status: Status[] = [];
235
- set currentData(value) {
236
- if (value?.data) {
237
- // Convert comma-separated warehouse codes back to array for dropdown
238
- // const warehouseCodes = value.data.Warehouses
239
- // ? value.data.Warehouses.split(',').filter((code: string) => code.trim())
240
- // : [];
241
- this.form.patchValue({
242
- MailAddress: value.data.MailAddress || '',
243
- FirstName: value.data.FirstName || '',
244
- LastName: value.data.LastName || '',
245
- PhoneNumber: value.data.PhoneNumber || '',
246
- // Address: value.data.Address || '',
247
- RoleID: value.data.RoleID || '',
248
- Tags: value.data.Tags || [],
249
- Status: value.data.Status || Status.Active,
250
- // Warehouses: warehouseCodes,
251
- });
252
- }
253
- else {
254
- this.form.reset();
255
- }
256
- }
257
- roles = [];
258
- tags = [];
259
- switchView = new EventEmitter();
260
- onFormSave = new EventEmitter();
155
+ user = input();
156
+ roles = input([]);
157
+ tags = input([]);
158
+ save = new EventEmitter();
159
+ switchToTable = new EventEmitter();
261
160
  form;
262
161
  statusOptions = Object.values(Status);
263
- // warehouses: Warehouse[] = [];
264
- constructor(fb, userManagementService, envService) {
162
+ constructor(fb) {
265
163
  this.fb = fb;
266
- this.userManagementService = userManagementService;
267
- this.envService = envService;
268
- this.form = this.fb.group({
269
- MailAddress: ['', { readonly: true }],
270
- FirstName: ['', { readonly: true }],
271
- LastName: ['', { readonly: true }],
272
- PhoneNumber: ['', { readonly: true }],
273
- // Address: ['', { readonly: true }],
274
- Status: ['', { readonly: true }],
275
- RoleID: [''],
276
- Tags: [[]],
277
- // Warehouses: [[]],
164
+ this.form = this.fb.group(USER_CONFIG.formGroupConfig.controls);
165
+ effect(() => {
166
+ const user = this.user();
167
+ if (user && this.form) {
168
+ this.form.patchValue({
169
+ MailAddress: user.MailAddress || '',
170
+ FirstName: user.FirstName || '',
171
+ LastName: user.LastName || '',
172
+ PhoneNumber: user.PhoneNumber || '',
173
+ RoleID: user.RoleID || '',
174
+ Tags: user.Tags || [],
175
+ Status: user.Status || Status.Active,
176
+ });
177
+ }
278
178
  });
279
179
  }
280
- ngOnInit() {
281
- // this.loadWarehouses();
282
- }
283
- // async loadWarehouses(): Promise<void> {
284
- // try {
285
- // this.warehouses = await this.userManagementService.loadEntities<Warehouse>(
286
- // 'Warehouse',
287
- // ['Name', 'Code'],
288
- // this.envService.environment.RevenueAPI
289
- // );
290
- // } catch (error) {
291
- // console.error('Error loading warehouses:', error);
292
- // this.warehouses = [];
293
- // }
294
- // }
295
- // onWarehouseChange(event: DropdownChangeEvent): void {
296
- // // Convert array of warehouse codes to comma-separated string
297
- // const selectedCodes = event.value as string[];
298
- // const commaSeparated = selectedCodes ? selectedCodes.join(',') : '';
299
- // // Update the form with the comma-separated value for saving
300
- // this.form.patchValue({
301
- // Warehouses: commaSeparated
302
- // }, { emitEvent: false });
303
- // }
304
180
  onSave() {
305
181
  if (this.form.valid) {
306
- // Emit save event with form value
307
- console.log('Form saved:', this.form.value);
308
- this.onFormSave.emit(this.form.value);
182
+ const merged = {
183
+ ...this.user(),
184
+ ...this.form.getRawValue(),
185
+ DataState: this.user()?.DataState === ObjectState.New
186
+ ? ObjectState.New
187
+ : ObjectState.Changed,
188
+ };
189
+ this.save.emit(merged);
309
190
  }
310
191
  }
311
- onDelete() {
312
- // Emit delete event
313
- console.log('Delete requested');
192
+ onSwitchToTable() {
193
+ this.switchToTable.emit();
314
194
  }
315
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserManagementFormComponent, deps: [{ token: i1.FormBuilder }, { token: UserManagementService }, { token: i4.EnvironmentService }], target: i0.ɵɵFactoryTarget.Component });
316
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: UserManagementFormComponent, selector: "lib-user-request-form", inputs: { currentData: "currentData", roles: "roles", tags: "tags" }, outputs: { switchView: "switchView", onFormSave: "onFormSave" }, ngImport: i0, template: "<form [formGroup]=\"form\" class=\"flex flex-col px-3 pb-3 rounded-xl h-full w-full relative space-y-4\">\n <verbena-input label=\"First Name:\" name=\"FirstName\" type=\"text\" formControlName=\"FirstName\" />\n <verbena-input label=\"Last Name:\" name=\"LastName\" type=\"text\" formControlName=\"LastName\" />\n <verbena-input label=\"Phone Number:\" name=\"PhoneNumber\" type=\"tel\" formControlName=\"PhoneNumber\" />\n <verbena-input name=\"MailAddress\" label=\"E-Mail Address:\" [type]=\"'email'\" formControlName=\"MailAddress\" />\n <!-- <verbena-input\n label=\"Address\"\n name=\"Address\"\n type=\"text\"\n formControlName=\"Address\"\n /> -->\n\n <div class=\"space-y-1\">\n <label for=\"role\">Role</label>\n\n <verben-drop-down label=\"Role\" styleClass=\"w-full\" width=\"100%\" [multiselect]=\"false\" [filter]=\"true\"\n [showClear]=\"true\" placeholder=\"\" [(options)]=\"roles\" id=\"role\" optionLabel=\"Name\" optionValue=\"Code\"\n formControlName=\"RoleID\" class=\"form-control\">\n </verben-drop-down>\n </div>\n\n <div class=\"space-y-1\">\n <label for=\"tags\">Tags</label>\n\n <verben-drop-down label=\"Tags\" styleClass=\"w-full\" width=\"100%\" [multiselect]=\"true\" [filter]=\"true\"\n [showClear]=\"true\" placeholder=\"\" [(options)]=\"tags\" id=\"tags\" optionLabel=\"Name\" optionValue=\"Code\"\n formControlName=\"Tags\" class=\"form-control\">\n </verben-drop-down>\n </div>\n\n <!-- <div class=\"space-y-1\">\n <label for=\"warehouses\">Warehouses</label>\n\n <verben-drop-down label=\"Warehouses\" styleClass=\"w-full\" width=\"100%\" [multiselect]=\"true\" [filter]=\"true\"\n [showClear]=\"true\" placeholder=\"\" [(options)]=\"warehouses\" id=\"warehouses\" optionLabel=\"Name\" optionValue=\"Code\"\n formControlName=\"Warehouses\" (onChange)=\"onWarehouseChange($event)\" class=\"form-control\">\n </verben-drop-down>\n </div> -->\n\n <div class=\"space-y-1\">\n <label for=\"status\">Status</label>\n\n <verben-drop-down styleClass=\"w-full\" width=\"100%\" [multiselect]=\"false\" [filter]=\"false\" [showClear]=\"false\"\n placeholder=\"\" [(options)]=\"statusOptions\" id=\"status\" formControlName=\"Status\" class=\"form-control\">\n </verben-drop-down>\n </div>\n</form>\n", styles: [""], dependencies: [{ kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i7.VerbenaInputComponent, selector: "verbena-input", inputs: ["disabled", "label", "placeHolder", "required", "svgPosition", "minLength", "maxLength", "type", "bgColor", "border", "borderRadius", "textColor", "value", "labelPosition", "labelColor", "disable", "readOnly", "min", "max", "showBorder", "showErrorMessage", "errorMessageColor", "errorBorderColor", "errorPosition", "svg", "fontSize", "svgWidth", "svgHeight", "svgColor", "capitalization", "inputContainerClass", "inputFieldClass", "passLength", "inputWrapperClass", "passwordToggle", "customErrorMessages", "icon", "textPass"], outputs: ["valueChange"] }, { kind: "component", type: i7.DropDownComponent, selector: "verben-drop-down", inputs: ["options", "width", "overlayWidth", "showHorizontalLine", "horizontalLineColor", "optionLabel", "optionSubLabel", "optionValue", "placeholder", "invalidMessage", "errorPosition", "loadMoreCaption", "display", "showClear", "lazyLoad", "selectKey", "styleClass", "group", "multiselect", "filter", "avoidDuplication", "filterBy", "debounceTime", "minChar", "refPageSize", "disabled", "required", "load", "asyncLabel", "search"], outputs: ["optionsChange", "onChange", "onClick", "onClear"] }] });
195
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserManagementFormComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
196
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.13", type: UserManagementFormComponent, isStandalone: true, selector: "lib-user-management-form", inputs: { user: { classPropertyName: "user", publicName: "user", isSignal: true, isRequired: false, transformFunction: null }, roles: { classPropertyName: "roles", publicName: "roles", isSignal: true, isRequired: false, transformFunction: null }, tags: { classPropertyName: "tags", publicName: "tags", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { save: "save", switchToTable: "switchToTable" }, ngImport: i0, template: "<form [formGroup]=\"form\" (ngSubmit)=\"onSave()\"\n class=\"flex flex-col px-3 pb-3 rounded-xl h-full w-full relative space-y-4\">\n <verbena-input label=\"First Name:\" name=\"FirstName\" type=\"text\" formControlName=\"FirstName\" [readOnly]=\"true\" />\n <verbena-input label=\"Last Name:\" name=\"LastName\" type=\"text\" formControlName=\"LastName\" [readOnly]=\"true\" />\n <verbena-input label=\"Phone Number:\" name=\"PhoneNumber\" type=\"tel\" formControlName=\"PhoneNumber\" [readOnly]=\"true\" />\n <verbena-input name=\"MailAddress\" label=\"E-Mail Address:\" [type]=\"'email'\" formControlName=\"MailAddress\"\n [readOnly]=\"true\" />\n\n <div class=\"space-y-1\">\n <label for=\"role\">Role</label>\n <verben-drop-down styleClass=\"w-full\" width=\"100%\" [multiselect]=\"false\" [filter]=\"true\" [showClear]=\"true\"\n placeholder=\"\" [options]=\"roles()\" id=\"role\" optionLabel=\"Name\" optionValue=\"Code\" formControlName=\"RoleID\"\n class=\"form-control\"></verben-drop-down>\n </div>\n\n <div class=\"space-y-1\">\n <label for=\"tags\">Tags</label>\n <verben-drop-down styleClass=\"w-full\" width=\"100%\" [multiselect]=\"true\" [filter]=\"true\" [showClear]=\"true\"\n placeholder=\"\" [options]=\"tags()\" id=\"tags\" optionLabel=\"Name\" optionValue=\"Code\" formControlName=\"Tags\"\n class=\"form-control\"></verben-drop-down>\n </div>\n\n <div class=\"space-y-1\">\n <label for=\"status\">Status</label>\n <verben-drop-down styleClass=\"w-full\" width=\"100%\" [multiselect]=\"false\" [filter]=\"false\" [showClear]=\"false\"\n placeholder=\"\" [options]=\"statusOptions\" id=\"status\" formControlName=\"Status\"\n class=\"form-control\"></verben-drop-down>\n </div>\n\n <!-- Form Actions -->\n <div class=\"flex justify-end gap-4 my-2 items-center\">\n <verbena-button styleType=\"ylw-outline\" text=\"Switch To Table\" (click)=\"onSwitchToTable()\" type=\"button\">\n </verbena-button>\n <verbena-button text=\"Save\" type=\"submit\" bgColor=\"#FFE681\" textColor=\"#404040\" borderRadius=\"10px\"\n pd=\"10px 20px\" width=\"114px\" height=\"39px\"></verbena-button>\n </div>\n</form>\n", styles: [":host{display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: VerbenaInputModule }, { kind: "component", type: i3.VerbenaInputComponent, selector: "verbena-input", inputs: ["disabled", "label", "placeHolder", "required", "svgPosition", "minLength", "maxLength", "type", "bgColor", "border", "borderRadius", "textColor", "value", "labelPosition", "labelColor", "disable", "readOnly", "min", "max", "showBorder", "showErrorMessage", "errorMessageColor", "errorBorderColor", "errorPosition", "svg", "fontSize", "svgWidth", "svgHeight", "svgColor", "capitalization", "inputContainerClass", "inputFieldClass", "passLength", "inputWrapperClass", "passwordToggle", "customErrorMessages", "icon", "textPass"], outputs: ["valueChange"] }, { kind: "ngmodule", type: VerbenaButtonModule }, { kind: "component", type: i3.VerbenaButtonComponent, selector: "verbena-button", inputs: ["type", "text", "icon", "useIcon", "svgPosition", "iconPosition", "bgColor", "textColor", "border", "borderRadius", "pd", "width", "height", "fontSize", "fontWeight", "disable", "svgSize", "weight", "variant", "styleType", "svg", "svgWidth", "svgHeight", "iconColor", "svgColor", "buttonClass", "buttonTextClass", "isLoading", "spinnerSize", "spinnerColor"] }, { kind: "ngmodule", type: DropDownModule }, { kind: "component", type: i3.DropDownComponent, selector: "verben-drop-down", inputs: ["options", "width", "overlayWidth", "showHorizontalLine", "horizontalLineColor", "optionLabel", "optionSubLabel", "optionValue", "placeholder", "invalidMessage", "errorPosition", "loadMoreCaption", "display", "showClear", "lazyLoad", "selectKey", "styleClass", "group", "multiselect", "filter", "avoidDuplication", "filterBy", "debounceTime", "minChar", "refPageSize", "disabled", "required", "load", "asyncLabel", "search"], outputs: ["optionsChange", "onChange", "onClick", "onClear"] }] });
317
197
  }
318
198
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserManagementFormComponent, decorators: [{
319
199
  type: Component,
320
- args: [{ selector: 'lib-user-request-form', template: "<form [formGroup]=\"form\" class=\"flex flex-col px-3 pb-3 rounded-xl h-full w-full relative space-y-4\">\n <verbena-input label=\"First Name:\" name=\"FirstName\" type=\"text\" formControlName=\"FirstName\" />\n <verbena-input label=\"Last Name:\" name=\"LastName\" type=\"text\" formControlName=\"LastName\" />\n <verbena-input label=\"Phone Number:\" name=\"PhoneNumber\" type=\"tel\" formControlName=\"PhoneNumber\" />\n <verbena-input name=\"MailAddress\" label=\"E-Mail Address:\" [type]=\"'email'\" formControlName=\"MailAddress\" />\n <!-- <verbena-input\n label=\"Address\"\n name=\"Address\"\n type=\"text\"\n formControlName=\"Address\"\n /> -->\n\n <div class=\"space-y-1\">\n <label for=\"role\">Role</label>\n\n <verben-drop-down label=\"Role\" styleClass=\"w-full\" width=\"100%\" [multiselect]=\"false\" [filter]=\"true\"\n [showClear]=\"true\" placeholder=\"\" [(options)]=\"roles\" id=\"role\" optionLabel=\"Name\" optionValue=\"Code\"\n formControlName=\"RoleID\" class=\"form-control\">\n </verben-drop-down>\n </div>\n\n <div class=\"space-y-1\">\n <label for=\"tags\">Tags</label>\n\n <verben-drop-down label=\"Tags\" styleClass=\"w-full\" width=\"100%\" [multiselect]=\"true\" [filter]=\"true\"\n [showClear]=\"true\" placeholder=\"\" [(options)]=\"tags\" id=\"tags\" optionLabel=\"Name\" optionValue=\"Code\"\n formControlName=\"Tags\" class=\"form-control\">\n </verben-drop-down>\n </div>\n\n <!-- <div class=\"space-y-1\">\n <label for=\"warehouses\">Warehouses</label>\n\n <verben-drop-down label=\"Warehouses\" styleClass=\"w-full\" width=\"100%\" [multiselect]=\"true\" [filter]=\"true\"\n [showClear]=\"true\" placeholder=\"\" [(options)]=\"warehouses\" id=\"warehouses\" optionLabel=\"Name\" optionValue=\"Code\"\n formControlName=\"Warehouses\" (onChange)=\"onWarehouseChange($event)\" class=\"form-control\">\n </verben-drop-down>\n </div> -->\n\n <div class=\"space-y-1\">\n <label for=\"status\">Status</label>\n\n <verben-drop-down styleClass=\"w-full\" width=\"100%\" [multiselect]=\"false\" [filter]=\"false\" [showClear]=\"false\"\n placeholder=\"\" [(options)]=\"statusOptions\" id=\"status\" formControlName=\"Status\" class=\"form-control\">\n </verben-drop-down>\n </div>\n</form>\n" }]
321
- }], ctorParameters: () => [{ type: i1.FormBuilder }, { type: UserManagementService }, { type: i4.EnvironmentService }], propDecorators: { currentData: [{
322
- type: Input
323
- }], roles: [{
324
- type: Input
325
- }], tags: [{
326
- type: Input
327
- }], switchView: [{
200
+ args: [{ selector: 'lib-user-management-form', standalone: true, imports: [
201
+ CommonModule,
202
+ ReactiveFormsModule,
203
+ VerbenaInputModule,
204
+ VerbenaButtonModule,
205
+ DropDownModule,
206
+ ], template: "<form [formGroup]=\"form\" (ngSubmit)=\"onSave()\"\n class=\"flex flex-col px-3 pb-3 rounded-xl h-full w-full relative space-y-4\">\n <verbena-input label=\"First Name:\" name=\"FirstName\" type=\"text\" formControlName=\"FirstName\" [readOnly]=\"true\" />\n <verbena-input label=\"Last Name:\" name=\"LastName\" type=\"text\" formControlName=\"LastName\" [readOnly]=\"true\" />\n <verbena-input label=\"Phone Number:\" name=\"PhoneNumber\" type=\"tel\" formControlName=\"PhoneNumber\" [readOnly]=\"true\" />\n <verbena-input name=\"MailAddress\" label=\"E-Mail Address:\" [type]=\"'email'\" formControlName=\"MailAddress\"\n [readOnly]=\"true\" />\n\n <div class=\"space-y-1\">\n <label for=\"role\">Role</label>\n <verben-drop-down styleClass=\"w-full\" width=\"100%\" [multiselect]=\"false\" [filter]=\"true\" [showClear]=\"true\"\n placeholder=\"\" [options]=\"roles()\" id=\"role\" optionLabel=\"Name\" optionValue=\"Code\" formControlName=\"RoleID\"\n class=\"form-control\"></verben-drop-down>\n </div>\n\n <div class=\"space-y-1\">\n <label for=\"tags\">Tags</label>\n <verben-drop-down styleClass=\"w-full\" width=\"100%\" [multiselect]=\"true\" [filter]=\"true\" [showClear]=\"true\"\n placeholder=\"\" [options]=\"tags()\" id=\"tags\" optionLabel=\"Name\" optionValue=\"Code\" formControlName=\"Tags\"\n class=\"form-control\"></verben-drop-down>\n </div>\n\n <div class=\"space-y-1\">\n <label for=\"status\">Status</label>\n <verben-drop-down styleClass=\"w-full\" width=\"100%\" [multiselect]=\"false\" [filter]=\"false\" [showClear]=\"false\"\n placeholder=\"\" [options]=\"statusOptions\" id=\"status\" formControlName=\"Status\"\n class=\"form-control\"></verben-drop-down>\n </div>\n\n <!-- Form Actions -->\n <div class=\"flex justify-end gap-4 my-2 items-center\">\n <verbena-button styleType=\"ylw-outline\" text=\"Switch To Table\" (click)=\"onSwitchToTable()\" type=\"button\">\n </verbena-button>\n <verbena-button text=\"Save\" type=\"submit\" bgColor=\"#FFE681\" textColor=\"#404040\" borderRadius=\"10px\"\n pd=\"10px 20px\" width=\"114px\" height=\"39px\"></verbena-button>\n </div>\n</form>\n", styles: [":host{display:block;width:100%;height:100%}\n"] }]
207
+ }], ctorParameters: () => [{ type: i1.FormBuilder }], propDecorators: { save: [{
328
208
  type: Output
329
- }], onFormSave: [{
209
+ }], switchToTable: [{
330
210
  type: Output
331
211
  }] } });
332
212
 
333
- class UserStatusBadgeComponent {
334
- status = Status.Active;
335
- badgeConfig() {
336
- switch (this.status) {
337
- case Status.Active:
338
- return { bgColor: '#CAE1CC', textColor: '#4ABB54', label: 'Active' };
339
- case Status.InActive:
340
- return { bgColor: '#FFDFDF', textColor: '#EB5757', label: 'InActive' };
341
- default:
342
- return { bgColor: '#827C7C', textColor: '#C3C3C3', label: 'Unknown' };
343
- }
213
+ /**
214
+ * State for the user-management page.
215
+ * Adds the roles/tags lists used by the form's dropdowns.
216
+ */
217
+ class UserState extends BaseDataPageState {
218
+ roles$ = new BehaviorSubject([]);
219
+ tags$ = new BehaviorSubject([]);
220
+ getRoles$() {
221
+ return this.roles$.asObservable();
344
222
  }
345
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserStatusBadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
346
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: UserStatusBadgeComponent, selector: "lib-user-status-badge", inputs: { status: "status" }, ngImport: i0, template: "<verbena-badge\n borderRadius=\"9px\"\n [bgColor]=\"badgeConfig().bgColor\"\n [textColor]=\"badgeConfig().textColor\"\n fontSize=\"12px\"\n [text]=\"badgeConfig().label\"\n [pd]=\"'2px 6px'\"\n></verbena-badge>\n", styles: [""], dependencies: [{ kind: "component", type: i7.VerbenaBadgeComponent, selector: "verbena-badge", inputs: ["text", "bgColor", "textColor", "borderRadius", "pd", "fontSize", "width", "height"] }] });
223
+ getRolesValue() {
224
+ return this.roles$.getValue();
225
+ }
226
+ setRoles(roles) {
227
+ this.roles$.next(roles);
228
+ }
229
+ getTags$() {
230
+ return this.tags$.asObservable();
231
+ }
232
+ setTags(tags) {
233
+ this.tags$.next(tags);
234
+ }
235
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserState, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
236
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserState });
347
237
  }
348
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserStatusBadgeComponent, decorators: [{
349
- type: Component,
350
- args: [{ selector: 'lib-user-status-badge', template: "<verbena-badge\n borderRadius=\"9px\"\n [bgColor]=\"badgeConfig().bgColor\"\n [textColor]=\"badgeConfig().textColor\"\n fontSize=\"12px\"\n [text]=\"badgeConfig().label\"\n [pd]=\"'2px 6px'\"\n></verbena-badge>\n" }]
351
- }], propDecorators: { status: [{
352
- type: Input
353
- }] } });
238
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserState, decorators: [{
239
+ type: Injectable
240
+ }] });
354
241
 
355
- var DateFilterTypes;
356
- (function (DateFilterTypes) {
357
- DateFilterTypes["Before"] = "LT";
358
- DateFilterTypes["On"] = "EQ";
359
- DateFilterTypes["After"] = "GT";
360
- })(DateFilterTypes || (DateFilterTypes = {}));
361
- class UserManagementComponent {
362
- route;
363
- userManagementService;
364
- userRole;
365
- server;
366
- utilService;
367
- envSvc;
368
- fb;
369
- cardDataView;
370
- dataView;
371
- childComponent;
372
- currentSearchTerm = '';
373
- allColumns = columns;
374
- filteredColumns = columns;
375
- skip = 0;
376
- users = [];
377
- searchTerm$ = new Subject();
378
- searchDebounceTime = 500;
379
- pageSize = 1;
380
- pageState = null;
381
- errorMessage = '';
382
- appliedFilters = false;
383
- isLoading = false;
384
- hasMore = true;
385
- limit = 20;
386
- sortParam = 'name';
387
- sortOrder = 'asc';
388
- Roles = [];
389
- Tags = signal([]);
390
- dataFit = {
391
- PageSize: 1,
392
- Skip: 0,
393
- Total: 0,
394
- Result: [],
395
- LastItem: [''],
396
- IsLoadingResults: false,
397
- };
398
- currentFilters = [];
399
- currentSorts = [];
400
- role = '';
401
- cardContextHistory = [];
402
- param;
403
- formGroupConfig;
404
- statuses = Object.values(Status);
405
- constructor(route, userManagementService, userRole, server, utilService, envSvc, fb) {
406
- this.route = route;
407
- this.userManagementService = userManagementService;
408
- this.userRole = userRole;
409
- this.server = server;
410
- this.utilService = utilService;
411
- this.envSvc = envSvc;
412
- this.fb = fb;
413
- this.formGroupConfig = signal({
414
- controls: {
415
- MailAddress: this.fb.control(''),
416
- FirstName: this.fb.control(''),
417
- PhoneNumber: this.fb.control(''),
418
- Address: this.fb.control(''),
419
- RoleID: this.fb.control(''),
420
- Tags: this.fb.control([]),
421
- Warehouses: this.fb.control(''),
422
- Status: this.fb.control(''),
423
- },
424
- // validatorOrOpts: null,
425
- // asyncValidator: null,
426
- });
242
+ /**
243
+ * Service for user API operations.
244
+ *
245
+ * The auth API pluralises names, appends a `/{sortParam}/{sortOrder}` suffix to
246
+ * reads, and deletes via a query string, so the base URL seams are overridden.
247
+ * Roles/tags are loaded here so this page no longer depends on the
248
+ * access-request module.
249
+ */
250
+ class UserService extends BaseDataPageService {
251
+ defaultSort = 'CreatedAt/Asc';
252
+ constructor(server, filterHandler, sortHandler) {
253
+ super(server, filterHandler, sortHandler);
427
254
  }
428
- async ngOnInit() {
429
- this.getRoles();
430
- this.getTags();
431
- this.route.paramMap.subscribe((params) => {
432
- this.role = params.get('role') || ''; // Default to an empty string if no role
433
- this.fetchUsers();
434
- });
255
+ getEndpoint() {
256
+ return 'User';
435
257
  }
436
- cardData = [];
437
- data = [];
438
- async fetchUsers(sortValue = 'CreatedAt', order = 'asc') {
439
- this.isLoading = true;
440
- this.utilService.sendBI(true);
441
- try {
442
- const res = await this.userManagementService.getRealUsers(this.role, this.skip, this.limit, this.sortParam, this.sortOrder);
443
- this.utilService.sendBI(false);
444
- if (res instanceof ErrorResponse) {
445
- // Handle error response
446
- console.error('Error fetching logs:', res);
447
- }
448
- else {
449
- const response = res;
450
- this.dataFit = response;
451
- this.users = [...this.users, ...response.Result];
452
- this.cardData = this.formatCardData(this.users);
453
- this.skip = response.Skip;
454
- this.hasMore = this.skip < response.Total;
455
- }
456
- }
457
- catch (error) {
458
- console.error('Error:', error);
459
- }
460
- finally {
461
- this.isLoading = false;
462
- }
258
+ // ===== URL seams =====
259
+ listUrl(skip, limit) {
260
+ return `GetUsers/${skip}/${limit}/${this.defaultSort}`;
261
+ }
262
+ searchTermUrl(term, skip, limit) {
263
+ return `GetUserWithParam/${term}/${skip}/${limit}/${this.defaultSort}`;
463
264
  }
265
+ filterSearchUrl(skip, limit) {
266
+ return `SearchUsers/${skip}/${limit}/${this.defaultSort}`;
267
+ }
268
+ saveUrl() {
269
+ return 'SaveUsers';
270
+ }
271
+ deleteUrl(itemIds) {
272
+ return `DeleteUsers?data=${itemIds.join(',')}`;
273
+ }
274
+ // ===== Lookups =====
464
275
  async getRoles() {
465
- this.utilService.sendBI(true);
466
- try {
467
- const res = await this.userRole.getRoles();
468
- this.utilService.sendBI(false);
469
- if (res instanceof ErrorResponse) {
470
- console.error('Error fetching roles:', res);
471
- return undefined;
472
- }
473
- const response = res;
474
- this.Roles = response.Result;
475
- }
476
- catch (error) {
477
- console.error('Error fetching roles:', error);
478
- return undefined;
276
+ const res = await this.server.get('GetRoles/0/0');
277
+ if (res instanceof ErrorResponse) {
278
+ return [];
479
279
  }
280
+ return res.Result ?? [];
480
281
  }
481
282
  async getTags() {
482
- this.utilService.sendBI(true);
483
- try {
484
- const res = await this.userRole.getTags();
485
- this.utilService.sendBI(false);
486
- if (res instanceof ErrorResponse) {
487
- console.error('Error fetching roles:', res);
488
- return undefined;
489
- }
490
- const response = res;
491
- this.Tags.set(response.Result);
283
+ const res = await this.server.get('GetTags/0/0');
284
+ if (res instanceof ErrorResponse) {
285
+ return [];
286
+ }
287
+ return res.Result ?? [];
288
+ }
289
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserService, deps: [{ token: i1$1.HttpWebRequestService }, { token: i2$1.FilterHandlerService }, { token: i2$1.SortHandlerService }], target: i0.ɵɵFactoryTarget.Injectable });
290
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserService });
291
+ }
292
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserService, decorators: [{
293
+ type: Injectable
294
+ }], ctorParameters: () => [{ type: i1$1.HttpWebRequestService }, { type: i2$1.FilterHandlerService }, { type: i2$1.SortHandlerService }] });
295
+
296
+ /**
297
+ * Facade for the user-management page.
298
+ */
299
+ class UserFacade extends BaseDataPageFacade {
300
+ userService;
301
+ blankUser;
302
+ constructor(state, service, searchHandler, utilService) {
303
+ super(state, service, searchHandler, utilService, USER_CONFIG);
304
+ this.userService = service;
305
+ }
306
+ // ===== Custom observables =====
307
+ get roles$() {
308
+ return this.state.getRoles$();
309
+ }
310
+ get tags$() {
311
+ return this.state.getTags$();
312
+ }
313
+ // ===== Runtime configuration (from component @Inputs) =====
314
+ applyRuntimeConfig(options) {
315
+ if (options.pageSize && options.pageSize > 0) {
316
+ this.state.updateQueryParams({ limit: options.pageSize });
492
317
  }
493
- catch (error) {
494
- console.error('Error fetching roles:', error);
495
- return undefined;
318
+ if (options.searchDebounceTime && options.searchDebounceTime > 0) {
319
+ this.searchHandler.setDebounceTime(options.searchDebounceTime);
496
320
  }
497
321
  }
498
- handleRoleId(value) {
499
- const matchedRole = this.Roles.filter((role) => role.Name === value);
500
- return matchedRole[0]?.Code;
322
+ /** Seed an initial search term (used by the optional `role` input). */
323
+ setInitialSearch(term) {
324
+ this.state.setSearchTerm(term);
501
325
  }
326
+ // ===== Lookups =====
327
+ async loadRoles() {
328
+ this.state.setRoles(await this.userService.getRoles());
329
+ }
330
+ async loadTags() {
331
+ this.state.setTags(await this.userService.getTags());
332
+ }
333
+ getRoleName(roleId) {
334
+ return this.state.getRolesValue().find((r) => r.Code === roleId)?.Name ?? '';
335
+ }
336
+ // ===== View management =====
502
337
  /**
503
- * Format users into CardData for the UI library
504
- * @param users Array of users to format
505
- * @returns Array of CardData
338
+ * Select the user to show in the form. The form template binds to
339
+ * currentCardData(), so route selection through selectCard (reusing the
340
+ * matching card from the loaded list when present) rather than a separate
341
+ * selected-user stream that nothing reads.
506
342
  */
507
- formatCardData(users) {
508
- return users.map((user) => ({
509
- selected: false, // Default selection state
510
- title: `${user.FirstName} ${user.LastName}`, // Display user's name as title
511
- data: { ...user }, // Pass the entire user object
512
- body: [
513
- { title: 'Name', value: `${user.FirstName} ${user.LastName}` },
514
- { title: 'E-Mail Address', value: user.MailAddress },
515
- { title: 'Phone Number', value: user.PhoneNumber || 'N/A' },
516
- ],
517
- children: [], // Add child data if necessary
518
- }));
519
- }
520
- columns = columns;
521
- styles = baseStyle;
522
- selectedParent;
523
- basicOption;
524
- selectedOption = [];
525
- selectedOptionTwo = [];
526
- selectedOptionThree;
527
- missingObject;
528
- // clearLogs(sortValue: string = 'CreatedAt', order: string = 'asc') {
529
- // this.User = []; // Clear the logs array
530
- // this.skip = 0; // Reset the skip value
531
- // this.hasMore = true; // Reset the flag to allow fetching more logs
532
- // this.appliedFilters = false;
533
- // this.fetchUsers();
534
- // }
535
- // Grid view properties
536
- isGridView = true;
537
- currentData;
538
- selectedColumnCount = 0;
539
- selectedFilterTableCount = 0;
540
- isOPen = true;
541
- selectedSortCount = 0;
542
- showFilter = false;
543
- searchTerm = '';
544
- showColumn = false;
545
- showSort = false;
546
- selectedAll = false;
547
- visibleColumns = columns.map((col) => ({
548
- checked: false,
549
- name: typeof col.header === 'string' ? col.header : col.id,
550
- type: DataFilterType.Bool,
551
- }));
552
- filterArray = [
553
- { name: 'FirstName', type: DataFilterType.String, checked: false },
554
- { name: 'LastName', type: DataFilterType.String, checked: false },
555
- { name: 'MailAddress', type: DataFilterType.String, checked: false },
556
- { name: 'Status', type: DataFilterType.String, checked: false },
557
- { name: 'PhoneNumber', type: DataFilterType.String, checked: false },
558
- { name: 'CreatedAt', type: DataFilterType.Date, checked: false },
559
- { name: 'Role', type: DataFilterType.String, checked: false },
560
- ];
561
- sortOptions = [
562
- { name: 'Name', type: DataFilterType.String, checked: false },
563
- { name: 'MailAddress', type: DataFilterType.String, checked: false },
564
- { name: 'PhoneNumber', type: DataFilterType.String, checked: false },
565
- { name: 'CreatedAt', type: DataFilterType.Date, checked: false },
566
- ];
567
- testParents = [
568
- { Id: '1', Name: 'Manager' },
569
- { Id: '2', Name: 'Administrator' },
570
- { Id: '3', Name: 'Jelom' },
571
- ];
572
- getParentLabel(context) {
573
- console.log({ MissingObj: this.missingObject });
574
- return this.missingObject.Name;
343
+ openForm(user) {
344
+ const target = user ?? this.createEmptyUser();
345
+ const existing = this.cardData().find((card) => card.data?.Code === target.Code);
346
+ this.selectCard(existing ?? this.getConfig().cardDataMapper(target));
575
347
  }
576
- onSave() {
577
- if (this.childComponent.form.valid) {
578
- // const userData: User = this.childComponent.form.value;
579
- // console.log('Payload:', [userData]); // Log the payload to check its structure
580
- this.utilService.sendBI(true);
581
- this.userManagementService
582
- .saveUsers([
583
- {
584
- ...this.currentData?.data,
585
- ...this.childComponent.form.value,
586
- DataState: this.currentData?.data.DataState === ObjectState.Unchanged
587
- ? ObjectState.Changed
588
- : this.currentData?.data.DataState,
589
- },
590
- ])
591
- .then((result) => {
592
- if (result instanceof ErrorResponse) {
593
- }
594
- else {
595
- this.utilService.showSuccess('User saved successfully');
596
- }
597
- }, (error) => {
598
- console.error('Unexpected error saving user:', error);
599
- })
600
- .finally(() => {
601
- this.utilService.sendBI(false);
602
- });
603
- console.log(this.childComponent.form.value);
604
- }
605
- else {
606
- console.error('Form is invalid');
607
- }
348
+ closeForm() {
349
+ this.selectCard(null);
608
350
  }
609
- async onDataSave(event) {
351
+ handleColumnsUpdated(columns) {
352
+ this.updateVisibleColumns(columns);
353
+ }
354
+ // ===== User operations =====
355
+ async saveUser(user) {
610
356
  const payload = {
611
- ...this.users[event.index],
612
- ...event.data,
613
- DataState: this.users[event.index]?.DataState === ObjectState.Unchanged
614
- ? ObjectState.Changed
615
- : ObjectState.New,
357
+ ...user,
358
+ DataState: user.DataState === ObjectState.New ? ObjectState.New : ObjectState.Changed,
359
+ };
360
+ const success = await this.saveItems([payload]);
361
+ if (success) {
362
+ this.closeForm();
363
+ await this.refresh();
364
+ }
365
+ return success;
366
+ }
367
+ async deleteUser(id) {
368
+ const success = await this.deleteItems([id]);
369
+ if (success) {
370
+ this.closeForm();
371
+ await this.refresh();
372
+ }
373
+ return success;
374
+ }
375
+ // ===== Empty placeholder =====
376
+ get emptyUser() {
377
+ return (this.blankUser ??= this.createEmptyUser());
378
+ }
379
+ createEmptyUser() {
380
+ return {
381
+ id: Date.now().toString(),
382
+ Id: '',
383
+ Code: '',
384
+ TenantId: '',
385
+ ServiceName: '',
386
+ CreatedAt: new Date(),
387
+ UpdatedAt: new Date(),
388
+ DataState: ObjectState.New,
389
+ Password: '',
390
+ FirstName: '',
391
+ LastName: '',
392
+ MailAddress: '',
393
+ IsSeeded: false,
394
+ Status: Status.Active,
395
+ SignupType: OAuthType.InApp,
616
396
  };
617
- this.utilService.sendBI(true);
618
- this.userManagementService
619
- .saveUsers([payload])
620
- .then((result) => {
621
- if (result instanceof ErrorResponse) {
622
- }
623
- else {
624
- if (result[0]) {
625
- this.users = this.users.map((user, index) => {
626
- if (index === event.index)
627
- return result[0];
628
- return user;
629
- });
630
- }
631
- this.utilService.showSuccess('User saved successfully');
632
- }
633
- }, (error) => {
634
- console.error('Unexpected error saving user:', error);
635
- })
636
- .finally(() => {
637
- this.utilService.sendBI(false);
638
- });
639
- }
640
- onDelete() {
641
- console.log('Child form delete triggered');
642
- // Perform delete logic here
643
- }
644
- onDropdownChange(event) {
645
- // console.log({
646
- // 'Test Parent Value': this.selectedParent,
647
- // ...
648
- // });
649
- }
650
- onSelectionChange(selectedRows) {
651
- console.log('Selection changed:', selectedRows);
652
- // Handle the selection change
653
- }
654
- handleExport(exportedData) {
655
- console.log('Exported data:', exportedData);
656
- this.downloadCSV(exportedData);
657
- }
658
- downloadCSV(data) {
659
- const headers = Object.keys(data[0]);
660
- const csvContent = [
661
- headers.join(','),
662
- ...data.map((row) => headers.map((header) => row[header]).join(',')),
663
- ].join('\n');
664
- const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
665
- const link = document.createElement('a');
666
- if (link.download !== undefined) {
667
- const url = URL.createObjectURL(blob);
668
- link.setAttribute('href', url);
669
- link.setAttribute('download', 'export.csv');
670
- link.style.visibility = 'hidden';
671
- document.body.appendChild(link);
672
- link.click();
673
- document.body.removeChild(link);
674
- }
675
397
  }
676
- getCardDataByMailAddress(mailAddress) {
677
- console.log('cardData array:', this.cardData);
678
- console.log(mailAddress);
679
- return this.cardData.find(({ data }) => data?.MailAddress === mailAddress);
680
- }
681
- openDetailView(mailAddress) {
682
- const cardItem = this.getCardDataByMailAddress(mailAddress);
683
- console.log(cardItem);
684
- if (cardItem && this.cardDataView) {
685
- this.dataView.toggleView();
686
- // First reset all selections
687
- this.cardData.forEach((item) => {
688
- item.selected = false;
689
- if (item.children) {
690
- item.children.forEach((child) => (child.selected = false));
691
- }
692
- });
693
- // Set the selected item
694
- cardItem.selected = true;
695
- this.currentData = this.cardDataView.onItemClick(cardItem);
696
- // Force change detection if needed
697
- // this.changeDetectorRef.detectChanges();
698
- }
398
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserFacade, deps: [{ token: UserState }, { token: UserService }, { token: i2$1.SearchHandlerService }, { token: i1$1.UtilService }], target: i0.ɵɵFactoryTarget.Injectable });
399
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserFacade });
400
+ }
401
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserFacade, decorators: [{
402
+ type: Injectable
403
+ }], ctorParameters: () => [{ type: UserState }, { type: UserService }, { type: i2$1.SearchHandlerService }, { type: i1$1.UtilService }] });
404
+
405
+ /**
406
+ * Table view for users with inline row editing.
407
+ */
408
+ class UserManagementTableComponent {
409
+ facade;
410
+ tableView = viewChild(DataTableComponent);
411
+ users = [];
412
+ columns = [];
413
+ isLoading = false;
414
+ formGroupConfig;
415
+ view = new EventEmitter();
416
+ delete = new EventEmitter();
417
+ saveRow = new EventEmitter();
418
+ statuses = Object.values(Status);
419
+ constructor(facade) {
420
+ this.facade = facade;
699
421
  }
700
- reset() {
701
- this.skip = 0;
702
- this.pageSize = 20;
422
+ onView(user) {
423
+ this.view.emit(user);
703
424
  }
704
- clearData() {
705
- this.currentData = {};
425
+ onDelete(user) {
426
+ this.delete.emit(user);
706
427
  }
707
- loadMore() {
708
- if (this.hasMore) {
709
- this.fetchUsers();
710
- }
428
+ onRowSaved(event) {
429
+ const original = this.users[event.index] ?? {};
430
+ this.saveRow.emit({ ...original, ...event.data });
711
431
  }
712
- onColumnChange(event) {
713
- this.showColumn = event;
714
- }
715
- onSortChange(event) {
716
- this.showSort = event;
717
- console.log(event);
718
- }
719
- onColumnsUpdated(updatedColumns) {
720
- this.onColumnChange(false);
721
- this.selectedColumnCount = updatedColumns.length;
722
- if (updatedColumns) {
723
- // Filter columns to include only visible ones
724
- this.filteredColumns = this.columns.filter((col) => this.visibleColumns.find((filter) => filter.name === col.header && filter.checked));
725
- // Reorder columns based on the order in visibleColumns
726
- const visibleColumnOrder = this.visibleColumns
727
- .filter((filter) => filter.checked)
728
- .map((filter) => filter.name);
729
- this.columns.sort((a, b) => {
730
- const indexA = visibleColumnOrder.indexOf(a.header);
731
- const indexB = visibleColumnOrder.indexOf(b.header);
732
- return indexA - indexB;
733
- });
734
- }
432
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserManagementTableComponent, deps: [{ token: UserFacade }], target: i0.ɵɵFactoryTarget.Component });
433
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "18.2.13", type: UserManagementTableComponent, isStandalone: true, selector: "lib-user-management-table", inputs: { users: "users", columns: "columns", isLoading: "isLoading", formGroupConfig: "formGroupConfig" }, outputs: { view: "view", delete: "delete", saveRow: "saveRow" }, viewQueries: [{ propertyName: "tableView", first: true, predicate: DataTableComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"table-container\" [class.loading]=\"isLoading\">\n <lib-data-table [data]=\"users\" [columns]=\"columns\" [formGroupConfig]=\"formGroupConfig\" dataKey=\"Code\"\n (rowSave)=\"onRowSaved($event)\">\n <!-- Select -->\n <ng-container libColumn=\"select\">\n <ng-template #cell let-isSelected=\"isSelected\" let-toggleRowSelection=\"toggleRowSelection\">\n <input type=\"checkbox\" [checked]=\"isSelected\" (change)=\"toggleRowSelection()\" />\n </ng-template>\n </ng-container>\n\n <!-- Created -->\n <ng-container libColumn=\"createdAt\">\n <ng-template #cell let-value>{{ value | date }}</ng-template>\n </ng-container>\n\n <!-- Mail -->\n <ng-container libColumn=\"mail\">\n <ng-template #cell let-value>{{ value }}</ng-template>\n <ng-template #cellEdit let-control=\"control\">\n <verbena-input name=\"MailAddress\" [formControl]=\"control\" placeHolder=\"Enter E-Mail\" />\n </ng-template>\n </ng-container>\n\n <!-- Phone -->\n <ng-container libColumn=\"phone\">\n <ng-template #cell let-value>{{ value }}</ng-template>\n <ng-template #cellEdit let-control=\"control\">\n <verbena-input name=\"PhoneNumber\" [formControl]=\"control\" placeHolder=\"Enter Phone Number\" />\n </ng-template>\n </ng-container>\n\n <!-- Role -->\n <ng-container libColumn=\"role\">\n <ng-template #cell let-value>{{ facade.getRoleName(value) || 'N/A' }}</ng-template>\n <ng-template #cellEdit let-control=\"control\">\n <verben-drop-down [width]=\"'100%'\" [formControl]=\"control\" placeHolder=\"Select Role\"\n [options]=\"(facade.roles$ | async) ?? []\" optionLabel=\"Name\" optionValue=\"Code\" [filter]=\"true\"\n [showClear]=\"true\"></verben-drop-down>\n </ng-template>\n </ng-container>\n\n <!-- Status -->\n <ng-container libColumn=\"status\">\n <ng-template #cell let-value>\n <lib-user-status-badge [status]=\"value\"></lib-user-status-badge>\n </ng-template>\n <ng-template #cellEdit let-control=\"control\">\n <verben-drop-down [width]=\"'100%'\" [formControl]=\"control\" placeHolder=\"Select Status\" [options]=\"statuses\"\n [filter]=\"false\" [showClear]=\"false\"></verben-drop-down>\n </ng-template>\n </ng-container>\n\n <!-- Actions -->\n <ng-container libColumn=\"actions\">\n <ng-template #cell let-row=\"row\" let-toggleRowEdit=\"toggleRowEdit\">\n <div class=\"flex gap-6\">\n <verben-svg (click)=\"toggleRowEdit()\" icon=\"edit\" [width]=\"15\" [height]=\"15\"\n class=\"cursor-pointer\"></verben-svg>\n <verben-svg (click)=\"onView(row)\" icon=\"eye\" [width]=\"15\" [height]=\"15\" class=\"cursor-pointer\"></verben-svg>\n <verben-svg (click)=\"onDelete(row)\" icon=\"delete\" [width]=\"15\" [height]=\"15\"\n class=\"cursor-pointer\"></verben-svg>\n </div>\n </ng-template>\n <ng-template #cellEdit let-toggleRowEdit=\"toggleRowEdit\">\n <div class=\"flex gap-6\">\n <verben-svg (click)=\"toggleRowEdit()\" icon=\"tick\" [width]=\"15\" [height]=\"15\"\n class=\"cursor-pointer\"></verben-svg>\n <verben-svg (click)=\"toggleRowEdit()\" icon=\"delete\" [width]=\"15\" [height]=\"15\"\n class=\"cursor-pointer\"></verben-svg>\n </div>\n </ng-template>\n </ng-container>\n </lib-data-table>\n\n <div *ngIf=\"users.length === 0 && !isLoading\" class=\"empty-state\">\n <p>No users found</p>\n </div>\n</div>\n", styles: [".table-container{width:100%}.table-container.loading{opacity:.6;pointer-events:none}.empty-state{padding:2rem;text-align:center;color:var(--vbn-color-text-muted)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.DatePipe, name: "date" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: DataTableModule }, { kind: "component", type: i3.DataTableComponent, selector: "lib-data-table", inputs: ["data", "columns", "dataKey", "formGroupConfig", "groupBy", "useVirtualScroll", "virtualScrollItemSize", "styleConfig"], outputs: ["rowEdit", "rowSave", "rowRevert", "rowDelete", "selectionChange"] }, { kind: "directive", type: i3.ColumnDirective, selector: "[libColumn]", inputs: ["libColumn"] }, { kind: "ngmodule", type: SvgModule }, { kind: "component", type: i3.SvgComponent, selector: "verben-svg", inputs: ["icon", "width", "height", "fill", "stroke", "type", "size"] }, { kind: "ngmodule", type: DropDownModule }, { kind: "component", type: i3.DropDownComponent, selector: "verben-drop-down", inputs: ["options", "width", "overlayWidth", "showHorizontalLine", "horizontalLineColor", "optionLabel", "optionSubLabel", "optionValue", "placeholder", "invalidMessage", "errorPosition", "loadMoreCaption", "display", "showClear", "lazyLoad", "selectKey", "styleClass", "group", "multiselect", "filter", "avoidDuplication", "filterBy", "debounceTime", "minChar", "refPageSize", "disabled", "required", "load", "asyncLabel", "search"], outputs: ["optionsChange", "onChange", "onClick", "onClear"] }, { kind: "ngmodule", type: VerbenaInputModule }, { kind: "component", type: i3.VerbenaInputComponent, selector: "verbena-input", inputs: ["disabled", "label", "placeHolder", "required", "svgPosition", "minLength", "maxLength", "type", "bgColor", "border", "borderRadius", "textColor", "value", "labelPosition", "labelColor", "disable", "readOnly", "min", "max", "showBorder", "showErrorMessage", "errorMessageColor", "errorBorderColor", "errorPosition", "svg", "fontSize", "svgWidth", "svgHeight", "svgColor", "capitalization", "inputContainerClass", "inputFieldClass", "passLength", "inputWrapperClass", "passwordToggle", "customErrorMessages", "icon", "textPass"], outputs: ["valueChange"] }, { kind: "component", type: UserStatusBadgeComponent, selector: "lib-user-status-badge", inputs: ["status"] }] });
434
+ }
435
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserManagementTableComponent, decorators: [{
436
+ type: Component,
437
+ args: [{ selector: 'lib-user-management-table', standalone: true, imports: [
438
+ CommonModule,
439
+ ReactiveFormsModule,
440
+ DataTableModule,
441
+ SvgModule,
442
+ DropDownModule,
443
+ VerbenaInputModule,
444
+ UserStatusBadgeComponent,
445
+ ], template: "<div class=\"table-container\" [class.loading]=\"isLoading\">\n <lib-data-table [data]=\"users\" [columns]=\"columns\" [formGroupConfig]=\"formGroupConfig\" dataKey=\"Code\"\n (rowSave)=\"onRowSaved($event)\">\n <!-- Select -->\n <ng-container libColumn=\"select\">\n <ng-template #cell let-isSelected=\"isSelected\" let-toggleRowSelection=\"toggleRowSelection\">\n <input type=\"checkbox\" [checked]=\"isSelected\" (change)=\"toggleRowSelection()\" />\n </ng-template>\n </ng-container>\n\n <!-- Created -->\n <ng-container libColumn=\"createdAt\">\n <ng-template #cell let-value>{{ value | date }}</ng-template>\n </ng-container>\n\n <!-- Mail -->\n <ng-container libColumn=\"mail\">\n <ng-template #cell let-value>{{ value }}</ng-template>\n <ng-template #cellEdit let-control=\"control\">\n <verbena-input name=\"MailAddress\" [formControl]=\"control\" placeHolder=\"Enter E-Mail\" />\n </ng-template>\n </ng-container>\n\n <!-- Phone -->\n <ng-container libColumn=\"phone\">\n <ng-template #cell let-value>{{ value }}</ng-template>\n <ng-template #cellEdit let-control=\"control\">\n <verbena-input name=\"PhoneNumber\" [formControl]=\"control\" placeHolder=\"Enter Phone Number\" />\n </ng-template>\n </ng-container>\n\n <!-- Role -->\n <ng-container libColumn=\"role\">\n <ng-template #cell let-value>{{ facade.getRoleName(value) || 'N/A' }}</ng-template>\n <ng-template #cellEdit let-control=\"control\">\n <verben-drop-down [width]=\"'100%'\" [formControl]=\"control\" placeHolder=\"Select Role\"\n [options]=\"(facade.roles$ | async) ?? []\" optionLabel=\"Name\" optionValue=\"Code\" [filter]=\"true\"\n [showClear]=\"true\"></verben-drop-down>\n </ng-template>\n </ng-container>\n\n <!-- Status -->\n <ng-container libColumn=\"status\">\n <ng-template #cell let-value>\n <lib-user-status-badge [status]=\"value\"></lib-user-status-badge>\n </ng-template>\n <ng-template #cellEdit let-control=\"control\">\n <verben-drop-down [width]=\"'100%'\" [formControl]=\"control\" placeHolder=\"Select Status\" [options]=\"statuses\"\n [filter]=\"false\" [showClear]=\"false\"></verben-drop-down>\n </ng-template>\n </ng-container>\n\n <!-- Actions -->\n <ng-container libColumn=\"actions\">\n <ng-template #cell let-row=\"row\" let-toggleRowEdit=\"toggleRowEdit\">\n <div class=\"flex gap-6\">\n <verben-svg (click)=\"toggleRowEdit()\" icon=\"edit\" [width]=\"15\" [height]=\"15\"\n class=\"cursor-pointer\"></verben-svg>\n <verben-svg (click)=\"onView(row)\" icon=\"eye\" [width]=\"15\" [height]=\"15\" class=\"cursor-pointer\"></verben-svg>\n <verben-svg (click)=\"onDelete(row)\" icon=\"delete\" [width]=\"15\" [height]=\"15\"\n class=\"cursor-pointer\"></verben-svg>\n </div>\n </ng-template>\n <ng-template #cellEdit let-toggleRowEdit=\"toggleRowEdit\">\n <div class=\"flex gap-6\">\n <verben-svg (click)=\"toggleRowEdit()\" icon=\"tick\" [width]=\"15\" [height]=\"15\"\n class=\"cursor-pointer\"></verben-svg>\n <verben-svg (click)=\"toggleRowEdit()\" icon=\"delete\" [width]=\"15\" [height]=\"15\"\n class=\"cursor-pointer\"></verben-svg>\n </div>\n </ng-template>\n </ng-container>\n </lib-data-table>\n\n <div *ngIf=\"users.length === 0 && !isLoading\" class=\"empty-state\">\n <p>No users found</p>\n </div>\n</div>\n", styles: [".table-container{width:100%}.table-container.loading{opacity:.6;pointer-events:none}.empty-state{padding:2rem;text-align:center;color:var(--vbn-color-text-muted)}\n"] }]
446
+ }], ctorParameters: () => [{ type: UserFacade }], propDecorators: { users: [{
447
+ type: Input
448
+ }], columns: [{
449
+ type: Input
450
+ }], isLoading: [{
451
+ type: Input
452
+ }], formGroupConfig: [{
453
+ type: Input
454
+ }], view: [{
455
+ type: Output
456
+ }], delete: [{
457
+ type: Output
458
+ }], saveRow: [{
459
+ type: Output
460
+ }] } });
461
+
462
+ /**
463
+ * User-management page. Lists users in table/card views with inline row editing
464
+ * and a form panel, driven by the base-page facade.
465
+ */
466
+ class UserManagementComponent {
467
+ facade;
468
+ searchDebounceTime = 500;
469
+ pageSize = 20;
470
+ /** Optional role filter, applied as the initial search term. */
471
+ role = '';
472
+ vdv;
473
+ cardDataView;
474
+ destroyRef = inject(DestroyRef);
475
+ constructor(facade) {
476
+ this.facade = facade;
735
477
  }
736
- async postSearch(payload) {
737
- this.utilService.sendBI(true);
738
- const res = await this.server.post(`SearchUsers/0/10/CreatedAt/asc`, payload);
739
- this.utilService.sendBI(false);
740
- if (res instanceof ErrorResponse) {
741
- this.appliedFilters = false;
478
+ ngOnInit() {
479
+ this.facade.applyRuntimeConfig({
480
+ pageSize: this.pageSize,
481
+ searchDebounceTime: this.searchDebounceTime,
482
+ });
483
+ if (this.role) {
484
+ this.facade.setInitialSearch(this.role);
485
+ }
486
+ this.facade.cardSelectionCleared$
487
+ .pipe(takeUntilDestroyed(this.destroyRef))
488
+ .subscribe(() => this.clearCardView());
489
+ this.facade.loadData();
490
+ this.facade.loadRoles();
491
+ this.facade.loadTags();
492
+ }
493
+ clearCardView() {
494
+ const view = this.cardDataView;
495
+ if (!view)
742
496
  return;
743
- }
744
- else {
745
- this.appliedFilters = true;
746
- const response = res;
747
- this.dataFit = response;
748
- this.users = response.Result;
749
- this.cardData = this.formatCardData(this.users);
497
+ view.clearData();
498
+ if (view.rightContent) {
499
+ view.rightContent.parentData = null;
750
500
  }
751
501
  }
752
- onFilterApplied(appliedFilter) {
753
- this.showFilter = false;
754
- if (Array.isArray(appliedFilter)) {
755
- this.selectedFilterTableCount = appliedFilter.length;
756
- console.log(appliedFilter);
757
- const queryParams = appliedFilter
758
- .filter((filter) => filter.checked)
759
- .map((filter) => ({
760
- PropertyName: filter.name,
761
- EntityValue: filter.name === 'Role'
762
- ? this.handleRoleId(filter.value)
763
- : filter.value,
764
- Type: filter.type,
765
- Operator: 'And',
766
- Sign: this.getCondition(filter.condition),
767
- }));
768
- this.postSearch(queryParams);
769
- }
502
+ // ===== Filter / Sort / Search =====
503
+ onFilterApplied(filters) {
504
+ this.facade.applyFilters(filters);
770
505
  }
771
- getCondition(value) {
772
- switch (value) {
773
- case ConditionalOptions.On:
774
- return ConditionOptions.On;
775
- case ConditionalOptions.After:
776
- return ConditionOptions.After;
777
- case ConditionalOptions.Before:
778
- return ConditionOptions.Before;
779
- case ConditionalOptions.NotEqual:
780
- return ConditionOptions.NotEqual;
781
- default:
782
- return undefined; // Explicitly return undefined for invalid cases
783
- }
506
+ onSortApplied(sorts) {
507
+ this.facade.applySorts(sorts);
784
508
  }
785
- onSortUpdated(updatedSorts) {
786
- this.currentSorts = updatedSorts;
509
+ onSearch(term) {
510
+ this.facade.onSearch(term);
787
511
  }
788
- async onSearch(event) {
789
- this.searchTerm = event.value;
790
- this.reset();
791
- if (!this.searchTerm) {
792
- this.clearLogs('CreatedAt', 'asc');
793
- return;
794
- }
795
- this.isLoading = true;
796
- this.utilService.sendBI(true);
797
- try {
798
- const res = await this.server.get(`GetUserWithParam/${this.searchTerm}/${this.skip}/${this.pageSize}/CreatedAt/asc`);
799
- this.utilService.sendBI(false);
800
- if (res instanceof ErrorResponse) {
801
- console.error('Error during search:', res);
802
- this.appliedFilters = false;
803
- }
804
- else {
805
- const response = res;
806
- this.dataFit = response;
807
- this.users = response.Result;
808
- this.cardData = this.formatCardData(this.users);
809
- }
810
- }
811
- catch (error) {
812
- console.error('Search error:', error);
813
- this.appliedFilters = false;
814
- }
815
- finally {
816
- this.isLoading = false;
817
- }
512
+ onColumnsUpdated(columns) {
513
+ this.facade.handleColumnsUpdated(columns);
514
+ }
515
+ onLoadMore() {
516
+ this.facade.loadMore();
818
517
  }
819
- clearLogs(sortValue = 'CreatedAt', order = 'asc') {
820
- this.users = []; // Clear the logs array
821
- this.skip = 0; // Reset the skip value
822
- this.hasMore = true; // Reset the flag to allow fetching more logs
823
- this.appliedFilters = false;
824
- this.fetchUsers(sortValue, order);
825
- }
826
- onViewChange(isGridView) { }
827
- onStateChange(event) {
828
- console.log(`State changed for ${event.key}:`, event.value);
829
- if (event.key === 'create') {
830
- console.log('peace is a boy');
831
- // const newUser = this.newItem()
832
- // if ( newUser && this.cardDataView) {
833
- // this.dataView.toggleView();
834
- // // First reset all selections
835
- // this.cardData.forEach((item) => {
836
- // item.selected = false;
837
- // if (item.children) {
838
- // item.children.forEach((child) => (child.selected = false));
839
- // }
840
- // });
841
- // this.currentData = this.cardDataView.onItemClick(newUser);
842
- // // Force change detection if needed
843
- // // this.changeDetectorRef.detectChanges();
844
- // }
518
+ // ===== Table events =====
519
+ onViewUser(user) {
520
+ this.facade.openForm(user);
521
+ this.vdv.toggleView();
522
+ }
523
+ onDeleteUser(user) {
524
+ const name = `${user.FirstName} ${user.LastName}`.trim() || user.MailAddress;
525
+ if (confirm(`Delete user ${name}?`)) {
526
+ this.facade.deleteUser(user.Id || user.Code);
845
527
  }
846
528
  }
847
- getRoleName(roleId) {
848
- const role = this.Roles.find((role) => role.Code === roleId);
849
- return role ? role.Name : '';
529
+ onSaveRow(user) {
530
+ this.facade.saveUser(user);
531
+ }
532
+ userCardClicked(selectedCard) {
533
+ this.facade.selectCard(selectedCard);
850
534
  }
851
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserManagementComponent, deps: [{ token: i1$1.ActivatedRoute }, { token: UserManagementService }, { token: i3.UserAccessRequestService }, { token: i4.HttpWebRequestService }, { token: i4.UtilService }, { token: i4.EnvironmentService }, { token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
852
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: UserManagementComponent, selector: "lib-user-management", inputs: { searchDebounceTime: "searchDebounceTime", pageSize: "pageSize" }, viewQueries: [{ propertyName: "cardDataView", first: true, predicate: ["vdcv"], descendants: true }, { propertyName: "dataView", first: true, predicate: ["vdv"], descendants: true }, { propertyName: "childComponent", first: true, predicate: UserManagementFormComponent, descendants: true }], ngImport: i0, template: "<div class=\"flex flex-col gap-4 message-log-container\">\n <verben-data-view\n #vdv\n [viewState]=\"{\n isSearch: true,\n isColumn: true,\n isFilter: true,\n isSort: true,\n isExport: true,\n isSelect: true,\n\n isToggle: true\n }\"\n [buttonClass]=\"'my-custom-button-class'\"\n [iconClass]=\"'my-icon-class'\"\n [activeIconClass]=\"'my-active-icon-class'\"\n [selectedColumnCount]=\"selectedColumnCount\"\n [selectedSortCount]=\"selectedSortCount\"\n [selectedFilterTableCount]=\"selectedFilterTableCount\"\n (onSearchChange)=\"onSearch($event)\"\n [searchValue]=\"searchTerm\"\n [showFilterChild]=\"showFilter\"\n (viewChange)=\"onViewChange($event)\"\n (stateChange)=\"onStateChange($event)\"\n [isTableView]=\"false\"\n >\n <div class=\"mt-2\" table-content>\n <lib-data-table\n [data]=\"users\"\n [columns]=\"filteredColumns\"\n [formGroupConfig]=\"formGroupConfig()\"\n [styleConfig]=\"styles\"\n (selectionChange)=\"onSelectionChange($event)\"\n (rowSave)=\"onDataSave($event)\"\n >\n <ng-container libColumn=\"select\">\n <ng-template\n #cell\n let-isSelected=\"isSelected\"\n let-toggleRowSelection=\"toggleRowSelection\"\n >\n <input\n type=\"checkbox\"\n [checked]=\"isSelected\"\n (change)=\"toggleRowSelection()\"\n />\n </ng-template>\n <ng-template\n #header\n let-allRowsSelected=\"allRowsSelected\"\n let-someRowsSelected=\"someRowsSelected\"\n let-toggleAllRows=\"toggleAllRows\"\n >\n <input\n type=\"checkbox\"\n [checked]=\"allRowsSelected()\"\n [indeterminate]=\"someRowsSelected()\"\n (change)=\"toggleAllRows()\"\n />\n </ng-template>\n </ng-container>\n <ng-container libColumn=\"createdAt\">\n <ng-template #cell let-value>\n {{ value | date }}\n </ng-template>\n </ng-container>\n <ng-container libColumn=\"user\">\n <ng-template #cellEdit let-formControl=\"formControl\" let-value>\n <verbena-input\n name=\"FirstName\"\n type=\"text\"\n [formControl]=\"formControl\"\n />\n </ng-template>\n </ng-container>\n <ng-container libColumn=\"mail\">\n <ng-template #cellEdit let-formControl=\"formControl\" let-value>\n <verbena-input\n name=\"MailAddress\"\n type=\"email\"\n [formControl]=\"formControl\"\n />\n </ng-template>\n </ng-container>\n <ng-container libColumn=\"phone\">\n <ng-template #cellEdit let-formControl=\"formControl\" let-value>\n <verbena-input\n name=\"PhoneNumber\"\n type=\"tel\"\n [formControl]=\"formControl\"\n />\n </ng-template>\n </ng-container>\n <ng-container libColumn=\"address\">\n <ng-template #cellEdit let-formControl=\"formControl\" let-value>\n <verbena-input\n name=\"Address\"\n type=\"text\"\n [formControl]=\"formControl\"\n />\n </ng-template>\n </ng-container>\n <ng-container libColumn=\"role\">\n <ng-template #cellEdit let-formControl=\"formControl\" let-value>\n <verben-drop-down\n name=\"Role\"\n styleClass=\"w-full\"\n width=\"100%\"\n [multiselect]=\"false\"\n [filter]=\"true\"\n [showClear]=\"true\"\n placeholder=\"\"\n [(options)]=\"Roles\"\n id=\"role\"\n optionLabel=\"Name\"\n optionValue=\"Code\"\n [formControl]=\"formControl\"\n class=\"form-control\"\n >\n </verben-drop-down>\n </ng-template>\n </ng-container>\n\n <ng-container libColumn=\"actions\">\n <ng-template\n #cell\n let-value\n let-deleteRow=\"deleteRow\"\n let-isEditing=\"isEditing\"\n let-toggleRowEdit=\"toggleRowEdit\"\n let-row=\"row\"\n let-rowIndex=\"rowIndex\"\n >\n <div class=\"flex gap-6\">\n <verben-svg\n (click)=\"toggleRowEdit()\"\n icon=\"edit\"\n [width]=\"15\"\n [height]=\"15\"\n class=\"cursor-pointer\"\n ></verben-svg>\n\n <verben-svg\n icon=\"delete\"\n [width]=\"15\"\n [height]=\"15\"\n (click)=\"deleteRow()\"\n class=\"cursor-pointer\"\n ></verben-svg>\n </div>\n </ng-template>\n <ng-template\n #cellEdit\n let-value\n let-deleteRow=\"deleteRow\"\n let-isEditing=\"isEditing\"\n let-toggleRowEdit=\"toggleRowEdit\"\n let-row=\"row\"\n let-rowIndex=\"rowIndex\"\n >\n <div class=\"flex gap-6\">\n <verben-svg\n (click)=\"toggleRowEdit()\"\n icon=\"tick\"\n [width]=\"15\"\n [height]=\"15\"\n class=\"cursor-pointer\"\n ></verben-svg>\n\n <verben-svg\n icon=\"delete\"\n [width]=\"15\"\n [height]=\"15\"\n (click)=\"toggleRowEdit()\"\n class=\"cursor-pointer\"\n ></verben-svg>\n\n <!-- <verben-svg\n icon=\"cardViewAlt\"\n [width]=\"15\"\n [height]=\"15\"\n class=\"cursor-pointer\"\n (click)=\"goToCardView(value)\"\n ></verben-svg> -->\n </div>\n </ng-template>\n <ng-template #header>\n <strong>Actions</strong>\n </ng-template>\n </ng-container>\n <ng-container libColumn=\"status\">\n <ng-template\n #cell\n let-isEditing=\"isEditing\"\n let-toggleRowEdit=\"toggleRowEdit\"\n let-deleteRow=\"deleteRow\"\n let-value=\"value\"\n >\n <lib-user-status-badge [status]=\"value\"></lib-user-status-badge>\n </ng-template>\n\n <ng-template\n #cellEdit\n let-rowIndex=\"rowIndex\"\n let-formControl=\"formControl\"\n >\n <verben-drop-down\n styleClass=\"w-full\"\n width=\"100%\"\n [multiselect]=\"false\"\n placeholder=\"Set status\"\n [options]=\"statuses\"\n [formControl]=\"formControl\"\n class=\"form-control\"\n >\n </verben-drop-down>\n </ng-template>\n </ng-container>\n </lib-data-table>\n </div>\n <div card-content>\n <verben-card-data-view\n borderRadius=\"12px\"\n (loadMoreClick)=\"loadMore()\"\n #vdcv\n dataId=\"MailAddress\"\n border=\"5px\"\n [cardDataList]=\"cardData\"\n rbgColor=\"#f5f6f9\"\n mg=\"0px\"\n class=\"gap-1\"\n >\n <verben-left-card-data-view class=\"m-0 gap-2\">\n <verben-left-card-data\n #vlcd\n [parent]=\"vdcv\"\n dataId=\"MailAddress\"\n class=\"bg-secondary-100 rounded-xl border-primary border-[1px]\"\n [cardDataList]=\"cardData\"\n >\n <ng-template #card let-item>\n <div (click)=\"currentData = vdcv.onItemClick(item)\" class=\"flex\">\n <verben-svg\n [width]=\"15\"\n [height]=\"15\"\n (click)=\"vlcd.showChildren(item)\"\n [ngClass]=\"vlcd.showToggle(item) ? 'visible' : 'invisible'\"\n class=\"items-center flex cursor-pointer\"\n [icon]=\"item.isChildrenExpanded ? 'minus' : 'plus'\"\n />\n <div\n (click)=\"currentData = vdcv.onItemClick(item)\"\n class=\"flex cursor-pointer w-full bg-secondary rounded-xl\"\n >\n <div\n class=\"w-3 rounded-xl rounded-tr-none rounded-br-none\"\n [ngClass]=\"\n item.selected ? 'bg-primary' : 'bg-secondary-200'\n \"\n ></div>\n <div class=\"flex-1 flex items-end gap-y-2 gap-x-4 p-4\">\n <div class=\"flex-1 space-y-2\">\n <span\n class=\"font-semibold text-[#404040] flex-1 truncate\"\n >{{ item.title }}</span\n >\n\n <p class=\"flex items-center my-1\">\n <label for=\"phone\" class=\"text-[10px] font-light\"\n >Role:</label\n >\n <span id=\"phone\" class=\"text-sm truncate\">{{\n getRoleName(item.data.RoleID)\n }}</span>\n </p>\n </div>\n\n <div class=\"grid gap-y-1\">\n <p class=\"grid\">\n <!-- <label\n for=\"role\"\n class=\"text-[10px] font-light text-[#404040]\"\n >Role</label\n >\n <span id=\"role\" class=\"text-sm font-medium\">{{\n item.data?.Role?.Name\n }}</span> -->\n </p>\n\n <lib-user-status-badge\n [status]=\"item.data.Status\"\n ></lib-user-status-badge>\n </div>\n </div>\n </div>\n </div>\n </ng-template>\n </verben-left-card-data>\n </verben-left-card-data-view>\n\n <verben-right-card-data-view>\n <ng-template #parent>\n <div class=\"bg-secondary-100 py-2 flex flex-col gap-20 px-2\">\n <lib-user-request-form\n [roles]=\"Roles\"\n [tags]=\"Tags()\"\n [currentData]=\"currentData\"\n (switchView)=\"vdv.toggleView()\"\n ></lib-user-request-form>\n <div class=\"flex justify-end bottom-8 left-0 right-0 p-3\">\n <!-- <verbena-button text=\"Delete\" bgColor=\"#999999\" textColor=\"white\"\n border=\"1px solid #999999\" (click)=\"onDelete()\"></verbena-button> -->\n <div class=\"flex gap-3\">\n <verbena-button\n (click)=\"vdv.toggleView()\"\n text=\"Switch To Table\"\n styleType=\"ylw-outline\"\n ></verbena-button>\n <verbena-button\n text=\"Save\"\n bgColor=\"#FFE681\"\n (click)=\"onSave()\"\n textColor=\"#404040\"\n border=\"1px solid #FFE681\"\n >\n <!-- (click)=\"\" -->\n </verbena-button>\n </div>\n </div>\n </div>\n </ng-template>\n </verben-right-card-data-view>\n\n <verben-card-data-view-footer class=\"w-full\">\n <div\n [ngClass]=\"{\n 'flex gap-2 items-center': true,\n 'justify-end': true,\n }\"\n >\n <!-- <verbena-button\n *ngIf=\"!vdcv.hasCurrentItem()\"\n [fontWeight]=\"'bold'\"\n [bgColor]=\"'#8E8D87'\"\n [borderRadius]=\"'4px'\"\n [textColor]=\"'#fff'\"\n [pd]=\"'9.79px 37.28px'\"\n [text]=\"'Delete'\"\n >\n </verbena-button> -->\n <div\n class=\"flex {{\n vdcv.hasCurrentItem() ? 'flex-1' : ''\n }} justify-end items-center gap-5\"\n >\n <span class=\"paginator-text\"\n >{{ cardData.length }} records loaded</span\n >\n <button\n (click)=\"loadMore()\"\n class=\"load-more view-links text-[#3479E9] underline\"\n >\n Load more\n </button>\n </div>\n </div>\n </verben-card-data-view-footer>\n </verben-card-data-view>\n </div>\n <div column-content>\n <verben-visible-column\n (columnsUpdated)=\"onColumnsUpdated($event)\"\n [border]=\"'1px solid rgba(212, 160, 7, 1)'\"\n borderRadius=\"10px\"\n boxShadow=\"2px 2px 2px 0px silver\"\n bgColor=\"white\"\n width=\"400px\"\n textColor=\"black\"\n pd=\"1rem\"\n primaryColor=\"#FFE681\"\n secondaryColor=\"#3479E9\"\n [columns]=\"visibleColumns\"\n [displayedColumns]=\"5\"\n ></verben-visible-column>\n </div>\n <div filter-content>\n <verben-table-filter\n [border]=\"'1px solid rgba(212, 160, 7, 1)'\"\n borderRadius=\"10px\"\n boxShadow=\"2px 2px 2px 0px silver\"\n bgColor=\"white\"\n width=\"420px\"\n textColor=\"black\"\n pd=\"1rem\"\n primaryColor=\"#FFE681\"\n secondaryColor=\"#3479E9\"\n tertiaryColor=\"#404040\"\n [filterOptions]=\"filterArray\"\n [maxFilterLength]=\"3\"\n (filtersApplied)=\"onFilterApplied($event)\"\n ></verben-table-filter>\n </div>\n <div sort-content>\n <verben-sort-table\n (selectedOptions)=\"onSortUpdated($event)\"\n [border]=\"'1px solid rgba(212, 160, 7, 1)'\"\n borderRadius=\"10px\"\n boxShadow=\"2px 2px 2px 0px silver\"\n bgColor=\"white\"\n width=\"400px\"\n textColor=\"black\"\n pd=\"1rem\"\n primaryColor=\"#FFE681\"\n secondaryColor=\"#3479E9\"\n tertiaryColor=\"#404040\"\n [enableDragAndDrop]=\"true\"\n [sortOptions]=\"sortOptions\"\n ></verben-sort-table>\n </div>\n <div export-content>\n <lib-data-xport\n [columns]=\"allColumns\"\n [data]=\"users\"\n >\n </lib-data-xport>\n </div>\n </verben-data-view>\n <div\n *ngIf=\"!vdcv.hasCurrentItem() && this.cardContextHistory.length == 0\"\n class=\"message-log-button-container flex justify-between\"\n ></div>\n\n <div *ngIf=\"vdv.isTableView\" class=\"w-full flex gap-2 justify-end\">\n <!-- <div class=\"message-log-button-container flex justify-between\">\n <verbena-button\n [fontWeight]=\"'bold'\"\n [bgColor]=\"'#8E8D87'\"\n [borderRadius]=\"'4px'\"\n [textColor]=\"'#fff'\"\n [pd]=\"'9.79px 37.28px'\"\n [text]=\"'Delete'\"\n >\n </verbena-button>\n </div> -->\n <div class=\"flex justify-end items-center gap-5\">\n <span class=\"paginator-text\">{{ cardData.length }} records loaded</span>\n <button\n (click)=\"loadMore()\"\n class=\"load-more view-links text-[#3479E9] underline\"\n >\n Load more\n </button>\n </div>\n </div>\n</div>\n", styles: ["*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:currentColor}:before,:after{--tw-content: \"\"}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.visible{visibility:visible}.invisible{visibility:hidden}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.bottom-8{bottom:2rem}.left-0{left:0}.right-0{right:0}.float-right{float:right}.my-2{margin-top:.5rem;margin-bottom:.5rem}.mb-0{margin-bottom:0}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.h-6{height:1.5rem}.h-full{height:100%}.w-10{width:2.5rem}.w-12{width:3rem}.w-3{width:.75rem}.w-4{width:1rem}.w-6{width:1.5rem}.w-full{width:100%}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.gap-6{gap:1.5rem}.space-x-8>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(2rem * var(--tw-space-x-reverse));margin-left:calc(2rem * calc(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(2rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem * var(--tw-space-y-reverse))}.break-all{word-break:break-all}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.rounded-br-none{border-bottom-right-radius:0}.rounded-tr-none{border-top-right-radius:0}.border,.border-\\[1px\\]{border-width:1px}.border-primary{--tw-border-opacity: 1;border-color:rgb(212 160 7 / var(--tw-border-opacity))}.border-secondary-200{border-color:#d7dbe6}.bg-primary{--tw-bg-opacity: 1;background-color:rgb(212 160 7 / var(--tw-bg-opacity))}.bg-secondary{--tw-bg-opacity: 1;background-color:rgb(232 234 241 / var(--tw-bg-opacity))}.bg-secondary-100{--tw-bg-opacity: 1;background-color:rgb(245 246 249 / var(--tw-bg-opacity))}.bg-secondary-200{background-color:#d7dbe6}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pr-1{padding-right:.25rem}.text-\\[10px\\]{font-size:10px}.text-\\[22px\\]{font-size:22px}.text-\\[24px\\]{font-size:24px}.text-\\[2rem\\]{font-size:2rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-\\[500\\]{font-weight:500}.font-bold{font-weight:700}.font-light{font-weight:300}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.leading-6{line-height:1.5rem}.leading-\\[29\\.05px\\]{line-height:29.05px}.leading-\\[33px\\]{line-height:33px}.leading-\\[48px\\]{line-height:48px}.text-\\[\\#333\\]{--tw-text-opacity: 1;color:rgb(51 51 51 / var(--tw-text-opacity))}.text-\\[\\#404040\\]{--tw-text-opacity: 1;color:rgb(64 64 64 / var(--tw-text-opacity))}.text-\\[\\#666666\\]{--tw-text-opacity: 1;color:rgb(102 102 102 / var(--tw-text-opacity))}.text-\\[black\\]{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity))}.text-muted{color:#0009}.underline{text-decoration-line:underline}.outline-none{outline:2px solid transparent;outline-offset:2px}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.master-only-contanier{margin-top:0!important}.scroll-no::-webkit-scrollbar{width:4px}.scroll-no::-webkit-scrollbar-thumb{background:gray}.justify-pp{justify-content:start!important;margin-top:0!important}.toolbar{margin:0!important}@media screen and (max-width: 1024px){.scroll-no{padding:5px}}.view-links{color:#3479e9;cursor:pointer}\n"], dependencies: [{ kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i7.DataTableComponent, selector: "lib-data-table", inputs: ["data", "columns", "dataKey", "formGroupConfig", "groupBy", "useVirtualScroll", "virtualScrollItemSize", "styleConfig"], outputs: ["rowEdit", "rowSave", "rowRevert", "rowDelete", "selectionChange"] }, { kind: "directive", type: i7.ColumnDirective, selector: "[libColumn]", inputs: ["libColumn"] }, { kind: "component", type: i7.SvgComponent, selector: "verben-svg", inputs: ["icon", "width", "height", "fill", "stroke", "type", "size"] }, { kind: "component", type: i7.DataViewComponent, selector: "verben-data-view", inputs: ["buttonClass", "iconClass", "activeIconClass", "columnCustomClass", "filterCustomClass", "sortCustomClass", "extendCustomClass", "exportCustomClass", "selectCustomClass", "importCustomClass", "zIndex", "createCustomClass", "tableIcon", "cardIcon", "cardClass", "tableClass", "searchKey", "searchValue", "viewState", "searchTemplate", "importTemplate", "columnTemplate", "extendTemplate", "filterTemplate", "sortTemplate", "children", "exportTemplate", "createTemplate", "selectedColumnCount", "selectedSortCount", "selectedFilterTableCount", "inputWidth", "milliseconds", "showColumnChild", "showSortChild", "showFilterChild", "showImportChild", "showExportChild", "showExtendChild", "create", "showSelected", "isTableView"], outputs: ["viewChange", "stateChange", "onSearchChange"] }, { kind: "component", type: i7.CardDataViewComponent, selector: "verben-card-data-view", inputs: ["pd", "mg", "lHeight", "rHeight", "rWidth", "lWidth", "textColor", "lbgColor", "rbgColor", "border", "display", "borderRadius", "activeCss", "inActiveCss", "displayAsRow", "cardDataList", "dataId", "totalRecords", "footer", "noOfVisibleChildren", "showEditIcon", "useVirtualScroll", "virtualScrollItemSize", "onItemClick", "onCardChildClick"], outputs: ["editClicked", "loadMoreClick"] }, { kind: "component", type: i7.LeftCardDataComponent, selector: "verben-left-card-data", inputs: ["pd", "mg", "height", "weight", "activeCss", "inActiveCss", "cardDataList", "iconCollapse", "iconExpanded", "parent", "useVirtualScroll", "virtualScrollItemSize", "dataId"] }, { kind: "component", type: i7.LeftCardDataViewComponent, selector: "verben-left-card-data-view", inputs: ["cardDataList"] }, { kind: "component", type: i7.RightCardDataViewComponent, selector: "verben-right-card-data-view", inputs: ["parentData", "chilData", "meth"] }, { kind: "component", type: i7.CardDataViewFooterComponent, selector: "verben-card-data-view-footer" }, { kind: "component", type: i7.SortTableComponent, selector: "verben-sort-table", inputs: ["enableDragAndDrop", "sortOptions", "resetText", "displayedOptions", "propertyText", "showMoreText", "sortButtonText", "pd", "mg", "height", "width", "bgColor", "boxShadow", "textColor", "primaryColor", "secondaryColor", "tertiaryColor", "border", "borderRadius", "selectWidth", "containerHeight"], outputs: ["selectedOptions", "resetSortData"] }, { kind: "component", type: i7.VisibleColumnComponent, selector: "verben-visible-column", inputs: ["columns", "items", "enableDragAndDrop", "displayedColumns", "showMore", "pd", "mg", "height", "width", "bgColor", "boxShadow", "textColor", "primaryColor", "secondaryColor", "tertiaryColor", "border", "borderRadius", "selectWidth", "closeColumn"], outputs: ["columnsUpdated", "resetFilter"] }, { kind: "component", type: i7.TableFilterComponent, selector: "verben-table-filter", inputs: ["filterOptions", "pd", "mg", "height", "width", "bgColor", "boxShadow", "textColor", "primaryColor", "secondaryColor", "tertiaryColor", "border", "borderRadius", "selectWidth", "maxFilterLength", "tooltip"], outputs: ["filtersApplied", "resetSortData"] }, { kind: "component", type: i7.DataXportComponent, selector: "lib-data-xport", inputs: ["data", "columns", "useImportKey", "dataFetchUrl", "dataQueryParameters", "dataQueryFunction"], outputs: ["exportDataEvent", "exportDataRangeEvent"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i7.VerbenaInputComponent, selector: "verbena-input", inputs: ["disabled", "label", "placeHolder", "required", "svgPosition", "minLength", "maxLength", "type", "bgColor", "border", "borderRadius", "textColor", "value", "labelPosition", "labelColor", "disable", "readOnly", "min", "max", "showBorder", "showErrorMessage", "errorMessageColor", "errorBorderColor", "errorPosition", "svg", "fontSize", "svgWidth", "svgHeight", "svgColor", "capitalization", "inputContainerClass", "inputFieldClass", "passLength", "inputWrapperClass", "passwordToggle", "customErrorMessages", "icon", "textPass"], outputs: ["valueChange"] }, { kind: "component", type: i7.VerbenaButtonComponent, selector: "verbena-button", inputs: ["type", "text", "icon", "useIcon", "svgPosition", "iconPosition", "bgColor", "textColor", "border", "borderRadius", "pd", "width", "height", "fontSize", "fontWeight", "disable", "svgSize", "weight", "variant", "styleType", "svg", "svgWidth", "svgHeight", "iconColor", "svgColor", "buttonClass", "buttonTextClass", "isLoading", "spinnerSize", "spinnerColor"] }, { kind: "component", type: i7.DropDownComponent, selector: "verben-drop-down", inputs: ["options", "width", "overlayWidth", "showHorizontalLine", "horizontalLineColor", "optionLabel", "optionSubLabel", "optionValue", "placeholder", "invalidMessage", "errorPosition", "loadMoreCaption", "display", "showClear", "lazyLoad", "selectKey", "styleClass", "group", "multiselect", "filter", "avoidDuplication", "filterBy", "debounceTime", "minChar", "refPageSize", "disabled", "required", "load", "asyncLabel", "search"], outputs: ["optionsChange", "onChange", "onClick", "onClear"] }, { kind: "component", type: UserManagementFormComponent, selector: "lib-user-request-form", inputs: ["currentData", "roles", "tags"], outputs: ["switchView", "onFormSave"] }, { kind: "component", type: UserStatusBadgeComponent, selector: "lib-user-status-badge", inputs: ["status"] }, { kind: "pipe", type: i6.DatePipe, name: "date" }] });
535
+ // ===== Form events =====
536
+ onSaveUser(user) {
537
+ this.facade.saveUser(user);
538
+ this.vdv.toggleView();
539
+ }
540
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserManagementComponent, deps: [{ token: UserFacade }], target: i0.ɵɵFactoryTarget.Component });
541
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: UserManagementComponent, isStandalone: true, selector: "lib-user-management", inputs: { searchDebounceTime: "searchDebounceTime", pageSize: "pageSize", role: "role" }, providers: [UserFacade, UserState, UserService, SearchHandlerService], viewQueries: [{ propertyName: "vdv", first: true, predicate: ["vdv"], descendants: true }, { propertyName: "cardDataView", first: true, predicate: ["vdcv"], descendants: true }], ngImport: i0, template: "<div class=\"user-management-page space-y-8\">\n <verben-data-view #vdv [viewState]=\"{\n isSearch: true,\n isColumn: true,\n isFilter: true,\n isSort: true,\n isExport: true,\n isCreate: false,\n isToggle: true,\n isImport: false,\n }\" [selectedColumnCount]=\"(facade.visibleColumns$ | async)?.length ?? 0\"\n [selectedSortCount]=\"(facade.sorts$ | async)?.length ?? 0\"\n [selectedFilterTableCount]=\"(facade.filters$ | async)?.length ?? 0\"\n (onSearchChange)=\"onSearch($event.value)\">\n\n <!-- Table View -->\n <div table-content>\n <lib-user-management-table [users]=\"(facade.items$ | async) ?? []\"\n [columns]=\"(facade.visibleColumns$ | async) ?? []\" [isLoading]=\"(facade.isLoading$ | async) ?? false\"\n [formGroupConfig]=\"facade.getConfig().formGroupConfig\" (view)=\"onViewUser($event)\"\n (delete)=\"onDeleteUser($event)\" (saveRow)=\"onSaveRow($event)\">\n </lib-user-management-table>\n </div>\n\n <!-- Card View -->\n <div card-content>\n <verben-card-data-view #vdcv [cardDataList]=\"facade.cardData()\" borderRadius=\"12px\" dataId=\"Code\" [border]=\"'5px'\"\n rbgColor=\"var(--vbn-color-surface-alt)\" mg=\"20px\">\n\n <verben-left-card-data-view class=\"space-y-7\">\n <verben-left-card-data #vlcd [parent]=\"vdcv\" dataId=\"Code\"\n class=\"bg-secondary-100 rounded-xl border-primary border-[1px]\" [cardDataList]=\"facade.cardData()\">\n <ng-template #card let-item>\n <div (click)=\"userCardClicked(vdcv.onItemClick(item))\" class=\"cursor-pointer h-[max-content]\">\n <lib-user-management-card [user]=\"item.data\" [selected]=\"item.selected\"></lib-user-management-card>\n </div>\n </ng-template>\n </verben-left-card-data>\n </verben-left-card-data-view>\n\n <verben-right-card-data-view>\n <ng-template #parent>\n <lib-user-management-form [user]=\"facade.currentCardData()?.data ?? facade.emptyUser\"\n [roles]=\"(facade.roles$ | async) ?? []\" [tags]=\"(facade.tags$ | async) ?? []\"\n (save)=\"onSaveUser($event)\" (switchToTable)=\"vdv.toggleView()\">\n </lib-user-management-form>\n </ng-template>\n </verben-right-card-data-view>\n\n <verben-card-data-view-footer class=\"w-full\">\n <div class=\"flex gap-2 items-center justify-end\">\n <div class=\"flex justify-end items-center gap-5\">\n <span class=\"paginator-text\">{{ (facade.items$ | async)?.length }} records loaded</span>\n <button class=\"load-more view-links text-[var(--vbn-color-border-focus)] underline\"\n [disabled]=\"(facade.isLoading$ | async) ?? false\" (click)=\"onLoadMore()\">Load More</button>\n </div>\n </div>\n </verben-card-data-view-footer>\n </verben-card-data-view>\n </div>\n\n <!-- Column Selector -->\n <div column-content>\n <lib-data-columns [columns]=\"facade.getColumns()\" (columnsUpdated)=\"onColumnsUpdated($event)\"></lib-data-columns>\n </div>\n\n <!-- Filter -->\n <div filter-content>\n <lib-data-filter [columns]=\"facade.getColumns()\" [data]=\"(facade.items$ | async) ?? []\"\n (filterApplied)=\"onFilterApplied($event)\"></lib-data-filter>\n </div>\n\n <!-- Sort -->\n <div sort-content>\n <lib-data-sort [columns]=\"facade.getColumns()\" [data]=\"(facade.items$ | async) ?? []\"\n (sortApplied)=\"onSortApplied($event)\"></lib-data-sort>\n </div>\n\n <!-- Export -->\n <div export-content>\n <lib-data-xport [columns]=\"facade.getColumns()\" [data]=\"(facade.items$ | async) ?? []\"></lib-data-xport>\n </div>\n </verben-data-view>\n\n <!-- Table View Load More -->\n <div *ngIf=\"vdv.isTableView\" class=\"flex gap-2 justify-end mt-4 px-4\">\n <div class=\"flex justify-end items-center gap-5\">\n <span class=\"paginator-text\">{{ (facade.items$ | async)?.length }} records loaded</span>\n <button class=\"load-more view-links text-[var(--vbn-color-border-focus)] underline\"\n [disabled]=\"(facade.isLoading$ | async) ?? false\" (click)=\"onLoadMore()\">Load More</button>\n </div>\n </div>\n</div>\n", styles: [".user-management-page{width:100%}.paginator-text{color:var(--vbn-color-text-muted);font-size:.875rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "ngmodule", type: DataViewModule }, { kind: "component", type: i3.DataViewComponent, selector: "verben-data-view", inputs: ["buttonClass", "iconClass", "activeIconClass", "columnCustomClass", "filterCustomClass", "sortCustomClass", "extendCustomClass", "exportCustomClass", "selectCustomClass", "importCustomClass", "zIndex", "createCustomClass", "tableIcon", "cardIcon", "cardClass", "tableClass", "searchKey", "searchValue", "viewState", "searchTemplate", "importTemplate", "columnTemplate", "extendTemplate", "filterTemplate", "sortTemplate", "children", "exportTemplate", "createTemplate", "selectedColumnCount", "selectedSortCount", "selectedFilterTableCount", "inputWidth", "milliseconds", "showColumnChild", "showSortChild", "showFilterChild", "showImportChild", "showExportChild", "showExtendChild", "create", "showSelected", "isTableView"], outputs: ["viewChange", "stateChange", "onSearchChange"] }, { kind: "ngmodule", type: DataColumnsModule }, { kind: "component", type: i3.DataColumnsComponent, selector: "lib-data-columns", inputs: ["columns", "enableDragAndDrop", "maxVisibleItems"], outputs: ["columnsUpdated"] }, { kind: "ngmodule", type: DataFilterModule }, { kind: "component", type: i3.DataFilterComponent, selector: "lib-data-filter", inputs: ["columns", "data"], outputs: ["filterApplied", "resetFilter"] }, { kind: "ngmodule", type: DataSortModule }, { kind: "component", type: i3.DataSortComponent, selector: "lib-data-sort", inputs: ["columns", "data", "enableDragAndDrop"], outputs: ["sortApplied", "resetFilter"] }, { kind: "ngmodule", type: DataXportModule }, { kind: "component", type: i3.DataXportComponent, selector: "lib-data-xport", inputs: ["data", "columns", "useImportKey", "dataFetchUrl", "dataQueryParameters", "dataQueryFunction"], outputs: ["exportDataEvent", "exportDataRangeEvent"] }, { kind: "ngmodule", type: CardDataViewModule }, { kind: "component", type: i3.CardDataViewComponent, selector: "verben-card-data-view", inputs: ["pd", "mg", "lHeight", "rHeight", "rWidth", "lWidth", "textColor", "lbgColor", "rbgColor", "border", "display", "borderRadius", "activeCss", "inActiveCss", "displayAsRow", "cardDataList", "dataId", "totalRecords", "footer", "noOfVisibleChildren", "showEditIcon", "useVirtualScroll", "virtualScrollItemSize", "onItemClick", "onCardChildClick"], outputs: ["editClicked", "loadMoreClick"] }, { kind: "component", type: i3.LeftCardDataComponent, selector: "verben-left-card-data", inputs: ["pd", "mg", "height", "weight", "activeCss", "inActiveCss", "cardDataList", "iconCollapse", "iconExpanded", "parent", "useVirtualScroll", "virtualScrollItemSize", "dataId"] }, { kind: "component", type: i3.LeftCardDataViewComponent, selector: "verben-left-card-data-view", inputs: ["cardDataList"] }, { kind: "component", type: i3.RightCardDataViewComponent, selector: "verben-right-card-data-view", inputs: ["parentData", "chilData", "meth"] }, { kind: "component", type: i3.CardDataViewFooterComponent, selector: "verben-card-data-view-footer" }, { kind: "component", type: UserManagementTableComponent, selector: "lib-user-management-table", inputs: ["users", "columns", "isLoading", "formGroupConfig"], outputs: ["view", "delete", "saveRow"] }, { kind: "component", type: UserManagementCardComponent, selector: "lib-user-management-card", inputs: ["user", "selected"] }, { kind: "component", type: UserManagementFormComponent, selector: "lib-user-management-form", inputs: ["user", "roles", "tags"], outputs: ["save", "switchToTable"] }] });
853
542
  }
854
543
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserManagementComponent, decorators: [{
855
544
  type: Component,
856
- args: [{ selector: 'lib-user-management', template: "<div class=\"flex flex-col gap-4 message-log-container\">\n <verben-data-view\n #vdv\n [viewState]=\"{\n isSearch: true,\n isColumn: true,\n isFilter: true,\n isSort: true,\n isExport: true,\n isSelect: true,\n\n isToggle: true\n }\"\n [buttonClass]=\"'my-custom-button-class'\"\n [iconClass]=\"'my-icon-class'\"\n [activeIconClass]=\"'my-active-icon-class'\"\n [selectedColumnCount]=\"selectedColumnCount\"\n [selectedSortCount]=\"selectedSortCount\"\n [selectedFilterTableCount]=\"selectedFilterTableCount\"\n (onSearchChange)=\"onSearch($event)\"\n [searchValue]=\"searchTerm\"\n [showFilterChild]=\"showFilter\"\n (viewChange)=\"onViewChange($event)\"\n (stateChange)=\"onStateChange($event)\"\n [isTableView]=\"false\"\n >\n <div class=\"mt-2\" table-content>\n <lib-data-table\n [data]=\"users\"\n [columns]=\"filteredColumns\"\n [formGroupConfig]=\"formGroupConfig()\"\n [styleConfig]=\"styles\"\n (selectionChange)=\"onSelectionChange($event)\"\n (rowSave)=\"onDataSave($event)\"\n >\n <ng-container libColumn=\"select\">\n <ng-template\n #cell\n let-isSelected=\"isSelected\"\n let-toggleRowSelection=\"toggleRowSelection\"\n >\n <input\n type=\"checkbox\"\n [checked]=\"isSelected\"\n (change)=\"toggleRowSelection()\"\n />\n </ng-template>\n <ng-template\n #header\n let-allRowsSelected=\"allRowsSelected\"\n let-someRowsSelected=\"someRowsSelected\"\n let-toggleAllRows=\"toggleAllRows\"\n >\n <input\n type=\"checkbox\"\n [checked]=\"allRowsSelected()\"\n [indeterminate]=\"someRowsSelected()\"\n (change)=\"toggleAllRows()\"\n />\n </ng-template>\n </ng-container>\n <ng-container libColumn=\"createdAt\">\n <ng-template #cell let-value>\n {{ value | date }}\n </ng-template>\n </ng-container>\n <ng-container libColumn=\"user\">\n <ng-template #cellEdit let-formControl=\"formControl\" let-value>\n <verbena-input\n name=\"FirstName\"\n type=\"text\"\n [formControl]=\"formControl\"\n />\n </ng-template>\n </ng-container>\n <ng-container libColumn=\"mail\">\n <ng-template #cellEdit let-formControl=\"formControl\" let-value>\n <verbena-input\n name=\"MailAddress\"\n type=\"email\"\n [formControl]=\"formControl\"\n />\n </ng-template>\n </ng-container>\n <ng-container libColumn=\"phone\">\n <ng-template #cellEdit let-formControl=\"formControl\" let-value>\n <verbena-input\n name=\"PhoneNumber\"\n type=\"tel\"\n [formControl]=\"formControl\"\n />\n </ng-template>\n </ng-container>\n <ng-container libColumn=\"address\">\n <ng-template #cellEdit let-formControl=\"formControl\" let-value>\n <verbena-input\n name=\"Address\"\n type=\"text\"\n [formControl]=\"formControl\"\n />\n </ng-template>\n </ng-container>\n <ng-container libColumn=\"role\">\n <ng-template #cellEdit let-formControl=\"formControl\" let-value>\n <verben-drop-down\n name=\"Role\"\n styleClass=\"w-full\"\n width=\"100%\"\n [multiselect]=\"false\"\n [filter]=\"true\"\n [showClear]=\"true\"\n placeholder=\"\"\n [(options)]=\"Roles\"\n id=\"role\"\n optionLabel=\"Name\"\n optionValue=\"Code\"\n [formControl]=\"formControl\"\n class=\"form-control\"\n >\n </verben-drop-down>\n </ng-template>\n </ng-container>\n\n <ng-container libColumn=\"actions\">\n <ng-template\n #cell\n let-value\n let-deleteRow=\"deleteRow\"\n let-isEditing=\"isEditing\"\n let-toggleRowEdit=\"toggleRowEdit\"\n let-row=\"row\"\n let-rowIndex=\"rowIndex\"\n >\n <div class=\"flex gap-6\">\n <verben-svg\n (click)=\"toggleRowEdit()\"\n icon=\"edit\"\n [width]=\"15\"\n [height]=\"15\"\n class=\"cursor-pointer\"\n ></verben-svg>\n\n <verben-svg\n icon=\"delete\"\n [width]=\"15\"\n [height]=\"15\"\n (click)=\"deleteRow()\"\n class=\"cursor-pointer\"\n ></verben-svg>\n </div>\n </ng-template>\n <ng-template\n #cellEdit\n let-value\n let-deleteRow=\"deleteRow\"\n let-isEditing=\"isEditing\"\n let-toggleRowEdit=\"toggleRowEdit\"\n let-row=\"row\"\n let-rowIndex=\"rowIndex\"\n >\n <div class=\"flex gap-6\">\n <verben-svg\n (click)=\"toggleRowEdit()\"\n icon=\"tick\"\n [width]=\"15\"\n [height]=\"15\"\n class=\"cursor-pointer\"\n ></verben-svg>\n\n <verben-svg\n icon=\"delete\"\n [width]=\"15\"\n [height]=\"15\"\n (click)=\"toggleRowEdit()\"\n class=\"cursor-pointer\"\n ></verben-svg>\n\n <!-- <verben-svg\n icon=\"cardViewAlt\"\n [width]=\"15\"\n [height]=\"15\"\n class=\"cursor-pointer\"\n (click)=\"goToCardView(value)\"\n ></verben-svg> -->\n </div>\n </ng-template>\n <ng-template #header>\n <strong>Actions</strong>\n </ng-template>\n </ng-container>\n <ng-container libColumn=\"status\">\n <ng-template\n #cell\n let-isEditing=\"isEditing\"\n let-toggleRowEdit=\"toggleRowEdit\"\n let-deleteRow=\"deleteRow\"\n let-value=\"value\"\n >\n <lib-user-status-badge [status]=\"value\"></lib-user-status-badge>\n </ng-template>\n\n <ng-template\n #cellEdit\n let-rowIndex=\"rowIndex\"\n let-formControl=\"formControl\"\n >\n <verben-drop-down\n styleClass=\"w-full\"\n width=\"100%\"\n [multiselect]=\"false\"\n placeholder=\"Set status\"\n [options]=\"statuses\"\n [formControl]=\"formControl\"\n class=\"form-control\"\n >\n </verben-drop-down>\n </ng-template>\n </ng-container>\n </lib-data-table>\n </div>\n <div card-content>\n <verben-card-data-view\n borderRadius=\"12px\"\n (loadMoreClick)=\"loadMore()\"\n #vdcv\n dataId=\"MailAddress\"\n border=\"5px\"\n [cardDataList]=\"cardData\"\n rbgColor=\"#f5f6f9\"\n mg=\"0px\"\n class=\"gap-1\"\n >\n <verben-left-card-data-view class=\"m-0 gap-2\">\n <verben-left-card-data\n #vlcd\n [parent]=\"vdcv\"\n dataId=\"MailAddress\"\n class=\"bg-secondary-100 rounded-xl border-primary border-[1px]\"\n [cardDataList]=\"cardData\"\n >\n <ng-template #card let-item>\n <div (click)=\"currentData = vdcv.onItemClick(item)\" class=\"flex\">\n <verben-svg\n [width]=\"15\"\n [height]=\"15\"\n (click)=\"vlcd.showChildren(item)\"\n [ngClass]=\"vlcd.showToggle(item) ? 'visible' : 'invisible'\"\n class=\"items-center flex cursor-pointer\"\n [icon]=\"item.isChildrenExpanded ? 'minus' : 'plus'\"\n />\n <div\n (click)=\"currentData = vdcv.onItemClick(item)\"\n class=\"flex cursor-pointer w-full bg-secondary rounded-xl\"\n >\n <div\n class=\"w-3 rounded-xl rounded-tr-none rounded-br-none\"\n [ngClass]=\"\n item.selected ? 'bg-primary' : 'bg-secondary-200'\n \"\n ></div>\n <div class=\"flex-1 flex items-end gap-y-2 gap-x-4 p-4\">\n <div class=\"flex-1 space-y-2\">\n <span\n class=\"font-semibold text-[#404040] flex-1 truncate\"\n >{{ item.title }}</span\n >\n\n <p class=\"flex items-center my-1\">\n <label for=\"phone\" class=\"text-[10px] font-light\"\n >Role:</label\n >\n <span id=\"phone\" class=\"text-sm truncate\">{{\n getRoleName(item.data.RoleID)\n }}</span>\n </p>\n </div>\n\n <div class=\"grid gap-y-1\">\n <p class=\"grid\">\n <!-- <label\n for=\"role\"\n class=\"text-[10px] font-light text-[#404040]\"\n >Role</label\n >\n <span id=\"role\" class=\"text-sm font-medium\">{{\n item.data?.Role?.Name\n }}</span> -->\n </p>\n\n <lib-user-status-badge\n [status]=\"item.data.Status\"\n ></lib-user-status-badge>\n </div>\n </div>\n </div>\n </div>\n </ng-template>\n </verben-left-card-data>\n </verben-left-card-data-view>\n\n <verben-right-card-data-view>\n <ng-template #parent>\n <div class=\"bg-secondary-100 py-2 flex flex-col gap-20 px-2\">\n <lib-user-request-form\n [roles]=\"Roles\"\n [tags]=\"Tags()\"\n [currentData]=\"currentData\"\n (switchView)=\"vdv.toggleView()\"\n ></lib-user-request-form>\n <div class=\"flex justify-end bottom-8 left-0 right-0 p-3\">\n <!-- <verbena-button text=\"Delete\" bgColor=\"#999999\" textColor=\"white\"\n border=\"1px solid #999999\" (click)=\"onDelete()\"></verbena-button> -->\n <div class=\"flex gap-3\">\n <verbena-button\n (click)=\"vdv.toggleView()\"\n text=\"Switch To Table\"\n styleType=\"ylw-outline\"\n ></verbena-button>\n <verbena-button\n text=\"Save\"\n bgColor=\"#FFE681\"\n (click)=\"onSave()\"\n textColor=\"#404040\"\n border=\"1px solid #FFE681\"\n >\n <!-- (click)=\"\" -->\n </verbena-button>\n </div>\n </div>\n </div>\n </ng-template>\n </verben-right-card-data-view>\n\n <verben-card-data-view-footer class=\"w-full\">\n <div\n [ngClass]=\"{\n 'flex gap-2 items-center': true,\n 'justify-end': true,\n }\"\n >\n <!-- <verbena-button\n *ngIf=\"!vdcv.hasCurrentItem()\"\n [fontWeight]=\"'bold'\"\n [bgColor]=\"'#8E8D87'\"\n [borderRadius]=\"'4px'\"\n [textColor]=\"'#fff'\"\n [pd]=\"'9.79px 37.28px'\"\n [text]=\"'Delete'\"\n >\n </verbena-button> -->\n <div\n class=\"flex {{\n vdcv.hasCurrentItem() ? 'flex-1' : ''\n }} justify-end items-center gap-5\"\n >\n <span class=\"paginator-text\"\n >{{ cardData.length }} records loaded</span\n >\n <button\n (click)=\"loadMore()\"\n class=\"load-more view-links text-[#3479E9] underline\"\n >\n Load more\n </button>\n </div>\n </div>\n </verben-card-data-view-footer>\n </verben-card-data-view>\n </div>\n <div column-content>\n <verben-visible-column\n (columnsUpdated)=\"onColumnsUpdated($event)\"\n [border]=\"'1px solid rgba(212, 160, 7, 1)'\"\n borderRadius=\"10px\"\n boxShadow=\"2px 2px 2px 0px silver\"\n bgColor=\"white\"\n width=\"400px\"\n textColor=\"black\"\n pd=\"1rem\"\n primaryColor=\"#FFE681\"\n secondaryColor=\"#3479E9\"\n [columns]=\"visibleColumns\"\n [displayedColumns]=\"5\"\n ></verben-visible-column>\n </div>\n <div filter-content>\n <verben-table-filter\n [border]=\"'1px solid rgba(212, 160, 7, 1)'\"\n borderRadius=\"10px\"\n boxShadow=\"2px 2px 2px 0px silver\"\n bgColor=\"white\"\n width=\"420px\"\n textColor=\"black\"\n pd=\"1rem\"\n primaryColor=\"#FFE681\"\n secondaryColor=\"#3479E9\"\n tertiaryColor=\"#404040\"\n [filterOptions]=\"filterArray\"\n [maxFilterLength]=\"3\"\n (filtersApplied)=\"onFilterApplied($event)\"\n ></verben-table-filter>\n </div>\n <div sort-content>\n <verben-sort-table\n (selectedOptions)=\"onSortUpdated($event)\"\n [border]=\"'1px solid rgba(212, 160, 7, 1)'\"\n borderRadius=\"10px\"\n boxShadow=\"2px 2px 2px 0px silver\"\n bgColor=\"white\"\n width=\"400px\"\n textColor=\"black\"\n pd=\"1rem\"\n primaryColor=\"#FFE681\"\n secondaryColor=\"#3479E9\"\n tertiaryColor=\"#404040\"\n [enableDragAndDrop]=\"true\"\n [sortOptions]=\"sortOptions\"\n ></verben-sort-table>\n </div>\n <div export-content>\n <lib-data-xport\n [columns]=\"allColumns\"\n [data]=\"users\"\n >\n </lib-data-xport>\n </div>\n </verben-data-view>\n <div\n *ngIf=\"!vdcv.hasCurrentItem() && this.cardContextHistory.length == 0\"\n class=\"message-log-button-container flex justify-between\"\n ></div>\n\n <div *ngIf=\"vdv.isTableView\" class=\"w-full flex gap-2 justify-end\">\n <!-- <div class=\"message-log-button-container flex justify-between\">\n <verbena-button\n [fontWeight]=\"'bold'\"\n [bgColor]=\"'#8E8D87'\"\n [borderRadius]=\"'4px'\"\n [textColor]=\"'#fff'\"\n [pd]=\"'9.79px 37.28px'\"\n [text]=\"'Delete'\"\n >\n </verbena-button>\n </div> -->\n <div class=\"flex justify-end items-center gap-5\">\n <span class=\"paginator-text\">{{ cardData.length }} records loaded</span>\n <button\n (click)=\"loadMore()\"\n class=\"load-more view-links text-[#3479E9] underline\"\n >\n Load more\n </button>\n </div>\n </div>\n</div>\n", styles: ["*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:currentColor}:before,:after{--tw-content: \"\"}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.visible{visibility:visible}.invisible{visibility:hidden}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.bottom-8{bottom:2rem}.left-0{left:0}.right-0{right:0}.float-right{float:right}.my-2{margin-top:.5rem;margin-bottom:.5rem}.mb-0{margin-bottom:0}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.h-6{height:1.5rem}.h-full{height:100%}.w-10{width:2.5rem}.w-12{width:3rem}.w-3{width:.75rem}.w-4{width:1rem}.w-6{width:1.5rem}.w-full{width:100%}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.gap-6{gap:1.5rem}.space-x-8>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(2rem * var(--tw-space-x-reverse));margin-left:calc(2rem * calc(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(2rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem * var(--tw-space-y-reverse))}.break-all{word-break:break-all}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.rounded-br-none{border-bottom-right-radius:0}.rounded-tr-none{border-top-right-radius:0}.border,.border-\\[1px\\]{border-width:1px}.border-primary{--tw-border-opacity: 1;border-color:rgb(212 160 7 / var(--tw-border-opacity))}.border-secondary-200{border-color:#d7dbe6}.bg-primary{--tw-bg-opacity: 1;background-color:rgb(212 160 7 / var(--tw-bg-opacity))}.bg-secondary{--tw-bg-opacity: 1;background-color:rgb(232 234 241 / var(--tw-bg-opacity))}.bg-secondary-100{--tw-bg-opacity: 1;background-color:rgb(245 246 249 / var(--tw-bg-opacity))}.bg-secondary-200{background-color:#d7dbe6}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pr-1{padding-right:.25rem}.text-\\[10px\\]{font-size:10px}.text-\\[22px\\]{font-size:22px}.text-\\[24px\\]{font-size:24px}.text-\\[2rem\\]{font-size:2rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-\\[500\\]{font-weight:500}.font-bold{font-weight:700}.font-light{font-weight:300}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.leading-6{line-height:1.5rem}.leading-\\[29\\.05px\\]{line-height:29.05px}.leading-\\[33px\\]{line-height:33px}.leading-\\[48px\\]{line-height:48px}.text-\\[\\#333\\]{--tw-text-opacity: 1;color:rgb(51 51 51 / var(--tw-text-opacity))}.text-\\[\\#404040\\]{--tw-text-opacity: 1;color:rgb(64 64 64 / var(--tw-text-opacity))}.text-\\[\\#666666\\]{--tw-text-opacity: 1;color:rgb(102 102 102 / var(--tw-text-opacity))}.text-\\[black\\]{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity))}.text-muted{color:#0009}.underline{text-decoration-line:underline}.outline-none{outline:2px solid transparent;outline-offset:2px}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.master-only-contanier{margin-top:0!important}.scroll-no::-webkit-scrollbar{width:4px}.scroll-no::-webkit-scrollbar-thumb{background:gray}.justify-pp{justify-content:start!important;margin-top:0!important}.toolbar{margin:0!important}@media screen and (max-width: 1024px){.scroll-no{padding:5px}}.view-links{color:#3479e9;cursor:pointer}\n"] }]
857
- }], ctorParameters: () => [{ type: i1$1.ActivatedRoute }, { type: UserManagementService }, { type: i3.UserAccessRequestService }, { type: i4.HttpWebRequestService }, { type: i4.UtilService }, { type: i4.EnvironmentService }, { type: i1.FormBuilder }], propDecorators: { cardDataView: [{
858
- type: ViewChild,
859
- args: ['vdcv']
860
- }], dataView: [{
861
- type: ViewChild,
862
- args: ['vdv']
863
- }], childComponent: [{
864
- type: ViewChild,
865
- args: [UserManagementFormComponent]
866
- }], searchDebounceTime: [{
545
+ args: [{ selector: 'lib-user-management', standalone: true, imports: [
546
+ CommonModule,
547
+ DataViewModule,
548
+ DataColumnsModule,
549
+ DataFilterModule,
550
+ DataSortModule,
551
+ DataXportModule,
552
+ CardDataViewModule,
553
+ UserManagementTableComponent,
554
+ UserManagementCardComponent,
555
+ UserManagementFormComponent,
556
+ ], providers: [UserFacade, UserState, UserService, SearchHandlerService], template: "<div class=\"user-management-page space-y-8\">\n <verben-data-view #vdv [viewState]=\"{\n isSearch: true,\n isColumn: true,\n isFilter: true,\n isSort: true,\n isExport: true,\n isCreate: false,\n isToggle: true,\n isImport: false,\n }\" [selectedColumnCount]=\"(facade.visibleColumns$ | async)?.length ?? 0\"\n [selectedSortCount]=\"(facade.sorts$ | async)?.length ?? 0\"\n [selectedFilterTableCount]=\"(facade.filters$ | async)?.length ?? 0\"\n (onSearchChange)=\"onSearch($event.value)\">\n\n <!-- Table View -->\n <div table-content>\n <lib-user-management-table [users]=\"(facade.items$ | async) ?? []\"\n [columns]=\"(facade.visibleColumns$ | async) ?? []\" [isLoading]=\"(facade.isLoading$ | async) ?? false\"\n [formGroupConfig]=\"facade.getConfig().formGroupConfig\" (view)=\"onViewUser($event)\"\n (delete)=\"onDeleteUser($event)\" (saveRow)=\"onSaveRow($event)\">\n </lib-user-management-table>\n </div>\n\n <!-- Card View -->\n <div card-content>\n <verben-card-data-view #vdcv [cardDataList]=\"facade.cardData()\" borderRadius=\"12px\" dataId=\"Code\" [border]=\"'5px'\"\n rbgColor=\"var(--vbn-color-surface-alt)\" mg=\"20px\">\n\n <verben-left-card-data-view class=\"space-y-7\">\n <verben-left-card-data #vlcd [parent]=\"vdcv\" dataId=\"Code\"\n class=\"bg-secondary-100 rounded-xl border-primary border-[1px]\" [cardDataList]=\"facade.cardData()\">\n <ng-template #card let-item>\n <div (click)=\"userCardClicked(vdcv.onItemClick(item))\" class=\"cursor-pointer h-[max-content]\">\n <lib-user-management-card [user]=\"item.data\" [selected]=\"item.selected\"></lib-user-management-card>\n </div>\n </ng-template>\n </verben-left-card-data>\n </verben-left-card-data-view>\n\n <verben-right-card-data-view>\n <ng-template #parent>\n <lib-user-management-form [user]=\"facade.currentCardData()?.data ?? facade.emptyUser\"\n [roles]=\"(facade.roles$ | async) ?? []\" [tags]=\"(facade.tags$ | async) ?? []\"\n (save)=\"onSaveUser($event)\" (switchToTable)=\"vdv.toggleView()\">\n </lib-user-management-form>\n </ng-template>\n </verben-right-card-data-view>\n\n <verben-card-data-view-footer class=\"w-full\">\n <div class=\"flex gap-2 items-center justify-end\">\n <div class=\"flex justify-end items-center gap-5\">\n <span class=\"paginator-text\">{{ (facade.items$ | async)?.length }} records loaded</span>\n <button class=\"load-more view-links text-[var(--vbn-color-border-focus)] underline\"\n [disabled]=\"(facade.isLoading$ | async) ?? false\" (click)=\"onLoadMore()\">Load More</button>\n </div>\n </div>\n </verben-card-data-view-footer>\n </verben-card-data-view>\n </div>\n\n <!-- Column Selector -->\n <div column-content>\n <lib-data-columns [columns]=\"facade.getColumns()\" (columnsUpdated)=\"onColumnsUpdated($event)\"></lib-data-columns>\n </div>\n\n <!-- Filter -->\n <div filter-content>\n <lib-data-filter [columns]=\"facade.getColumns()\" [data]=\"(facade.items$ | async) ?? []\"\n (filterApplied)=\"onFilterApplied($event)\"></lib-data-filter>\n </div>\n\n <!-- Sort -->\n <div sort-content>\n <lib-data-sort [columns]=\"facade.getColumns()\" [data]=\"(facade.items$ | async) ?? []\"\n (sortApplied)=\"onSortApplied($event)\"></lib-data-sort>\n </div>\n\n <!-- Export -->\n <div export-content>\n <lib-data-xport [columns]=\"facade.getColumns()\" [data]=\"(facade.items$ | async) ?? []\"></lib-data-xport>\n </div>\n </verben-data-view>\n\n <!-- Table View Load More -->\n <div *ngIf=\"vdv.isTableView\" class=\"flex gap-2 justify-end mt-4 px-4\">\n <div class=\"flex justify-end items-center gap-5\">\n <span class=\"paginator-text\">{{ (facade.items$ | async)?.length }} records loaded</span>\n <button class=\"load-more view-links text-[var(--vbn-color-border-focus)] underline\"\n [disabled]=\"(facade.isLoading$ | async) ?? false\" (click)=\"onLoadMore()\">Load More</button>\n </div>\n </div>\n</div>\n", styles: [".user-management-page{width:100%}.paginator-text{color:var(--vbn-color-text-muted);font-size:.875rem}\n"] }]
557
+ }], ctorParameters: () => [{ type: UserFacade }], propDecorators: { searchDebounceTime: [{
867
558
  type: Input
868
559
  }], pageSize: [{
869
560
  type: Input
561
+ }], role: [{
562
+ type: Input
563
+ }], vdv: [{
564
+ type: ViewChild,
565
+ args: ['vdv']
566
+ }], cardDataView: [{
567
+ type: ViewChild,
568
+ args: ['vdcv']
870
569
  }] } });
871
570
 
571
+ /**
572
+ * Backward-compatibility shim. The components are standalone; this module keeps
573
+ * the historical `LibUserManagementModule` name so existing NgModule-based
574
+ * consumers keep working after the rebuild. It no longer depends on the
575
+ * access-request module.
576
+ */
872
577
  class LibUserManagementModule {
873
578
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibUserManagementModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
874
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: LibUserManagementModule, declarations: [UserManagementComponent,
875
- UserManagementFormComponent,
876
- UserStatusBadgeComponent], imports: [HttpClientModule,
877
- CommonModule,
878
- DataTableModule,
879
- CardModule,
880
- SvgModule,
881
- DataViewModule,
882
- CardDataViewModule,
883
- SortTableModule,
884
- VisibleColumnModule,
885
- TableFilterModule,
886
- DataExportModule,
887
- DataXportModule,
888
- FormsModule,
889
- ReactiveFormsModule,
890
- VerbenaInputModule,
891
- VerbenaButtonModule,
892
- VerbenaBadgeModule,
893
- DropDownModule,
894
- VerbenaSwitchModule,
895
- LibUserRequestApprovalModule], exports: [UserManagementComponent] });
896
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibUserManagementModule, providers: [UserManagementService], imports: [HttpClientModule,
897
- CommonModule,
898
- DataTableModule,
899
- CardModule,
900
- SvgModule,
901
- DataViewModule,
902
- CardDataViewModule,
903
- SortTableModule,
904
- VisibleColumnModule,
905
- TableFilterModule,
906
- DataExportModule,
907
- DataXportModule,
908
- FormsModule,
909
- ReactiveFormsModule,
910
- VerbenaInputModule,
911
- VerbenaButtonModule,
912
- VerbenaBadgeModule,
913
- DropDownModule,
914
- VerbenaSwitchModule,
915
- LibUserRequestApprovalModule] });
579
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: LibUserManagementModule, imports: [UserManagementComponent, UserStatusBadgeComponent], exports: [UserManagementComponent, UserStatusBadgeComponent] });
580
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibUserManagementModule, imports: [UserManagementComponent, UserStatusBadgeComponent] });
916
581
  }
917
582
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibUserManagementModule, decorators: [{
918
583
  type: NgModule,
919
584
  args: [{
920
- declarations: [
921
- UserManagementComponent,
922
- UserManagementFormComponent,
923
- UserStatusBadgeComponent,
924
- ],
925
- imports: [
926
- HttpClientModule,
927
- CommonModule,
928
- DataTableModule,
929
- CardModule,
930
- SvgModule,
931
- DataViewModule,
932
- CardDataViewModule,
933
- SortTableModule,
934
- VisibleColumnModule,
935
- TableFilterModule,
936
- DataExportModule,
937
- DataXportModule,
938
- FormsModule,
939
- ReactiveFormsModule,
940
- VerbenaInputModule,
941
- VerbenaButtonModule,
942
- VerbenaBadgeModule,
943
- DropDownModule,
944
- VerbenaSwitchModule,
945
- LibUserRequestApprovalModule,
946
- // AsyncLabelPipe,
947
- ],
948
- providers: [UserManagementService],
949
- exports: [UserManagementComponent],
585
+ imports: [UserManagementComponent, UserStatusBadgeComponent],
586
+ exports: [UserManagementComponent, UserStatusBadgeComponent],
950
587
  }]
951
588
  }] });
952
589
 
@@ -954,5 +591,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
954
591
  * Generated bundle index. Do not edit.
955
592
  */
956
593
 
957
- export { LibUserManagementModule, UserManagementComponent };
594
+ export { LibUserManagementModule, UserManagementComponent, UserStatusBadgeComponent };
958
595
  //# sourceMappingURL=verben-authentication-ui-src-lib-components-user-management.mjs.map