verben-authentication-ui 1.0.37 → 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.
- package/README.md +23 -1
- package/esm2022/src/lib/base/core/base-data-page.facade.mjs +215 -0
- package/esm2022/src/lib/base/core/base-data-page.service.mjs +103 -0
- package/esm2022/src/lib/base/core/base-data-page.state.mjs +203 -0
- package/esm2022/src/lib/base/handlers/filter-handler.service.mjs +53 -0
- package/esm2022/src/lib/base/handlers/search-handler.service.mjs +31 -0
- package/esm2022/src/lib/base/handlers/sort-handler.service.mjs +49 -0
- package/esm2022/src/lib/base/models/api-payload.mjs +4 -0
- package/esm2022/src/lib/base/models/page-config.interface.mjs +2 -0
- package/esm2022/src/lib/base/public-api.mjs +14 -6
- package/esm2022/src/lib/base/utils/column-helpers.mjs +45 -0
- package/esm2022/src/lib/components/button/button.component.mjs +3 -3
- package/esm2022/src/lib/components/forgot-password/forgot-password.component.mjs +2 -2
- package/esm2022/src/lib/components/mail/mail.component.mjs +3 -3
- package/esm2022/src/lib/components/mail-validation/mail-validation.component.mjs +5 -5
- package/esm2022/src/lib/components/o-auth/o-auth.component.mjs +3 -3
- package/esm2022/src/lib/components/otp-input/otp-input.component.mjs +2 -2
- package/esm2022/src/lib/components/reset-password/reset-password.component.mjs +2 -2
- package/esm2022/src/lib/components/role-control/base-table-style.mjs +6 -6
- package/esm2022/src/lib/components/role-control/role-control.component.mjs +3 -3
- package/esm2022/src/lib/components/sign-in/sign-in.component.mjs +4 -4
- package/esm2022/src/lib/components/sign-up/sign-up.component.mjs +6 -6
- package/esm2022/src/lib/components/sso/base-table-style.mjs +6 -6
- package/esm2022/src/lib/components/sso/sso-form/sso-form.component.mjs +3 -3
- package/esm2022/src/lib/components/sso/sso.component.mjs +3 -3
- package/esm2022/src/lib/components/two-factor-auth-otp/two-factor-auth-otp.component.mjs +4 -4
- package/esm2022/src/lib/components/two-factor-auth-setup/two-factor-auth-setup.component.mjs +5 -5
- package/esm2022/src/lib/components/user-management/public-api.mjs +2 -1
- package/esm2022/src/lib/components/user-management/user-management-card/user-management-card.component.mjs +23 -0
- package/esm2022/src/lib/components/user-management/user-management-form/user-management-form.component.mjs +53 -91
- package/esm2022/src/lib/components/user-management/user-management-table/user-management-table.component.mjs +68 -0
- package/esm2022/src/lib/components/user-management/user-management.component.mjs +98 -509
- package/esm2022/src/lib/components/user-management/user-management.module.mjs +11 -80
- package/esm2022/src/lib/components/user-management/user-status-badge/user-status-badge.component.mjs +8 -6
- package/esm2022/src/lib/components/user-management/user.config.mjs +94 -0
- package/esm2022/src/lib/components/user-management/user.facade.mjs +118 -0
- package/esm2022/src/lib/components/user-management/user.service.mjs +60 -0
- package/esm2022/src/lib/components/user-management/user.state.mjs +33 -0
- package/esm2022/src/lib/components/user-request/user-request.component.mjs +8 -8
- package/esm2022/src/lib/components/user-request-approval/public-api.mjs +2 -2
- package/esm2022/src/lib/components/user-request-approval/user-access-request-status-badge/user-access-request-status-badge.component.mjs +8 -6
- package/esm2022/src/lib/components/user-request-approval/user-access-request.config.mjs +79 -0
- package/esm2022/src/lib/components/user-request-approval/user-access-request.facade.mjs +123 -0
- package/esm2022/src/lib/components/user-request-approval/user-access-request.service.mjs +74 -0
- package/esm2022/src/lib/components/user-request-approval/user-access-request.state.mjs +26 -0
- package/esm2022/src/lib/components/user-request-approval/user-request-approval-card/user-request-approval-card.component.mjs +23 -0
- package/esm2022/src/lib/components/user-request-approval/user-request-approval-form/user-request-approval-form.component.mjs +124 -0
- package/esm2022/src/lib/components/user-request-approval/user-request-approval-table/user-request-approval-table.component.mjs +44 -0
- package/esm2022/src/lib/components/user-request-approval/user-request-approval.component.mjs +101 -273
- package/esm2022/src/lib/components/user-request-approval/user-request-approval.module.mjs +10 -74
- package/fesm2022/verben-authentication-ui-src-lib-base.mjs +596 -214
- package/fesm2022/verben-authentication-ui-src-lib-base.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-button.mjs +2 -2
- package/fesm2022/verben-authentication-ui-src-lib-components-button.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-forgot-password.mjs +2 -2
- package/fesm2022/verben-authentication-ui-src-lib-components-forgot-password.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-mail-validation.mjs +4 -4
- package/fesm2022/verben-authentication-ui-src-lib-components-mail-validation.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-mail.mjs +2 -2
- package/fesm2022/verben-authentication-ui-src-lib-components-mail.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-o-auth.mjs +2 -2
- package/fesm2022/verben-authentication-ui-src-lib-components-o-auth.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-otp-input.mjs +2 -2
- package/fesm2022/verben-authentication-ui-src-lib-components-otp-input.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-reset-password.mjs +2 -2
- package/fesm2022/verben-authentication-ui-src-lib-components-reset-password.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-role-control.mjs +7 -7
- package/fesm2022/verben-authentication-ui-src-lib-components-role-control.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-sign-in.mjs +3 -3
- package/fesm2022/verben-authentication-ui-src-lib-components-sign-in.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-sign-up.mjs +5 -5
- package/fesm2022/verben-authentication-ui-src-lib-components-sign-up.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-sso.mjs +9 -9
- package/fesm2022/verben-authentication-ui-src-lib-components-sso.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-two-factor-auth-otp.mjs +3 -3
- package/fesm2022/verben-authentication-ui-src-lib-components-two-factor-auth-otp.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-two-factor-auth-setup.mjs +4 -4
- package/fesm2022/verben-authentication-ui-src-lib-components-two-factor-auth-setup.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-user-management.mjs +468 -831
- package/fesm2022/verben-authentication-ui-src-lib-components-user-management.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-user-request-approval.mjs +509 -952
- package/fesm2022/verben-authentication-ui-src-lib-components-user-request-approval.mjs.map +1 -1
- package/fesm2022/verben-authentication-ui-src-lib-components-user-request.mjs +7 -7
- package/fesm2022/verben-authentication-ui-src-lib-components-user-request.mjs.map +1 -1
- package/package.json +36 -42
- package/src/lib/base/README.md +99 -0
- package/src/lib/base/core/base-data-page.facade.d.ts +65 -0
- package/src/lib/base/core/base-data-page.service.d.ts +43 -0
- package/src/lib/base/core/base-data-page.state.d.ts +68 -0
- package/src/lib/base/handlers/filter-handler.service.d.ts +13 -0
- package/src/lib/base/handlers/search-handler.service.d.ts +20 -0
- package/src/lib/base/handlers/sort-handler.service.d.ts +13 -0
- package/src/lib/base/models/api-payload.d.ts +2 -0
- package/src/lib/base/models/page-config.interface.d.ts +21 -0
- package/src/lib/base/public-api.d.ts +9 -5
- package/src/lib/base/utils/column-helpers.d.ts +16 -0
- package/src/lib/components/user-management/public-api.d.ts +1 -0
- package/src/lib/components/user-management/user-management-card/user-management-card.component.d.ts +11 -0
- package/src/lib/components/user-management/user-management-form/user-management-form.component.d.ts +12 -14
- package/src/lib/components/user-management/user-management-table/user-management-table.component.d.ts +30 -0
- package/src/lib/components/user-management/user-management.component.d.ts +28 -124
- package/src/lib/components/user-management/user-management.module.d.ts +8 -8
- package/src/lib/components/user-management/user-status-badge/user-status-badge.component.d.ts +1 -1
- package/src/lib/components/user-management/user.config.d.ts +13 -0
- package/src/lib/components/user-management/user.facade.d.ts +42 -0
- package/src/lib/components/user-management/user.service.d.ts +26 -0
- package/src/lib/components/user-management/user.state.d.ts +19 -0
- package/src/lib/components/user-request-approval/public-api.d.ts +1 -1
- package/src/lib/components/user-request-approval/user-access-request-status-badge/user-access-request-status-badge.component.d.ts +1 -1
- package/src/lib/components/user-request-approval/user-access-request.config.d.ts +13 -0
- package/src/lib/components/user-request-approval/user-access-request.facade.d.ts +36 -0
- package/src/lib/components/user-request-approval/user-access-request.service.d.ts +30 -0
- package/src/lib/components/user-request-approval/user-access-request.state.d.ts +16 -0
- package/src/lib/components/user-request-approval/user-request-approval-card/user-request-approval-card.component.d.ts +11 -0
- package/src/lib/components/user-request-approval/user-request-approval-form/user-request-approval-form.component.d.ts +47 -0
- package/src/lib/components/user-request-approval/user-request-approval-table/user-request-approval-table.component.d.ts +20 -0
- package/src/lib/components/user-request-approval/user-request-approval.component.d.ts +29 -68
- package/src/lib/components/user-request-approval/user-request-approval.module.d.ts +7 -6
- package/esm2022/src/lib/base/base-data.component.mjs +0 -80
- package/esm2022/src/lib/base/base-data.facade.mjs +0 -130
- package/esm2022/src/lib/base/base-data.service.mjs +0 -21
- package/esm2022/src/lib/base/base-data.state.mjs +0 -74
- package/esm2022/src/lib/base/models.mjs +0 -2
- package/esm2022/src/lib/components/user-management/base-table-style.mjs +0 -53
- package/esm2022/src/lib/components/user-management/services/user-management.service.mjs +0 -110
- package/esm2022/src/lib/components/user-management/user-management.columns.mjs +0 -53
- package/esm2022/src/lib/components/user-request-approval/access-request.columns.mjs +0 -29
- package/esm2022/src/lib/components/user-request-approval/base-table-style.mjs +0 -53
- package/esm2022/src/lib/components/user-request-approval/facades/user-access-request.facade.mjs +0 -260
- package/esm2022/src/lib/components/user-request-approval/helper.mjs +0 -56
- package/esm2022/src/lib/components/user-request-approval/services/user-access-request.service.mjs +0 -92
- package/esm2022/src/lib/components/user-request-approval/states/user-access-request.state.mjs +0 -92
- package/esm2022/src/lib/components/user-request-approval/user-request-form/user-request-form.component.mjs +0 -105
- package/esm2022/src/lib/components/user-request-process/index.mjs +0 -2
- package/esm2022/src/lib/components/user-request-process/public-api.mjs +0 -3
- package/esm2022/src/lib/components/user-request-process/user-request-process.component.mjs +0 -11
- package/esm2022/src/lib/components/user-request-process/user-request-process.module.mjs +0 -18
- package/esm2022/src/lib/components/user-request-process/verben-authentication-ui-src-lib-components-user-request-process.mjs +0 -5
- package/fesm2022/verben-authentication-ui-src-lib-components-user-request-process.mjs +0 -34
- package/fesm2022/verben-authentication-ui-src-lib-components-user-request-process.mjs.map +0 -1
- package/src/lib/base/base-data.component.d.ts +0 -32
- package/src/lib/base/base-data.facade.d.ts +0 -27
- package/src/lib/base/base-data.service.d.ts +0 -14
- package/src/lib/base/base-data.state.d.ts +0 -28
- package/src/lib/base/models.d.ts +0 -11
- package/src/lib/components/user-management/base-table-style.d.ts +0 -1
- package/src/lib/components/user-management/services/user-management.service.d.ts +0 -44
- package/src/lib/components/user-management/user-management.columns.d.ts +0 -3
- package/src/lib/components/user-request-approval/access-request.columns.d.ts +0 -3
- package/src/lib/components/user-request-approval/base-table-style.d.ts +0 -1
- package/src/lib/components/user-request-approval/facades/user-access-request.facade.d.ts +0 -39
- package/src/lib/components/user-request-approval/helper.d.ts +0 -7
- package/src/lib/components/user-request-approval/services/user-access-request.service.d.ts +0 -64
- package/src/lib/components/user-request-approval/states/user-access-request.state.d.ts +0 -35
- package/src/lib/components/user-request-approval/user-request-form/user-request-form.component.d.ts +0 -34
- package/src/lib/components/user-request-process/index.d.ts +0 -1
- package/src/lib/components/user-request-process/public-api.d.ts +0 -2
- package/src/lib/components/user-request-process/user-request-process.component.d.ts +0 -5
- package/src/lib/components/user-request-process/user-request-process.module.d.ts +0 -7
|
@@ -1,16 +1,69 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import { Injectable, EventEmitter, Component, Input, Output, signal, computed, ChangeDetectionStrategy, ViewChild, NgModule } from '@angular/core';
|
|
3
|
-
import { SearchPropertyValueType, SortDirection, SearchOperator, SearchPropertySign, UserAccessRequestStatus, ErrorResponse } from 'verben-authentication-ui/src/lib/models';
|
|
4
|
-
import * as i4 from 'verben-ng-ui';
|
|
5
|
-
import { DataFilterType, VerbenDialogueModule, DataTableModule, CardModule, SvgModule, DataViewModule, CardDataViewModule, SortTableModule, VisibleColumnModule, TableFilterModule, DataExportModule, DataXportModule, VerbenaInputModule, VerbenaButtonModule, VerbenaBadgeModule, DropDownModule } from 'verben-ng-ui';
|
|
6
|
-
import * as i1 from 'verben-authentication-ui/src/lib/services';
|
|
7
|
-
import { BehaviorSubject, Subject, debounceTime, distinctUntilChanged, takeUntil, lastValueFrom } from 'rxjs';
|
|
8
|
-
import * as i3 from '@angular/common';
|
|
1
|
+
import * as i1 from '@angular/common';
|
|
9
2
|
import { CommonModule } from '@angular/common';
|
|
3
|
+
import * as i0 from '@angular/core';
|
|
4
|
+
import { Component, Input, input, EventEmitter, effect, Output, Injectable, inject, DestroyRef, ViewChild, NgModule } from '@angular/core';
|
|
5
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
6
|
+
import * as i2 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, VerbenaTextareaModule, DropDownModule, VerbenDialogueModule, DataTableModule, SvgModule, DataViewModule, DataColumnsModule, DataFilterModule, DataSortModule, DataXportModule, CardDataViewModule } from 'verben-ng-ui';
|
|
10
|
+
import { UserAccessRequestStatus, ErrorResponse, ObjectState, Status, OAuthType } from 'verben-authentication-ui/src/lib/models';
|
|
10
11
|
import * as i1$1 from '@angular/forms';
|
|
11
|
-
import { Validators,
|
|
12
|
+
import { FormBuilder, Validators, FormControl, ReactiveFormsModule } from '@angular/forms';
|
|
13
|
+
import { BehaviorSubject } from 'rxjs';
|
|
14
|
+
import * as i1$2 from 'verben-authentication-ui/src/lib/services';
|
|
15
|
+
|
|
16
|
+
class UserAccessRequestStatusBadgeComponent {
|
|
17
|
+
status = UserAccessRequestStatus.Pending;
|
|
18
|
+
badgeConfig() {
|
|
19
|
+
switch (this.status) {
|
|
20
|
+
case UserAccessRequestStatus.Approved:
|
|
21
|
+
return { bgColor: 'var(--vbn-color-success-bg)', textColor: 'var(--vbn-color-success)', label: 'Approved' };
|
|
22
|
+
case UserAccessRequestStatus.Declined:
|
|
23
|
+
return { bgColor: 'var(--vbn-color-error-bg)', textColor: 'var(--vbn-color-error)', label: 'Rejected' };
|
|
24
|
+
default:
|
|
25
|
+
return { bgColor: 'var(--vbn-color-text-muted)', textColor: 'var(--vbn-color-border)', label: 'Pending' };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserAccessRequestStatusBadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
29
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: UserAccessRequestStatusBadgeComponent, isStandalone: true, selector: "lib-user-access-request-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: UserAccessRequestStatusBadgeComponent, decorators: [{
|
|
32
|
+
type: Component,
|
|
33
|
+
args: [{ selector: 'lib-user-access-request-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
|
+
}] } });
|
|
12
37
|
|
|
13
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Presentational card for a single access request in the card view.
|
|
40
|
+
*/
|
|
41
|
+
class UserRequestApprovalCardComponent {
|
|
42
|
+
request;
|
|
43
|
+
selected = false;
|
|
44
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserRequestApprovalCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
45
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: UserRequestApprovalCardComponent, isStandalone: true, selector: "lib-user-request-approval-card", inputs: { request: "request", 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 {{ request.FirstName }} {{ request.LastName }}\n </span>\n <p class=\"flex items-center my-1 gap-1\">\n <label class=\"text-[10px] font-light\">Medium:</label>\n <span class=\"text-sm truncate\">{{ request.SignupType }}</span>\n </p>\n </div>\n <div class=\"grid gap-y-1\">\n <lib-user-access-request-status-badge [status]=\"request.RequestStatus\"></lib-user-access-request-status-badge>\n </div>\n </div>\n</div>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: UserAccessRequestStatusBadgeComponent, selector: "lib-user-access-request-status-badge", inputs: ["status"] }] });
|
|
46
|
+
}
|
|
47
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserRequestApprovalCardComponent, decorators: [{
|
|
48
|
+
type: Component,
|
|
49
|
+
args: [{ selector: 'lib-user-request-approval-card', standalone: true, imports: [CommonModule, UserAccessRequestStatusBadgeComponent], 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 {{ request.FirstName }} {{ request.LastName }}\n </span>\n <p class=\"flex items-center my-1 gap-1\">\n <label class=\"text-[10px] font-light\">Medium:</label>\n <span class=\"text-sm truncate\">{{ request.SignupType }}</span>\n </p>\n </div>\n <div class=\"grid gap-y-1\">\n <lib-user-access-request-status-badge [status]=\"request.RequestStatus\"></lib-user-access-request-status-badge>\n </div>\n </div>\n</div>\n", styles: [":host{display:block}\n"] }]
|
|
50
|
+
}], propDecorators: { request: [{
|
|
51
|
+
type: Input
|
|
52
|
+
}], selected: [{
|
|
53
|
+
type: Input
|
|
54
|
+
}] } });
|
|
55
|
+
|
|
56
|
+
const fb = new FormBuilder();
|
|
57
|
+
/**
|
|
58
|
+
* Column definitions for the access-request table.
|
|
59
|
+
* Single source of truth for table, filter, sort, and export.
|
|
60
|
+
*/
|
|
61
|
+
const USER_ACCESS_REQUEST_COLUMNS = [
|
|
62
|
+
{
|
|
63
|
+
id: 'select',
|
|
64
|
+
header: '',
|
|
65
|
+
canExport: false,
|
|
66
|
+
},
|
|
14
67
|
{
|
|
15
68
|
id: 'createdAt',
|
|
16
69
|
header: 'CREATED',
|
|
@@ -29,1030 +82,534 @@ const columns = [
|
|
|
29
82
|
{
|
|
30
83
|
id: 'role',
|
|
31
84
|
header: 'ROLE',
|
|
32
|
-
accessorFn: (row) => row.Role?.Name,
|
|
85
|
+
accessorFn: (row) => row.Role?.Name ?? '',
|
|
33
86
|
},
|
|
34
87
|
{
|
|
35
88
|
id: 'status',
|
|
36
89
|
header: 'STATUS',
|
|
37
90
|
accessorKey: 'RequestStatus',
|
|
38
91
|
},
|
|
39
|
-
{
|
|
92
|
+
{
|
|
93
|
+
id: 'actions',
|
|
94
|
+
header: 'ACTIONS',
|
|
95
|
+
canExport: false,
|
|
96
|
+
},
|
|
40
97
|
];
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
98
|
+
/**
|
|
99
|
+
* Page configuration for access-request approval.
|
|
100
|
+
* Create/import are disabled — this is an approval workflow, not CRUD create.
|
|
101
|
+
*/
|
|
102
|
+
const USER_ACCESS_REQUEST_CONFIG = {
|
|
103
|
+
endpoint: 'UserAccessRequest',
|
|
104
|
+
pageSize: 20,
|
|
105
|
+
columns: USER_ACCESS_REQUEST_COLUMNS,
|
|
106
|
+
cardDataMapper: (request) => ({
|
|
107
|
+
selected: false,
|
|
108
|
+
title: `${request.FirstName} ${request.LastName}`,
|
|
109
|
+
data: request,
|
|
110
|
+
body: [{ title: 'Role', value: request.Role?.Name ?? '' }],
|
|
111
|
+
children: [],
|
|
112
|
+
}),
|
|
113
|
+
searchDebounceTime: 500,
|
|
114
|
+
formGroupConfig: {
|
|
115
|
+
controls: {
|
|
116
|
+
MailAddress: fb.control(''),
|
|
117
|
+
FirstName: fb.control(''),
|
|
118
|
+
LastName: fb.control(''),
|
|
119
|
+
OtherName: fb.control(''),
|
|
120
|
+
PhoneNumber: fb.control(''),
|
|
121
|
+
RoleID: fb.control('', [Validators.required]),
|
|
60
122
|
},
|
|
61
|
-
height: '68px',
|
|
62
|
-
},
|
|
63
|
-
cells: {
|
|
64
|
-
padding: '0.5rem 1rem',
|
|
65
|
-
},
|
|
66
|
-
header: {
|
|
67
|
-
// stickyTop: true,
|
|
68
|
-
// zIndex: 2,
|
|
69
|
-
backgroundColor: '#EFF2FB',
|
|
70
|
-
fontWeight: 'bold',
|
|
71
|
-
textAlign: 'left',
|
|
72
|
-
padding: '12px 16px',
|
|
73
|
-
height: '40px',
|
|
74
|
-
},
|
|
75
|
-
footer: {
|
|
76
|
-
// stickyBottom: true,
|
|
77
|
-
// zIndex: 2,
|
|
78
|
-
padding: '3px',
|
|
79
|
-
},
|
|
80
|
-
// body: {
|
|
81
|
-
// background: '#fff',
|
|
82
|
-
// padding: '4px 5px',
|
|
83
|
-
// textAlign: 'center',
|
|
84
|
-
// },
|
|
85
|
-
// firstColumn: {
|
|
86
|
-
// stickyLeft: true,
|
|
87
|
-
// zIndex: 1,
|
|
88
|
-
// },
|
|
89
|
-
lastColumn: {
|
|
90
|
-
// stickyRight: true,
|
|
91
|
-
// zIndex: 1,
|
|
92
123
|
},
|
|
124
|
+
enableCreate: false,
|
|
125
|
+
enableImport: false,
|
|
126
|
+
enableExport: true,
|
|
127
|
+
enableFilter: true,
|
|
128
|
+
enableSort: true,
|
|
129
|
+
enableSearch: true,
|
|
130
|
+
enableCardView: true,
|
|
131
|
+
enableTableRowEdit: false,
|
|
93
132
|
};
|
|
94
133
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
// RoleID: roles[Math.floor(Math.random() * roles.length)].id,
|
|
112
|
-
// Password: '1234567',
|
|
113
|
-
// ExpireOn: new Date(),
|
|
114
|
-
// IsSeeded: false,
|
|
115
|
-
// OTPExpireOn: new Date(),
|
|
116
|
-
// Tenants: [],
|
|
117
|
-
// SignupType: OAuthType.InApp,
|
|
118
|
-
// CreatedAt: new Date(),
|
|
119
|
-
// UpdatedAt: new Date(),
|
|
120
|
-
// DataState: ObjectState.New,
|
|
121
|
-
// TenantId: `Tenant${id + i}`,
|
|
122
|
-
// Code: '',
|
|
123
|
-
// ServiceName: '',
|
|
124
|
-
// }));
|
|
125
|
-
function randomEnum(anEnum) {
|
|
126
|
-
const enumValues = Object.values(anEnum);
|
|
127
|
-
const randomIndex = Math.floor(Math.random() * enumValues.length);
|
|
128
|
-
return enumValues[randomIndex];
|
|
129
|
-
}
|
|
130
|
-
function convertDataFilterTypeToSearchPropertyValueType(type) {
|
|
131
|
-
switch (type) {
|
|
132
|
-
case DataFilterType.String:
|
|
133
|
-
return SearchPropertyValueType.String;
|
|
134
|
-
case DataFilterType.Integer:
|
|
135
|
-
return SearchPropertyValueType.Int;
|
|
136
|
-
case DataFilterType.Decimal:
|
|
137
|
-
return SearchPropertyValueType.Decimal;
|
|
138
|
-
case DataFilterType.Credit:
|
|
139
|
-
return SearchPropertyValueType.Float;
|
|
140
|
-
case DataFilterType.Date:
|
|
141
|
-
return SearchPropertyValueType.Date;
|
|
142
|
-
case DataFilterType.Bool:
|
|
143
|
-
return SearchPropertyValueType.Bool;
|
|
144
|
-
case DataFilterType.Number:
|
|
145
|
-
return SearchPropertyValueType.Int;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
class UserAccessRequestService {
|
|
150
|
-
httpService;
|
|
151
|
-
constructor(httpService) {
|
|
152
|
-
this.httpService = httpService;
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Get user access requests with pagination and sorting
|
|
156
|
-
* @param skip Number of records to skip
|
|
157
|
-
* @param limit Number of records to take
|
|
158
|
-
* @param sortParam Sort parameter
|
|
159
|
-
* @param sortOrder Sort order ('asc' or 'desc')
|
|
160
|
-
* @returns Promise containing the user access requests
|
|
161
|
-
*/
|
|
162
|
-
getUserAccessRequests(skip, limit, sortParam, sortOrder) {
|
|
163
|
-
const url = `GetUserAccessRequests/${skip}/${limit}/${sortParam}/${sortOrder}`;
|
|
164
|
-
return this.httpService.get(url);
|
|
165
|
-
}
|
|
166
|
-
getRoles() {
|
|
167
|
-
const url = `GetRoles/0/0`;
|
|
168
|
-
return this.httpService.get(url);
|
|
169
|
-
}
|
|
170
|
-
getTags() {
|
|
171
|
-
const url = `GetTags/0/0`;
|
|
172
|
-
return this.httpService.get(url);
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* Get user access requests with additional parameter, pagination and sorting
|
|
176
|
-
* @param param Search parameter
|
|
177
|
-
* @param skip Number of records to skip
|
|
178
|
-
* @param limit Number of records to take
|
|
179
|
-
* @param sortParam Sort parameter
|
|
180
|
-
* @param sortOrder Sort order ('asc' or 'desc')
|
|
181
|
-
* @returns Promise containing the filtered user access requests
|
|
182
|
-
*/
|
|
183
|
-
getUserAccessRequestWithParam(param, skip, limit, sortParam, sortOrder) {
|
|
184
|
-
const url = `GetUserAccessRequestWithParam/${param}/${skip}/${limit}/${sortParam}/${sortOrder}`;
|
|
185
|
-
return this.httpService.get(url);
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* Get user access requests with additional parameter, pagination and sorting
|
|
189
|
-
* @param params Filter parameters
|
|
190
|
-
* @param skip Number of records to skip
|
|
191
|
-
* @param limit Number of records to take
|
|
192
|
-
* @param sortParam Sort parameter
|
|
193
|
-
* @param sortOrder Sort order ('asc' or 'desc')
|
|
194
|
-
* @returns Promise containing the filtered user access requests
|
|
195
|
-
*/
|
|
196
|
-
getUserAccessRequestByFilterParams(params, skip, limit, sortParam, sortOrder) {
|
|
197
|
-
const url = `SearchUserAccessRequest/${skip}/${limit}/${sortParam}/${sortOrder}`;
|
|
198
|
-
return this.httpService.post(url, params);
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* Save multiple user access requests
|
|
202
|
-
* @param requests Array of user access requests to save
|
|
203
|
-
* @returns Promise containing the save operation result
|
|
204
|
-
*/
|
|
205
|
-
saveUserAccessRequests(requests) {
|
|
206
|
-
const url = `SaveUserAccessRequests`;
|
|
207
|
-
return this.httpService.post(url, requests);
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Approve or reject multiple user access requests
|
|
211
|
-
* @param requests Array of user access requests to save
|
|
212
|
-
* @param isApproval True for approval, false for decline
|
|
213
|
-
* @returns Promise containing the save operation result
|
|
214
|
-
*/
|
|
215
|
-
processUserAccessRequests(requests, isApproval) {
|
|
216
|
-
const url = `UserAccessRequestAction/${isApproval}`;
|
|
217
|
-
return this.httpService.post(url, requests);
|
|
218
|
-
}
|
|
134
|
+
/**
|
|
135
|
+
* Form for approving/rejecting a single access request.
|
|
136
|
+
* Identity fields are read-only; the role must be chosen before approval.
|
|
137
|
+
*/
|
|
138
|
+
class UserRequestApprovalFormComponent {
|
|
139
|
+
fb;
|
|
140
|
+
request = input();
|
|
141
|
+
roles = input([]);
|
|
142
|
+
showDelete = input(false);
|
|
143
|
+
approve = new EventEmitter();
|
|
144
|
+
reject = new EventEmitter();
|
|
145
|
+
deleteRequest = new EventEmitter();
|
|
146
|
+
switchToTable = new EventEmitter();
|
|
147
|
+
form;
|
|
148
|
+
showDeleteDialogue = false;
|
|
149
|
+
showRejectDialogue = false;
|
|
219
150
|
/**
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
* @returns Observable containing the delete operation result
|
|
151
|
+
* Rejection reason. Deliberately outside `form` — that group's validity gates
|
|
152
|
+
* Approve, and a required comment there would gate Approve too.
|
|
223
153
|
*/
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
updating$ = new BehaviorSubject(false);
|
|
240
|
-
requests$ = new BehaviorSubject([]);
|
|
241
|
-
roles$ = new BehaviorSubject([]);
|
|
242
|
-
searchTerm$ = new BehaviorSubject('');
|
|
243
|
-
queryParams$ = new BehaviorSubject({
|
|
244
|
-
skip: 0,
|
|
245
|
-
limit: 20,
|
|
246
|
-
sortParam: 'CreatedAt',
|
|
247
|
-
sortOrder: SortDirection.Asc,
|
|
248
|
-
});
|
|
249
|
-
filterParams$ = new BehaviorSubject([]);
|
|
250
|
-
isUpdating$() {
|
|
251
|
-
return this.updating$.asObservable();
|
|
252
|
-
}
|
|
253
|
-
setUpdating(isUpdating) {
|
|
254
|
-
this.updating$.next(isUpdating);
|
|
255
|
-
}
|
|
256
|
-
getRequests$() {
|
|
257
|
-
return this.requests$.asObservable();
|
|
258
|
-
}
|
|
259
|
-
setRequests(requests) {
|
|
260
|
-
this.requests$.next(requests);
|
|
261
|
-
}
|
|
262
|
-
getFilterParams$() {
|
|
263
|
-
return this.filterParams$.asObservable();
|
|
264
|
-
}
|
|
265
|
-
setFilterParams(params) {
|
|
266
|
-
this.filterParams$.next(params);
|
|
267
|
-
}
|
|
268
|
-
getRoles$() {
|
|
269
|
-
return this.roles$.asObservable();
|
|
270
|
-
}
|
|
271
|
-
setRoles(roles) {
|
|
272
|
-
this.roles$.next(roles);
|
|
273
|
-
}
|
|
274
|
-
appendRequests(newRequests) {
|
|
275
|
-
const currentRequests = this.requests$.getValue();
|
|
276
|
-
this.requests$.next([...currentRequests, ...newRequests]);
|
|
277
|
-
}
|
|
278
|
-
getSearchTerm$() {
|
|
279
|
-
return this.searchTerm$.asObservable();
|
|
280
|
-
}
|
|
281
|
-
getSearchTermValue() {
|
|
282
|
-
return this.searchTerm$.getValue();
|
|
283
|
-
}
|
|
284
|
-
setSearchTerm(term) {
|
|
285
|
-
this.searchTerm$.next(term);
|
|
286
|
-
}
|
|
287
|
-
getQueryParams$() {
|
|
288
|
-
return this.queryParams$.asObservable();
|
|
289
|
-
}
|
|
290
|
-
getQueryParamsValue() {
|
|
291
|
-
return this.queryParams$.getValue();
|
|
292
|
-
}
|
|
293
|
-
updateQueryParams(params) {
|
|
294
|
-
this.queryParams$.next({ ...this.queryParams$.getValue(), ...params });
|
|
295
|
-
}
|
|
296
|
-
resetPagination() {
|
|
297
|
-
const currentParams = this.queryParams$.getValue();
|
|
298
|
-
this.queryParams$.next({ ...currentParams, skip: 0 });
|
|
299
|
-
}
|
|
300
|
-
addRequest(request) {
|
|
301
|
-
const currentValue = this.requests$.getValue();
|
|
302
|
-
this.requests$.next([...currentValue, request]);
|
|
303
|
-
}
|
|
304
|
-
updateRequest(updatedRequest) {
|
|
305
|
-
const requests = this.requests$.getValue();
|
|
306
|
-
const index = requests.findIndex((r) => r.Code === updatedRequest.Code);
|
|
307
|
-
if (index !== -1) {
|
|
308
|
-
requests[index] = updatedRequest;
|
|
309
|
-
this.requests$.next([...requests]);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
removeRequest(requestId) {
|
|
313
|
-
const currentValue = this.requests$.getValue();
|
|
314
|
-
this.requests$.next(currentValue.filter((r) => r.Id !== requestId));
|
|
315
|
-
}
|
|
316
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserAccessRequestState, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
317
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserAccessRequestState, providedIn: 'root' });
|
|
318
|
-
}
|
|
319
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserAccessRequestState, decorators: [{
|
|
320
|
-
type: Injectable,
|
|
321
|
-
args: [{
|
|
322
|
-
providedIn: 'root',
|
|
323
|
-
}]
|
|
324
|
-
}] });
|
|
325
|
-
|
|
326
|
-
class UserAccessRequestFacade {
|
|
327
|
-
userAccessRequestService;
|
|
328
|
-
userAccessRequestState;
|
|
329
|
-
utilService;
|
|
330
|
-
searchSubject = new Subject();
|
|
331
|
-
destroy$ = new Subject();
|
|
332
|
-
constructor(userAccessRequestService, userAccessRequestState, utilService) {
|
|
333
|
-
this.userAccessRequestService = userAccessRequestService;
|
|
334
|
-
this.userAccessRequestState = userAccessRequestState;
|
|
335
|
-
this.utilService = utilService;
|
|
336
|
-
// Set up debounced search handling
|
|
337
|
-
this.searchSubject
|
|
338
|
-
.pipe(debounceTime(1000), distinctUntilChanged(), takeUntil(this.destroy$))
|
|
339
|
-
.subscribe((searchTerm) => {
|
|
340
|
-
this.handleSearch(searchTerm);
|
|
341
|
-
});
|
|
342
|
-
this.isUpdating$().subscribe((loading) => {
|
|
343
|
-
this.utilService.sendBI(loading);
|
|
344
|
-
});
|
|
345
|
-
this.getFilterParams$().subscribe((params) => {
|
|
346
|
-
if (params.length) {
|
|
347
|
-
}
|
|
348
|
-
else {
|
|
349
|
-
this.loadRequests();
|
|
154
|
+
rejectComment = new FormControl('', [Validators.required]);
|
|
155
|
+
constructor(fb) {
|
|
156
|
+
this.fb = fb;
|
|
157
|
+
this.form = this.fb.group(USER_ACCESS_REQUEST_CONFIG.formGroupConfig.controls);
|
|
158
|
+
effect(() => {
|
|
159
|
+
const request = this.request();
|
|
160
|
+
if (request && this.form) {
|
|
161
|
+
this.form.patchValue({
|
|
162
|
+
MailAddress: request.MailAddress || '',
|
|
163
|
+
FirstName: request.FirstName || '',
|
|
164
|
+
LastName: request.LastName || '',
|
|
165
|
+
OtherName: request.OtherName || '',
|
|
166
|
+
PhoneNumber: request.PhoneNumber || '',
|
|
167
|
+
RoleID: request.RoleID || '',
|
|
168
|
+
});
|
|
350
169
|
}
|
|
351
170
|
});
|
|
352
171
|
}
|
|
353
|
-
|
|
354
|
-
this.
|
|
355
|
-
this.destroy$.complete();
|
|
172
|
+
isPending() {
|
|
173
|
+
return this.request()?.RequestStatus === UserAccessRequestStatus.Pending;
|
|
356
174
|
}
|
|
357
|
-
|
|
358
|
-
return this.
|
|
175
|
+
canProcess() {
|
|
176
|
+
return this.isPending() && this.form.valid;
|
|
359
177
|
}
|
|
360
|
-
|
|
361
|
-
return this.
|
|
178
|
+
canReject() {
|
|
179
|
+
return this.isPending();
|
|
362
180
|
}
|
|
363
|
-
|
|
364
|
-
return this.
|
|
365
|
-
}
|
|
366
|
-
getRoles$() {
|
|
367
|
-
return this.userAccessRequestState.getRoles$();
|
|
368
|
-
}
|
|
369
|
-
getQueryParams$() {
|
|
370
|
-
return this.userAccessRequestState.getQueryParams$();
|
|
371
|
-
}
|
|
372
|
-
getSearchTerm$() {
|
|
373
|
-
return this.userAccessRequestState.getSearchTerm$();
|
|
374
|
-
}
|
|
375
|
-
// Search handling
|
|
376
|
-
search(term) {
|
|
377
|
-
this.searchSubject.next(term);
|
|
378
|
-
}
|
|
379
|
-
async handleSearch(searchTerm) {
|
|
380
|
-
this.userAccessRequestState.setSearchTerm(searchTerm);
|
|
381
|
-
this.userAccessRequestState.resetPagination();
|
|
382
|
-
try {
|
|
383
|
-
this.userAccessRequestState.setUpdating(true);
|
|
384
|
-
if (searchTerm.trim()) {
|
|
385
|
-
await this.loadRequestsWithParam(searchTerm);
|
|
386
|
-
}
|
|
387
|
-
else {
|
|
388
|
-
await this.loadRequests();
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
catch (error) {
|
|
392
|
-
console.error('Search failed:', error);
|
|
393
|
-
throw error;
|
|
394
|
-
}
|
|
395
|
-
finally {
|
|
396
|
-
this.userAccessRequestState.setUpdating(false);
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
async filter(filterParams) {
|
|
400
|
-
this.userAccessRequestState.resetPagination();
|
|
401
|
-
this.userAccessRequestState.setFilterParams(filterParams);
|
|
402
|
-
}
|
|
403
|
-
// Load more handling
|
|
404
|
-
async loadMore() {
|
|
405
|
-
try {
|
|
406
|
-
this.userAccessRequestState.setUpdating(true);
|
|
407
|
-
const currentParams = this.userAccessRequestState.getQueryParamsValue();
|
|
408
|
-
const searchTerm = this.userAccessRequestState.getSearchTermValue();
|
|
409
|
-
// Update skip value
|
|
410
|
-
const newSkip = currentParams.skip + currentParams.limit;
|
|
411
|
-
this.userAccessRequestState.updateQueryParams({ skip: newSkip });
|
|
412
|
-
// Load and append data
|
|
413
|
-
const response = searchTerm
|
|
414
|
-
? await this.userAccessRequestService.getUserAccessRequestWithParam(searchTerm, newSkip, currentParams.limit, currentParams.sortParam || 'createdDate', currentParams.sortOrder)
|
|
415
|
-
: await this.userAccessRequestService.getUserAccessRequests(newSkip, currentParams.limit, currentParams.sortParam || 'createdDate', currentParams.sortOrder);
|
|
416
|
-
this.userAccessRequestState.appendRequests(response.Result);
|
|
417
|
-
}
|
|
418
|
-
catch (error) {
|
|
419
|
-
console.error('Load more failed:', error);
|
|
420
|
-
throw error;
|
|
421
|
-
}
|
|
422
|
-
finally {
|
|
423
|
-
this.userAccessRequestState.setUpdating(false);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
async loadRequests() {
|
|
427
|
-
try {
|
|
428
|
-
this.userAccessRequestState.setUpdating(true);
|
|
429
|
-
const params = this.userAccessRequestState.getQueryParamsValue();
|
|
430
|
-
const requests = await this.userAccessRequestService.getUserAccessRequests(params.skip, params.limit, params.sortParam || 'createdDate', params.sortOrder);
|
|
431
|
-
this.userAccessRequestState.setRequests(requests.Result);
|
|
432
|
-
}
|
|
433
|
-
catch (error) {
|
|
434
|
-
console.error('Failed to load requests:', error);
|
|
435
|
-
throw error;
|
|
436
|
-
}
|
|
437
|
-
finally {
|
|
438
|
-
this.userAccessRequestState.setUpdating(false);
|
|
439
|
-
}
|
|
181
|
+
canDelete() {
|
|
182
|
+
return this.showDelete() && this.isPending();
|
|
440
183
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
const requests = await this.userAccessRequestService.getRoles();
|
|
446
|
-
this.userAccessRequestState.setRoles(requests.Result);
|
|
447
|
-
}
|
|
448
|
-
catch (error) {
|
|
449
|
-
console.error('Failed to load requests:', error);
|
|
450
|
-
throw error;
|
|
451
|
-
}
|
|
452
|
-
finally {
|
|
453
|
-
// this.userAccessRequestState.setUpdating(false);
|
|
184
|
+
onApprove() {
|
|
185
|
+
const request = this.request();
|
|
186
|
+
if (request && this.canProcess()) {
|
|
187
|
+
this.approve.emit({ request, roleId: this.form.get('RoleID')?.value });
|
|
454
188
|
}
|
|
455
189
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
const requests = await this.userAccessRequestService.getUserAccessRequestWithParam(param, params.skip, params.limit, params.sortParam || 'createdDate', params.sortOrder);
|
|
461
|
-
this.userAccessRequestState.setRequests(requests.Result);
|
|
462
|
-
}
|
|
463
|
-
catch (error) {
|
|
464
|
-
console.error('Failed to load requests with param:', error);
|
|
465
|
-
throw error;
|
|
466
|
-
}
|
|
467
|
-
finally {
|
|
468
|
-
this.userAccessRequestState.setUpdating(false);
|
|
190
|
+
onDelete() {
|
|
191
|
+
const request = this.request();
|
|
192
|
+
if (request) {
|
|
193
|
+
this.deleteRequest.emit(request);
|
|
469
194
|
}
|
|
195
|
+
this.closeDeleteDialogue();
|
|
470
196
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
this.userAccessRequestState.setUpdating(true);
|
|
474
|
-
const params = this.userAccessRequestState.getQueryParamsValue();
|
|
475
|
-
const requests = await this.userAccessRequestService.getUserAccessRequestByFilterParams(filterParams.map((filter) => ({
|
|
476
|
-
PropertyName: filter.name,
|
|
477
|
-
EntityValue: filter.value,
|
|
478
|
-
type: convertDataFilterTypeToSearchPropertyValueType(filter.type),
|
|
479
|
-
Operator: SearchOperator.And,
|
|
480
|
-
Sign: SearchPropertySign.EQ,
|
|
481
|
-
})), params.skip, params.limit, params.sortParam || 'createdDate', params.sortOrder);
|
|
482
|
-
this.userAccessRequestState.setRequests(requests.Result);
|
|
483
|
-
}
|
|
484
|
-
catch (error) {
|
|
485
|
-
console.error('Failed to load requests with param:', error);
|
|
486
|
-
throw error;
|
|
487
|
-
}
|
|
488
|
-
finally {
|
|
489
|
-
this.userAccessRequestState.setUpdating(false);
|
|
490
|
-
}
|
|
197
|
+
toggleDeleteDialogue() {
|
|
198
|
+
this.showDeleteDialogue = !this.showDeleteDialogue;
|
|
491
199
|
}
|
|
492
|
-
|
|
493
|
-
this.
|
|
494
|
-
this.loadRequests();
|
|
200
|
+
closeDeleteDialogue() {
|
|
201
|
+
this.showDeleteDialogue = false;
|
|
495
202
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
}
|
|
504
|
-
catch (error) {
|
|
505
|
-
console.error('Failed to add request:', error);
|
|
506
|
-
this.userAccessRequestState.removeRequest(request.Id);
|
|
507
|
-
throw error;
|
|
508
|
-
}
|
|
509
|
-
finally {
|
|
510
|
-
this.userAccessRequestState.setUpdating(false);
|
|
511
|
-
}
|
|
203
|
+
// ===== Reject (requires a reason) =====
|
|
204
|
+
openRejectDialogue() {
|
|
205
|
+
if (!this.canReject())
|
|
206
|
+
return;
|
|
207
|
+
this.rejectComment.setValue('');
|
|
208
|
+
this.rejectComment.markAsUntouched();
|
|
209
|
+
this.showRejectDialogue = true;
|
|
512
210
|
}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
this.userAccessRequestState.setUpdating(true);
|
|
516
|
-
await this.userAccessRequestService.saveUserAccessRequests([request]);
|
|
517
|
-
this.userAccessRequestState.updateRequest(request);
|
|
518
|
-
this.utilService.showSuccess('Request updated successfully');
|
|
519
|
-
}
|
|
520
|
-
catch (error) {
|
|
521
|
-
console.error('Failed to update request:', error);
|
|
522
|
-
throw error;
|
|
523
|
-
}
|
|
524
|
-
finally {
|
|
525
|
-
this.userAccessRequestState.setUpdating(false);
|
|
526
|
-
}
|
|
211
|
+
closeRejectDialogue() {
|
|
212
|
+
this.showRejectDialogue = false;
|
|
527
213
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
this.userAccessRequestState.setUpdating(true);
|
|
531
|
-
await lastValueFrom(this.userAccessRequestService.deleteUserAccessRequests([requestId]));
|
|
532
|
-
this.userAccessRequestState.removeRequest(requestId);
|
|
533
|
-
}
|
|
534
|
-
catch (error) {
|
|
535
|
-
console.error('Failed to delete request:', error);
|
|
536
|
-
throw error;
|
|
537
|
-
}
|
|
538
|
-
finally {
|
|
539
|
-
this.userAccessRequestState.setUpdating(false);
|
|
540
|
-
}
|
|
214
|
+
canConfirmReject() {
|
|
215
|
+
return !!this.rejectComment.value?.trim();
|
|
541
216
|
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
if (data) {
|
|
549
|
-
this.userAccessRequestState.updateRequest(data);
|
|
550
|
-
this.utilService.showSuccess('Request approved successfully');
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
catch (error) {
|
|
554
|
-
console.error('Failed to update request:', error);
|
|
555
|
-
throw error;
|
|
556
|
-
}
|
|
557
|
-
finally {
|
|
558
|
-
this.userAccessRequestState.setUpdating(false);
|
|
559
|
-
}
|
|
217
|
+
confirmReject() {
|
|
218
|
+
const request = this.request();
|
|
219
|
+
if (!request || !this.canReject() || !this.canConfirmReject())
|
|
220
|
+
return;
|
|
221
|
+
this.reject.emit({ request, comment: this.rejectComment.value.trim() });
|
|
222
|
+
this.closeRejectDialogue();
|
|
560
223
|
}
|
|
561
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type:
|
|
562
|
-
static
|
|
224
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserRequestApprovalFormComponent, deps: [{ token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
|
|
225
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.13", type: UserRequestApprovalFormComponent, isStandalone: true, selector: "lib-user-request-approval-form", inputs: { request: { classPropertyName: "request", publicName: "request", isSignal: true, isRequired: false, transformFunction: null }, roles: { classPropertyName: "roles", publicName: "roles", isSignal: true, isRequired: false, transformFunction: null }, showDelete: { classPropertyName: "showDelete", publicName: "showDelete", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { approve: "approve", reject: "reject", deleteRequest: "deleteRequest", switchToTable: "switchToTable" }, 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 name=\"MailAddress\" label=\"Mail Address:\" formControlName=\"MailAddress\" [readOnly]=\"true\" />\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=\"Other Name:\" name=\"OtherName\" type=\"text\" formControlName=\"OtherName\" [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\">\n </verben-drop-down>\n </div>\n\n <!-- buttons -->\n <div class=\"flex justify-between my-2 overflow-auto\">\n <div class=\"flex gap-2\">\n <verbena-button (click)=\"switchToTable.emit()\" text=\"Switch To Table\" styleType=\"ylw-outline\"></verbena-button>\n\n <verbena-button *ngIf=\"showDelete()\" width=\"114px\" height=\"39px\" (click)=\"toggleDeleteDialogue()\" text=\"Delete\"\n styleType=\"danger\" borderRadius=\"10px\" [disable]=\"!canDelete()\"></verbena-button>\n </div>\n\n <div class=\"flex gap-2\">\n <verbena-button width=\"114px\" height=\"39px\" text=\"Reject\" styleType=\"danger\" borderRadius=\"10px\"\n (click)=\"openRejectDialogue()\" [disable]=\"!canReject()\"></verbena-button>\n\n <verbena-button (click)=\"onApprove()\" text=\"Approve\" bgColor=\"var(--vbn-color-success)\" textColor=\"white\"\n border=\"1px solid var(--vbn-color-success)\" borderRadius=\"10px\" pd=\"10px 20px\" width=\"114px\" height=\"39px\"\n [disable]=\"!canProcess()\"></verbena-button>\n </div>\n </div>\n</form>\n\n<verben-dialogue [showCloseIcon]=\"false\" [dismissOutsideClick]=\"false\" [closeOnEscape]=\"true\" [size]=\"'medium'\"\n [mode]=\"'dialogue'\" [customClass]=\"'show-revert-dialogue'\" [disableFooter]=\"true\" [isVisible]=\"showDeleteDialogue\"\n [bodyTemplate]=\"deleteBodyTemplate\" (closeModal)=\"closeDeleteDialogue()\">\n <ng-template #deleteBodyTemplate>\n <div class=\"dialog-body flex flex-col gap-4\">\n <div class=\"header font-bold text-2xl\">Delete User Request</div>\n <div class=\"form-container-dialogue flex flex-col gap-2\">\n Are you sure you want to proceed?\n </div>\n <div class=\"dialog-button-container flex gap-2\">\n <div class=\"flex-1\">\n <verbena-button width=\"100%\" [fontWeight]=\"'bold'\" [bgColor]=\"'var(--vbn-color-surface)'\"\n [borderRadius]=\"'4px'\" [textColor]=\"'var(--vbn-color-text)'\" [border]=\"'1px solid var(--vbn-color-text)'\"\n [text]=\"'Close'\" (click)=\"closeDeleteDialogue()\">\n </verbena-button>\n </div>\n <div class=\"flex-1\">\n <verbena-button width=\"100%\" class=\"verben-primary-button\" [text]=\"'Proceed'\" (click)=\"onDelete()\">\n </verbena-button>\n </div>\n </div>\n </div>\n </ng-template>\n</verben-dialogue>\n\n<verben-dialogue [showCloseIcon]=\"false\" [dismissOutsideClick]=\"false\" [closeOnEscape]=\"true\" [size]=\"'medium'\"\n [mode]=\"'dialogue'\" [customClass]=\"'show-revert-dialogue'\" [disableFooter]=\"true\" [isVisible]=\"showRejectDialogue\"\n [bodyTemplate]=\"rejectBodyTemplate\" (closeModal)=\"closeRejectDialogue()\">\n <ng-template #rejectBodyTemplate>\n <div class=\"dialog-body flex flex-col gap-4\">\n <div class=\"header font-bold text-2xl\">Reject User Request</div>\n <div class=\"form-container-dialogue flex flex-col gap-2\">\n Please provide a reason for rejecting this request.\n <verbena-textarea label=\"Reason\" [required]=\"true\" [rows]=\"4\" width=\"100%\" [formControl]=\"rejectComment\"\n errorMessageColor=\"var(--vbn-color-danger)\">\n </verbena-textarea>\n </div>\n <div class=\"dialog-button-container flex gap-2\">\n <div class=\"flex-1\">\n <verbena-button width=\"100%\" [fontWeight]=\"'bold'\" [bgColor]=\"'var(--vbn-color-surface)'\"\n [borderRadius]=\"'4px'\" [textColor]=\"'var(--vbn-color-text)'\" [border]=\"'1px solid var(--vbn-color-text)'\"\n [text]=\"'Close'\" (click)=\"closeRejectDialogue()\">\n </verbena-button>\n </div>\n <div class=\"flex-1\">\n <verbena-button width=\"100%\" class=\"verben-primary-button\" [text]=\"'Proceed'\" (click)=\"confirmReject()\"\n [disable]=\"!canConfirmReject()\">\n </verbena-button>\n </div>\n </div>\n </div>\n </ng-template>\n</verben-dialogue>\n", styles: [":host{display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.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: VerbenaTextareaModule }, { kind: "component", type: i3.VerbenaTextareaComponent, selector: "verbena-textarea", inputs: ["disabled", "label", "required", "rows", "cols", "bgColor", "textColor", "border", "borderRadius", "pd", "width", "height", "value", "errorMessageColor"], outputs: ["valueChange"] }, { 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: VerbenDialogueModule }, { kind: "component", type: i3.VerbenDialogueComponent, selector: "verben-dialogue", inputs: ["dialogueWidth", "headerTemplate", "bodyTemplate", "footerTemplate", "showCloseIcon", "dismissOutsideClick", "closeOnEscape", "isVisible", "size", "backdropColor", "customClass", "disableFooter", "margin", "padding", "borderRadius", "dialogueBgColor", "width", "closeIconClass", "boxShadow", "enableTransition", "modalData", "mode", "position", "drawerWidth"], outputs: ["openModal", "closeModal"] }] });
|
|
563
226
|
}
|
|
564
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type:
|
|
565
|
-
type:
|
|
566
|
-
args: [{
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
}
|
|
227
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserRequestApprovalFormComponent, decorators: [{
|
|
228
|
+
type: Component,
|
|
229
|
+
args: [{ selector: 'lib-user-request-approval-form', standalone: true, imports: [
|
|
230
|
+
CommonModule,
|
|
231
|
+
ReactiveFormsModule,
|
|
232
|
+
VerbenaInputModule,
|
|
233
|
+
VerbenaButtonModule,
|
|
234
|
+
VerbenaTextareaModule,
|
|
235
|
+
DropDownModule,
|
|
236
|
+
VerbenDialogueModule,
|
|
237
|
+
], 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 name=\"MailAddress\" label=\"Mail Address:\" formControlName=\"MailAddress\" [readOnly]=\"true\" />\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=\"Other Name:\" name=\"OtherName\" type=\"text\" formControlName=\"OtherName\" [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\">\n </verben-drop-down>\n </div>\n\n <!-- buttons -->\n <div class=\"flex justify-between my-2 overflow-auto\">\n <div class=\"flex gap-2\">\n <verbena-button (click)=\"switchToTable.emit()\" text=\"Switch To Table\" styleType=\"ylw-outline\"></verbena-button>\n\n <verbena-button *ngIf=\"showDelete()\" width=\"114px\" height=\"39px\" (click)=\"toggleDeleteDialogue()\" text=\"Delete\"\n styleType=\"danger\" borderRadius=\"10px\" [disable]=\"!canDelete()\"></verbena-button>\n </div>\n\n <div class=\"flex gap-2\">\n <verbena-button width=\"114px\" height=\"39px\" text=\"Reject\" styleType=\"danger\" borderRadius=\"10px\"\n (click)=\"openRejectDialogue()\" [disable]=\"!canReject()\"></verbena-button>\n\n <verbena-button (click)=\"onApprove()\" text=\"Approve\" bgColor=\"var(--vbn-color-success)\" textColor=\"white\"\n border=\"1px solid var(--vbn-color-success)\" borderRadius=\"10px\" pd=\"10px 20px\" width=\"114px\" height=\"39px\"\n [disable]=\"!canProcess()\"></verbena-button>\n </div>\n </div>\n</form>\n\n<verben-dialogue [showCloseIcon]=\"false\" [dismissOutsideClick]=\"false\" [closeOnEscape]=\"true\" [size]=\"'medium'\"\n [mode]=\"'dialogue'\" [customClass]=\"'show-revert-dialogue'\" [disableFooter]=\"true\" [isVisible]=\"showDeleteDialogue\"\n [bodyTemplate]=\"deleteBodyTemplate\" (closeModal)=\"closeDeleteDialogue()\">\n <ng-template #deleteBodyTemplate>\n <div class=\"dialog-body flex flex-col gap-4\">\n <div class=\"header font-bold text-2xl\">Delete User Request</div>\n <div class=\"form-container-dialogue flex flex-col gap-2\">\n Are you sure you want to proceed?\n </div>\n <div class=\"dialog-button-container flex gap-2\">\n <div class=\"flex-1\">\n <verbena-button width=\"100%\" [fontWeight]=\"'bold'\" [bgColor]=\"'var(--vbn-color-surface)'\"\n [borderRadius]=\"'4px'\" [textColor]=\"'var(--vbn-color-text)'\" [border]=\"'1px solid var(--vbn-color-text)'\"\n [text]=\"'Close'\" (click)=\"closeDeleteDialogue()\">\n </verbena-button>\n </div>\n <div class=\"flex-1\">\n <verbena-button width=\"100%\" class=\"verben-primary-button\" [text]=\"'Proceed'\" (click)=\"onDelete()\">\n </verbena-button>\n </div>\n </div>\n </div>\n </ng-template>\n</verben-dialogue>\n\n<verben-dialogue [showCloseIcon]=\"false\" [dismissOutsideClick]=\"false\" [closeOnEscape]=\"true\" [size]=\"'medium'\"\n [mode]=\"'dialogue'\" [customClass]=\"'show-revert-dialogue'\" [disableFooter]=\"true\" [isVisible]=\"showRejectDialogue\"\n [bodyTemplate]=\"rejectBodyTemplate\" (closeModal)=\"closeRejectDialogue()\">\n <ng-template #rejectBodyTemplate>\n <div class=\"dialog-body flex flex-col gap-4\">\n <div class=\"header font-bold text-2xl\">Reject User Request</div>\n <div class=\"form-container-dialogue flex flex-col gap-2\">\n Please provide a reason for rejecting this request.\n <verbena-textarea label=\"Reason\" [required]=\"true\" [rows]=\"4\" width=\"100%\" [formControl]=\"rejectComment\"\n errorMessageColor=\"var(--vbn-color-danger)\">\n </verbena-textarea>\n </div>\n <div class=\"dialog-button-container flex gap-2\">\n <div class=\"flex-1\">\n <verbena-button width=\"100%\" [fontWeight]=\"'bold'\" [bgColor]=\"'var(--vbn-color-surface)'\"\n [borderRadius]=\"'4px'\" [textColor]=\"'var(--vbn-color-text)'\" [border]=\"'1px solid var(--vbn-color-text)'\"\n [text]=\"'Close'\" (click)=\"closeRejectDialogue()\">\n </verbena-button>\n </div>\n <div class=\"flex-1\">\n <verbena-button width=\"100%\" class=\"verben-primary-button\" [text]=\"'Proceed'\" (click)=\"confirmReject()\"\n [disable]=\"!canConfirmReject()\">\n </verbena-button>\n </div>\n </div>\n </div>\n </ng-template>\n</verben-dialogue>\n", styles: [":host{display:block;width:100%;height:100%}\n"] }]
|
|
238
|
+
}], ctorParameters: () => [{ type: i1$1.FormBuilder }], propDecorators: { approve: [{
|
|
239
|
+
type: Output
|
|
240
|
+
}], reject: [{
|
|
241
|
+
type: Output
|
|
242
|
+
}], deleteRequest: [{
|
|
243
|
+
type: Output
|
|
244
|
+
}], switchToTable: [{
|
|
245
|
+
type: Output
|
|
246
|
+
}] } });
|
|
576
247
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
248
|
+
/**
|
|
249
|
+
* Table view for access requests. Row actions open the form (to approve/reject
|
|
250
|
+
* with a role) or delete the request.
|
|
251
|
+
*/
|
|
252
|
+
class UserRequestApprovalTableComponent {
|
|
253
|
+
requests = [];
|
|
254
|
+
columns = [];
|
|
255
|
+
isLoading = false;
|
|
580
256
|
showDelete = false;
|
|
581
|
-
|
|
582
|
-
|
|
257
|
+
view = new EventEmitter();
|
|
258
|
+
delete = new EventEmitter();
|
|
259
|
+
onView(request) {
|
|
260
|
+
this.view.emit(request);
|
|
583
261
|
}
|
|
584
|
-
|
|
585
|
-
this.
|
|
586
|
-
console.log(value?.data);
|
|
587
|
-
if (value?.data) {
|
|
588
|
-
this.form.patchValue({
|
|
589
|
-
MailAddress: value.data.MailAddress || '',
|
|
590
|
-
FirstName: value.data.FirstName || '',
|
|
591
|
-
LastName: value.data.LastName || '',
|
|
592
|
-
OtherName: value.data.OtherName || '',
|
|
593
|
-
PhoneNumber: value.data.PhoneNumber || '',
|
|
594
|
-
RoleID: value.data.RoleID || '',
|
|
595
|
-
});
|
|
596
|
-
}
|
|
597
|
-
else {
|
|
598
|
-
this.form.reset();
|
|
599
|
-
}
|
|
262
|
+
onDelete(request) {
|
|
263
|
+
this.delete.emit(request);
|
|
600
264
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
switchView = new EventEmitter();
|
|
604
|
-
onApproval = new EventEmitter();
|
|
605
|
-
onDeleteRequest = new EventEmitter();
|
|
606
|
-
form;
|
|
607
|
-
// roles: WritableSignal<Role[]> = signal([]);
|
|
608
|
-
constructor(fb) {
|
|
609
|
-
this.fb = fb;
|
|
610
|
-
this.form = this.fb.group({
|
|
611
|
-
MailAddress: ['', { readonly: true }],
|
|
612
|
-
FirstName: ['', { readonly: true }],
|
|
613
|
-
LastName: ['', { readonly: true }],
|
|
614
|
-
OtherName: ['', { readonly: true }],
|
|
615
|
-
PhoneNumber: ['', { readonly: true }],
|
|
616
|
-
RoleID: ['', { validators: [Validators.required] }],
|
|
617
|
-
});
|
|
618
|
-
}
|
|
619
|
-
ngOnInit() {
|
|
620
|
-
// this.userAccessRequestFacade.getRoles$().subscribe((data) => {
|
|
621
|
-
// this.roles.set(data);
|
|
622
|
-
// });
|
|
623
|
-
// try {
|
|
624
|
-
// this.userAccessRequestFacade.loadRoles();
|
|
625
|
-
// } catch (error) {
|
|
626
|
-
// // Handle error
|
|
627
|
-
// }
|
|
628
|
-
console.log(this.currentData?.data);
|
|
629
|
-
}
|
|
630
|
-
onSave() {
|
|
631
|
-
if (this.form.valid) {
|
|
632
|
-
// Emit save event with form value
|
|
633
|
-
console.log('Form saved:', this.form.value);
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
onDelete() {
|
|
637
|
-
// Emit delete event
|
|
638
|
-
this.onDeleteRequest.emit({ email: this.form.get('MailAddress')?.value });
|
|
639
|
-
this.onModalClose('');
|
|
640
|
-
}
|
|
641
|
-
canDelete() {
|
|
642
|
-
return (this.currentData?.data?.RequestStatus == UserAccessRequestStatus.Pending);
|
|
643
|
-
}
|
|
644
|
-
disableProcessing() {
|
|
645
|
-
return (this.currentData?.data?.RequestStatus !==
|
|
646
|
-
UserAccessRequestStatus.Pending || !this.form.valid);
|
|
647
|
-
}
|
|
648
|
-
toggleModal() {
|
|
649
|
-
this.showDialogue = !this.showDialogue;
|
|
650
|
-
}
|
|
651
|
-
onModalOpen(event) { }
|
|
652
|
-
onModalClose(event) {
|
|
653
|
-
this.showDialogue = false;
|
|
654
|
-
}
|
|
655
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserRequestFormComponent, deps: [{ token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
|
|
656
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: UserRequestFormComponent, selector: "lib-user-request-form", inputs: { roles: "roles", showDelete: "showDelete", currentData: "currentData" }, outputs: { switchView: "switchView", onApproval: "onApproval", onDeleteRequest: "onDeleteRequest" }, ngImport: i0, template: "<form\n [formGroup]=\"form\"\n class=\"flex flex-col px-3 pb-3 rounded-xl h-full w-full relative space-y-4\"\n>\n <verbena-input\n name=\"MailAddress\"\n label=\"Mail Address:\"\n formControlName=\"MailAddress\"\n [readOnly]=\"true\"\n />\n <verbena-input\n label=\"First Name:\"\n name=\"FirstName\"\n type=\"text\"\n formControlName=\"FirstName\"\n [readOnly]=\"true\"\n />\n <verbena-input\n label=\"Last Name:\"\n name=\"LastName\"\n type=\"text\"\n formControlName=\"LastName\"\n [readOnly]=\"true\"\n />\n <verbena-input\n label=\"OtherName:\"\n name=\"OtherName\"\n type=\"text\"\n formControlName=\"OtherName\"\n [readOnly]=\"true\"\n />\n <!-- <verbena-input\n label=\"Phone Number:\"\n name=\"PhoneNumber\"\n type=\"tel\"\n formControlName=\"PhoneNumber\"\n [readOnly]=\"true\"\n /> -->\n\n <div class=\"space-y-1\">\n <label for=\"role\">Role</label>\n\n <verben-drop-down\n label=\"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 formControlName=\"RoleID\"\n class=\"form-control\"\n >\n </verben-drop-down>\n </div>\n\n <!-- buttons -->\n <div class=\"flex justify-between my-2 overflow-auto\">\n <div class=\"flex gap-2\">\n <verbena-button\n (click)=\"switchView.emit()\"\n text=\"Switch To Table\"\n styleType=\"ylw-outline\"\n ></verbena-button>\n\n <verbena-button\n *ngIf=\"showDelete\"\n width=\"114px\"\n height=\"39px\"\n (click)=\"toggleModal()\"\n text=\"Delete\"\n styleType=\"danger\"\n borderRadius=\"10px\"\n ></verbena-button>\n </div>\n\n <div class=\"flex gap-2\">\n <verbena-button\n width=\"114px\"\n height=\"39px\"\n text=\"Reject\"\n styleType=\"danger\"\n borderRadius=\"10px\"\n [disable]=\"disableProcessing()\"\n ></verbena-button>\n\n <verbena-button\n (click)=\"\n onApproval.emit({\n email: form.get('MailAddress')?.value,\n role: form.get('RoleID')?.value,\n })\n \"\n text=\"Approve\"\n bgColor=\"#28a745\"\n textColor=\"white\"\n border=\"1px solid #28a745\"\n borderRadius=\"10px\"\n pd=\"10px 20px\"\n width=\"114px\"\n height=\"39px\"\n [disable]=\"disableProcessing()\"\n ></verbena-button>\n </div>\n </div>\n</form>\n\n<verben-dialogue\n [showCloseIcon]=\"false\"\n [dismissOutsideClick]=\"false\"\n [closeOnEscape]=\"true\"\n [size]=\"'medium'\"\n [mode]=\"'dialogue'\"\n [customClass]=\"'show-revert-dialogue'\"\n [disableFooter]=\"true\"\n (openModal)=\"onModalOpen($event)\"\n [isVisible]=\"showDialogue\"\n [bodyTemplate]=\"bodyTemplate\"\n (closeModal)=\"onModalClose($event)\"\n>\n <ng-template #bodyTemplate>\n <div class=\"dialog-body flex flex-col gap-4\">\n <div class=\"header font-bold text-2xl\">Delete User Request</div>\n <div class=\"form-container-dialogue flex flex-col gap-2\">\n Are you sure you want to proceed ?\n </div>\n <div class=\"dialog-button-container flex gap-2\">\n <div class=\"flex-1\">\n <verbena-button\n width=\"100%\"\n [fontWeight]=\"'bold'\"\n [bgColor]=\"'#ffffff'\"\n [borderRadius]=\"'4px'\"\n [textColor]=\"'#000'\"\n [border]=\"'1px solid #000'\"\n [text]=\"'Close'\"\n (click)=\"onModalClose($event)\"\n >\n </verbena-button>\n </div>\n <div class=\"flex-1\">\n <verbena-button\n width=\"100%\"\n class=\"verben-primary-button\"\n [text]=\"'Proceed'\"\n (click)=\"onDelete()\"\n >\n </verbena-button>\n </div>\n </div>\n </div>\n </ng-template>\n</verben-dialogue>\n", styles: [".form-container-dialogue{overflow:auto;max-height:60vh}.dialog-body{padding:15px;height:100%}.dialog-button-container{flex:1 1 0;align-items:end}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4.VerbenDialogueComponent, selector: "verben-dialogue", inputs: ["dialogueWidth", "headerTemplate", "bodyTemplate", "footerTemplate", "showCloseIcon", "dismissOutsideClick", "closeOnEscape", "isVisible", "size", "backdropColor", "customClass", "disableFooter", "margin", "padding", "borderRadius", "dialogueBgColor", "width", "closeIconClass", "boxShadow", "enableTransition", "modalData", "mode", "position", "drawerWidth"], outputs: ["openModal", "closeModal"] }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i4.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: i4.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: i4.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"] }] });
|
|
265
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserRequestApprovalTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
266
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: UserRequestApprovalTableComponent, isStandalone: true, selector: "lib-user-request-approval-table", inputs: { requests: "requests", columns: "columns", isLoading: "isLoading", showDelete: "showDelete" }, outputs: { view: "view", delete: "delete" }, ngImport: i0, template: "<div class=\"table-container\" [class.loading]=\"isLoading\">\n <lib-data-table [data]=\"requests\" [columns]=\"columns\" dataKey=\"MailAddress\">\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 <!-- Status -->\n <ng-container libColumn=\"status\">\n <ng-template #cell let-value>\n <lib-user-access-request-status-badge [status]=\"value\"></lib-user-access-request-status-badge>\n </ng-template>\n </ng-container>\n\n <!-- Actions -->\n <ng-container libColumn=\"actions\">\n <ng-template #cell let-row=\"row\">\n <div class=\"flex gap-6\">\n <verben-svg (click)=\"onView(row)\" icon=\"edit\" [width]=\"15\" [height]=\"15\" class=\"cursor-pointer\"></verben-svg>\n <verben-svg *ngIf=\"showDelete\" (click)=\"onDelete(row)\" 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=\"requests.length === 0 && !isLoading\" class=\"empty-state\">\n <p>No access requests 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: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }, { 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: "component", type: UserAccessRequestStatusBadgeComponent, selector: "lib-user-access-request-status-badge", inputs: ["status"] }] });
|
|
657
267
|
}
|
|
658
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type:
|
|
268
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserRequestApprovalTableComponent, decorators: [{
|
|
659
269
|
type: Component,
|
|
660
|
-
args: [{ selector: 'lib-user-request-
|
|
661
|
-
}],
|
|
270
|
+
args: [{ selector: 'lib-user-request-approval-table', standalone: true, imports: [CommonModule, DataTableModule, SvgModule, UserAccessRequestStatusBadgeComponent], template: "<div class=\"table-container\" [class.loading]=\"isLoading\">\n <lib-data-table [data]=\"requests\" [columns]=\"columns\" dataKey=\"MailAddress\">\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 <!-- Status -->\n <ng-container libColumn=\"status\">\n <ng-template #cell let-value>\n <lib-user-access-request-status-badge [status]=\"value\"></lib-user-access-request-status-badge>\n </ng-template>\n </ng-container>\n\n <!-- Actions -->\n <ng-container libColumn=\"actions\">\n <ng-template #cell let-row=\"row\">\n <div class=\"flex gap-6\">\n <verben-svg (click)=\"onView(row)\" icon=\"edit\" [width]=\"15\" [height]=\"15\" class=\"cursor-pointer\"></verben-svg>\n <verben-svg *ngIf=\"showDelete\" (click)=\"onDelete(row)\" 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=\"requests.length === 0 && !isLoading\" class=\"empty-state\">\n <p>No access requests 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"] }]
|
|
271
|
+
}], propDecorators: { requests: [{
|
|
662
272
|
type: Input
|
|
663
|
-
}],
|
|
273
|
+
}], columns: [{
|
|
664
274
|
type: Input
|
|
665
|
-
}],
|
|
275
|
+
}], isLoading: [{
|
|
666
276
|
type: Input
|
|
667
|
-
}],
|
|
668
|
-
type:
|
|
669
|
-
}],
|
|
277
|
+
}], showDelete: [{
|
|
278
|
+
type: Input
|
|
279
|
+
}], view: [{
|
|
670
280
|
type: Output
|
|
671
|
-
}],
|
|
281
|
+
}], delete: [{
|
|
672
282
|
type: Output
|
|
673
283
|
}] } });
|
|
674
284
|
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
default:
|
|
684
|
-
return { bgColor: '#827C7C', textColor: '#C3C3C3', label: 'Pending' };
|
|
685
|
-
}
|
|
285
|
+
/**
|
|
286
|
+
* State for the access-request approval page.
|
|
287
|
+
* Adds the roles list used by the form's role dropdown.
|
|
288
|
+
*/
|
|
289
|
+
class UserAccessRequestState extends BaseDataPageState {
|
|
290
|
+
roles$ = new BehaviorSubject([]);
|
|
291
|
+
getRoles$() {
|
|
292
|
+
return this.roles$.asObservable();
|
|
686
293
|
}
|
|
687
|
-
|
|
688
|
-
|
|
294
|
+
getRolesValue() {
|
|
295
|
+
return this.roles$.getValue();
|
|
296
|
+
}
|
|
297
|
+
setRoles(roles) {
|
|
298
|
+
this.roles$.next(roles);
|
|
299
|
+
}
|
|
300
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserAccessRequestState, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
301
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserAccessRequestState });
|
|
689
302
|
}
|
|
690
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type:
|
|
691
|
-
type:
|
|
692
|
-
|
|
693
|
-
}], propDecorators: { status: [{
|
|
694
|
-
type: Input
|
|
695
|
-
}] } });
|
|
303
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserAccessRequestState, decorators: [{
|
|
304
|
+
type: Injectable
|
|
305
|
+
}] });
|
|
696
306
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
styles = baseStyle;
|
|
712
|
-
currentData = null;
|
|
713
|
-
isGridView = true;
|
|
714
|
-
selected = null;
|
|
715
|
-
cardData = computed(() => this.data()?.map(({ FirstName, LastName, MailAddress, PhoneNumber, RoleID, RequestStatus, Role, SignupType, }) => ({
|
|
716
|
-
selected: false,
|
|
717
|
-
title: `${FirstName} ${LastName}`,
|
|
718
|
-
data: {
|
|
719
|
-
FirstName,
|
|
720
|
-
LastName,
|
|
721
|
-
MailAddress,
|
|
722
|
-
PhoneNumber,
|
|
723
|
-
RoleID,
|
|
724
|
-
RequestStatus,
|
|
725
|
-
Role,
|
|
726
|
-
SignupType,
|
|
727
|
-
},
|
|
728
|
-
body: [{ title: 'Role', value: Role?.Name ?? '' }],
|
|
729
|
-
children: [],
|
|
730
|
-
})));
|
|
731
|
-
roles = signal([]);
|
|
732
|
-
constructor(cdr,
|
|
733
|
-
// private service: UserRequestApprovalService,
|
|
734
|
-
utilService, envService, server, userAccessRequestFacade) {
|
|
735
|
-
this.cdr = cdr;
|
|
736
|
-
this.utilService = utilService;
|
|
737
|
-
this.envService = envService;
|
|
738
|
-
this.server = server;
|
|
739
|
-
this.userAccessRequestFacade = userAccessRequestFacade;
|
|
307
|
+
/**
|
|
308
|
+
* Service for access-request API operations.
|
|
309
|
+
*
|
|
310
|
+
* The auth API pluralises names and appends a `/{sortParam}/{sortOrder}` suffix
|
|
311
|
+
* to every read, so the base URL seams are overridden accordingly. It also
|
|
312
|
+
* carries an approve/reject workflow and a bespoke delete-by-email endpoint that
|
|
313
|
+
* have no analog in the generic CRUD base.
|
|
314
|
+
*
|
|
315
|
+
* Kept publicly exported under its original name for backward compatibility.
|
|
316
|
+
*/
|
|
317
|
+
class UserAccessRequestService extends BaseDataPageService {
|
|
318
|
+
defaultSort = 'CreatedAt/Asc';
|
|
319
|
+
constructor(server, filterHandler, sortHandler) {
|
|
320
|
+
super(server, filterHandler, sortHandler);
|
|
740
321
|
}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
this.userAccessRequestFacade.getRequests$().subscribe((data) => {
|
|
744
|
-
this.data.set(data);
|
|
745
|
-
});
|
|
746
|
-
this.userAccessRequestFacade.getRoles$().subscribe((data) => {
|
|
747
|
-
this.roles.set(data);
|
|
748
|
-
});
|
|
749
|
-
try {
|
|
750
|
-
this.userAccessRequestFacade.loadRequests();
|
|
751
|
-
this.userAccessRequestFacade.loadRoles();
|
|
752
|
-
}
|
|
753
|
-
catch (error) {
|
|
754
|
-
// Handle error
|
|
755
|
-
}
|
|
322
|
+
getEndpoint() {
|
|
323
|
+
return 'UserAccessRequest';
|
|
756
324
|
}
|
|
757
|
-
|
|
758
|
-
|
|
325
|
+
// ===== URL seams =====
|
|
326
|
+
listUrl(skip, limit) {
|
|
327
|
+
return `GetUserAccessRequests/${skip}/${limit}/${this.defaultSort}`;
|
|
759
328
|
}
|
|
760
|
-
|
|
761
|
-
this.
|
|
329
|
+
searchTermUrl(term, skip, limit) {
|
|
330
|
+
return `GetUserAccessRequestWithParam/${term}/${skip}/${limit}/${this.defaultSort}`;
|
|
762
331
|
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
await this.userAccessRequestFacade.loadMore();
|
|
766
|
-
}
|
|
767
|
-
catch (error) {
|
|
768
|
-
// Handle error
|
|
769
|
-
}
|
|
332
|
+
filterSearchUrl(skip, limit) {
|
|
333
|
+
return `SearchUserAccessRequest/${skip}/${limit}/${this.defaultSort}`;
|
|
770
334
|
}
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
try {
|
|
774
|
-
await this.userAccessRequestFacade.loadRequestsWithParam(param);
|
|
775
|
-
}
|
|
776
|
-
catch (error) {
|
|
777
|
-
// Handle error
|
|
778
|
-
}
|
|
335
|
+
saveUrl() {
|
|
336
|
+
return 'SaveUserAccessRequests';
|
|
779
337
|
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
await this.
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
});
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
|
-
async onDelete(deletionData) {
|
|
790
|
-
const data = this.data().find(({ MailAddress }) => MailAddress === deletionData.email);
|
|
791
|
-
this.utilService.sendBI(true);
|
|
792
|
-
const res = await this.server.get(`DeleteUserRequestWithUser/${deletionData.email}`, this.envService.environment.AuthenticationAPI);
|
|
793
|
-
this.utilService.sendBI(false);
|
|
794
|
-
if (res instanceof ErrorResponse) {
|
|
795
|
-
}
|
|
796
|
-
else {
|
|
797
|
-
if (data) {
|
|
798
|
-
this.data.update((items) => items.filter((x) => x.Code !== data.Code));
|
|
338
|
+
// ===== Delete (bespoke: by email, also removes the associated signup) =====
|
|
339
|
+
async deleteItems(emails) {
|
|
340
|
+
for (const email of emails) {
|
|
341
|
+
const res = await this.server.get(`DeleteUserRequestWithUser/${email}`, this.baseUrl);
|
|
342
|
+
if (res instanceof ErrorResponse) {
|
|
343
|
+
return res;
|
|
799
344
|
}
|
|
800
|
-
this.cardDataView.clearData();
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
openDetailView(mailAddress) {
|
|
804
|
-
const cardItem = this.getCardDataByMailAddress(mailAddress);
|
|
805
|
-
if (cardItem && this.cardDataView) {
|
|
806
|
-
this.dataView.toggleView();
|
|
807
|
-
// First reset all selections
|
|
808
|
-
this.cardData().forEach((item) => {
|
|
809
|
-
item.selected = false;
|
|
810
|
-
if (item.children) {
|
|
811
|
-
item.children.forEach((child) => (child.selected = false));
|
|
812
|
-
}
|
|
813
|
-
});
|
|
814
|
-
// Set the selected item
|
|
815
|
-
cardItem.selected = true;
|
|
816
|
-
this.currentData = this.cardDataView.onItemClick(cardItem);
|
|
817
|
-
// Force change detection if needed
|
|
818
|
-
// this.changeDetectorRef.detectChanges();
|
|
819
345
|
}
|
|
346
|
+
return true;
|
|
820
347
|
}
|
|
821
|
-
|
|
822
|
-
|
|
348
|
+
// ===== Workflow =====
|
|
349
|
+
/** Approve (isApproval=true) or reject (false) the given requests. */
|
|
350
|
+
processRequests(requests, isApproval) {
|
|
351
|
+
return this.server.post(`UserAccessRequestAction/${isApproval}`, requests);
|
|
823
352
|
}
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
if (
|
|
828
|
-
|
|
829
|
-
this.currentData = null;
|
|
830
|
-
}
|
|
831
|
-
console.log('SELECTED', this.selected);
|
|
832
|
-
if (this.selected) {
|
|
833
|
-
this.cardDataView.onItemClick(this.selected);
|
|
353
|
+
// ===== Lookups =====
|
|
354
|
+
async getRoles() {
|
|
355
|
+
const res = await this.server.get('GetRoles/0/0');
|
|
356
|
+
if (res instanceof ErrorResponse) {
|
|
357
|
+
return [];
|
|
834
358
|
}
|
|
359
|
+
return res.Result ?? [];
|
|
835
360
|
}
|
|
836
|
-
|
|
837
|
-
const
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
handleExport(exportedData) {
|
|
841
|
-
console.log('Exported data:', exportedData);
|
|
842
|
-
this.downloadCSV(exportedData);
|
|
843
|
-
}
|
|
844
|
-
/**
|
|
845
|
-
* @param data Simple csv export for testing
|
|
846
|
-
*/
|
|
847
|
-
downloadCSV(data) {
|
|
848
|
-
const headers = Object.keys(data[0]);
|
|
849
|
-
const csvContent = [
|
|
850
|
-
headers.join(','),
|
|
851
|
-
...data.map((row) => headers.map((header) => row[header]).join(',')),
|
|
852
|
-
].join('\n');
|
|
853
|
-
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
|
|
854
|
-
const link = document.createElement('a');
|
|
855
|
-
if (link.download !== undefined) {
|
|
856
|
-
const url = URL.createObjectURL(blob);
|
|
857
|
-
link.setAttribute('href', url);
|
|
858
|
-
link.setAttribute('download', 'export.csv');
|
|
859
|
-
link.style.visibility = 'hidden';
|
|
860
|
-
document.body.appendChild(link);
|
|
861
|
-
link.click();
|
|
862
|
-
document.body.removeChild(link);
|
|
361
|
+
async getTags() {
|
|
362
|
+
const res = await this.server.get('GetTags/0/0');
|
|
363
|
+
if (res instanceof ErrorResponse) {
|
|
364
|
+
return [];
|
|
863
365
|
}
|
|
366
|
+
return res.Result ?? [];
|
|
864
367
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
368
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserAccessRequestService, deps: [{ token: i1$2.HttpWebRequestService }, { token: i2.FilterHandlerService }, { token: i2.SortHandlerService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
369
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserAccessRequestService });
|
|
370
|
+
}
|
|
371
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserAccessRequestService, decorators: [{
|
|
372
|
+
type: Injectable
|
|
373
|
+
}], ctorParameters: () => [{ type: i1$2.HttpWebRequestService }, { type: i2.FilterHandlerService }, { type: i2.SortHandlerService }] });
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Facade for the access-request approval page.
|
|
377
|
+
* Adds the approve/reject workflow on top of the generic base facade.
|
|
378
|
+
*/
|
|
379
|
+
class UserAccessRequestFacade extends BaseDataPageFacade {
|
|
380
|
+
requestService;
|
|
381
|
+
blankRequest;
|
|
382
|
+
constructor(state, service, searchHandler, utilService) {
|
|
383
|
+
super(state, service, searchHandler, utilService, USER_ACCESS_REQUEST_CONFIG);
|
|
384
|
+
this.requestService = service;
|
|
385
|
+
}
|
|
386
|
+
// ===== Custom observables =====
|
|
387
|
+
get roles$() {
|
|
388
|
+
return this.state.getRoles$();
|
|
389
|
+
}
|
|
390
|
+
// ===== View management =====
|
|
869
391
|
/**
|
|
870
|
-
*
|
|
392
|
+
* Select the request to show in the form. The form template binds to
|
|
393
|
+
* currentCardData(), so route selection through selectCard (reusing the
|
|
394
|
+
* matching card from the loaded list when present) rather than a separate
|
|
395
|
+
* selected-request stream that nothing reads.
|
|
871
396
|
*/
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
visibleColumns = columns.map((col) => ({
|
|
880
|
-
checked: true,
|
|
881
|
-
name: typeof col.header === 'string' ? col.header : col.id,
|
|
882
|
-
type: DataFilterType.Bool,
|
|
883
|
-
}));
|
|
884
|
-
filterArray = [
|
|
885
|
-
{
|
|
886
|
-
name: 'Name',
|
|
887
|
-
type: DataFilterType.String,
|
|
888
|
-
checked: false,
|
|
889
|
-
},
|
|
890
|
-
{
|
|
891
|
-
name: 'MailAddress',
|
|
892
|
-
type: DataFilterType.String,
|
|
893
|
-
checked: false,
|
|
894
|
-
},
|
|
895
|
-
{
|
|
896
|
-
name: 'PhoneNumber',
|
|
897
|
-
type: DataFilterType.String,
|
|
898
|
-
checked: false,
|
|
899
|
-
},
|
|
900
|
-
{
|
|
901
|
-
name: 'CreatedAt',
|
|
902
|
-
type: DataFilterType.Date,
|
|
903
|
-
checked: false,
|
|
904
|
-
},
|
|
905
|
-
];
|
|
906
|
-
sortOptions = [
|
|
907
|
-
{
|
|
908
|
-
name: 'Name',
|
|
909
|
-
type: DataFilterType.String,
|
|
910
|
-
checked: false,
|
|
911
|
-
},
|
|
912
|
-
{
|
|
913
|
-
name: 'MailAddress',
|
|
914
|
-
type: DataFilterType.String,
|
|
915
|
-
checked: false,
|
|
916
|
-
},
|
|
917
|
-
{
|
|
918
|
-
name: 'PhoneNumber',
|
|
919
|
-
type: DataFilterType.String,
|
|
920
|
-
checked: false,
|
|
921
|
-
},
|
|
922
|
-
{
|
|
923
|
-
name: 'CreatedAt',
|
|
924
|
-
type: DataFilterType.Date,
|
|
925
|
-
checked: true,
|
|
926
|
-
},
|
|
927
|
-
];
|
|
928
|
-
clearData() {
|
|
929
|
-
this.currentData = {};
|
|
930
|
-
}
|
|
931
|
-
onColumnChange(event) {
|
|
932
|
-
this.showColumn = event;
|
|
933
|
-
}
|
|
934
|
-
onSortChange(event) {
|
|
935
|
-
this.showSort = event;
|
|
936
|
-
console.log(event);
|
|
937
|
-
}
|
|
938
|
-
onColumnsUpdated(updatedColumns) {
|
|
939
|
-
console.log(updatedColumns);
|
|
940
|
-
const updatedColumnDef = [];
|
|
941
|
-
updatedColumns.forEach((col) => {
|
|
942
|
-
const matchingCol = this.columns.find((column) => column.header === col.name || column.id === col.name);
|
|
943
|
-
if (matchingCol) {
|
|
944
|
-
updatedColumnDef.push(matchingCol);
|
|
945
|
-
}
|
|
946
|
-
});
|
|
947
|
-
console.log(updatedColumnDef);
|
|
948
|
-
this.visibleColumnDef = [...updatedColumnDef];
|
|
949
|
-
this.cdr.markForCheck();
|
|
950
|
-
this.onColumnChange(false);
|
|
951
|
-
this.selectedColumnCount = updatedColumns.length;
|
|
397
|
+
openForm(request) {
|
|
398
|
+
if (!request) {
|
|
399
|
+
this.selectCard(null);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
const existing = this.cardData().find((card) => card.data?.MailAddress === request.MailAddress);
|
|
403
|
+
this.selectCard(existing ?? this.getConfig().cardDataMapper(request));
|
|
952
404
|
}
|
|
953
|
-
|
|
954
|
-
this.
|
|
955
|
-
this.selectedSortCount = updatedSorts.length;
|
|
956
|
-
console.log(updatedSorts);
|
|
405
|
+
closeForm() {
|
|
406
|
+
this.selectCard(null);
|
|
957
407
|
}
|
|
958
|
-
|
|
959
|
-
|
|
408
|
+
handleColumnsUpdated(columns) {
|
|
409
|
+
this.updateVisibleColumns(columns);
|
|
960
410
|
}
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
this.
|
|
411
|
+
// ===== Roles =====
|
|
412
|
+
async loadRoles() {
|
|
413
|
+
const roles = await this.requestService.getRoles();
|
|
414
|
+
this.state.setRoles(roles);
|
|
415
|
+
}
|
|
416
|
+
// ===== Approval workflow =====
|
|
417
|
+
async approveRequest(request, roleId) {
|
|
418
|
+
return this.process({ ...request, RoleID: roleId }, true, 'Request approved');
|
|
419
|
+
}
|
|
420
|
+
async rejectRequest(request, comment) {
|
|
421
|
+
return this.process({ ...request, Comment: comment }, false, 'Request rejected');
|
|
422
|
+
}
|
|
423
|
+
async process(request, isApproval, successMessage) {
|
|
424
|
+
this.state.setUpdating(true);
|
|
425
|
+
const result = await this.requestService.processRequests([request], isApproval);
|
|
426
|
+
this.state.setUpdating(false);
|
|
427
|
+
if (result instanceof ErrorResponse) {
|
|
428
|
+
this.utilService.showError(result.ErrorMsg);
|
|
429
|
+
return false;
|
|
430
|
+
}
|
|
431
|
+
this.utilService.showSuccess(successMessage);
|
|
432
|
+
const updated = result[0] ?? {
|
|
433
|
+
...request,
|
|
434
|
+
RequestStatus: isApproval
|
|
435
|
+
? UserAccessRequestStatus.Approved
|
|
436
|
+
: UserAccessRequestStatus.Declined,
|
|
437
|
+
};
|
|
438
|
+
this.state.updateItem(updated);
|
|
439
|
+
this.closeForm();
|
|
440
|
+
return true;
|
|
441
|
+
}
|
|
442
|
+
async deleteRequest(request) {
|
|
443
|
+
// Delete is keyed by email (DeleteUserRequestWithUser/{email}), which does
|
|
444
|
+
// not match the list's Id/Code key, so call the service directly and let
|
|
445
|
+
// refresh() reconcile the list rather than the base facade's key-based
|
|
446
|
+
// removeItem (which would be a no-op for an email).
|
|
447
|
+
this.state.setUpdating(true);
|
|
448
|
+
const result = await this.requestService.deleteItems([request.MailAddress]);
|
|
449
|
+
this.state.setUpdating(false);
|
|
450
|
+
if (result instanceof ErrorResponse) {
|
|
451
|
+
this.utilService.showError(result.ErrorMsg);
|
|
452
|
+
return false;
|
|
453
|
+
}
|
|
454
|
+
this.closeForm();
|
|
455
|
+
await this.refresh();
|
|
456
|
+
return true;
|
|
457
|
+
}
|
|
458
|
+
// ===== Empty placeholder for the form when nothing is selected =====
|
|
459
|
+
get emptyRequest() {
|
|
460
|
+
return (this.blankRequest ??= this.createEmptyRequest());
|
|
461
|
+
}
|
|
462
|
+
createEmptyRequest() {
|
|
463
|
+
return {
|
|
464
|
+
id: Date.now().toString(),
|
|
465
|
+
Id: '',
|
|
466
|
+
Code: '',
|
|
467
|
+
TenantId: '',
|
|
468
|
+
ServiceName: '',
|
|
469
|
+
CreatedAt: new Date(),
|
|
470
|
+
UpdatedAt: new Date(),
|
|
471
|
+
DataState: ObjectState.New,
|
|
472
|
+
Password: '',
|
|
473
|
+
FirstName: '',
|
|
474
|
+
LastName: '',
|
|
475
|
+
MailAddress: '',
|
|
476
|
+
IsSeeded: false,
|
|
477
|
+
Status: Status.Active,
|
|
478
|
+
SignupType: OAuthType.InApp,
|
|
479
|
+
RequestStatus: UserAccessRequestStatus.Pending,
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserAccessRequestFacade, deps: [{ token: UserAccessRequestState }, { token: UserAccessRequestService }, { token: i2.SearchHandlerService }, { token: i1$2.UtilService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
483
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserAccessRequestFacade });
|
|
484
|
+
}
|
|
485
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserAccessRequestFacade, decorators: [{
|
|
486
|
+
type: Injectable
|
|
487
|
+
}], ctorParameters: () => [{ type: UserAccessRequestState }, { type: UserAccessRequestService }, { type: i2.SearchHandlerService }, { type: i1$2.UtilService }] });
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Access-request approval page. Lists requests in table/card views and drives
|
|
491
|
+
* the approve/reject/delete workflow through the facade.
|
|
492
|
+
*/
|
|
493
|
+
class UserRequestApprovalComponent {
|
|
494
|
+
facade;
|
|
495
|
+
showDelete = false;
|
|
496
|
+
vdv;
|
|
497
|
+
cardDataView;
|
|
498
|
+
destroyRef = inject(DestroyRef);
|
|
499
|
+
constructor(facade) {
|
|
500
|
+
this.facade = facade;
|
|
964
501
|
}
|
|
965
|
-
|
|
966
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: UserRequestApprovalComponent, selector: "lib-user-request-approval", inputs: { showDelete: "showDelete" }, viewQueries: [{ propertyName: "cardDataView", first: true, predicate: ["vdcv"], descendants: true }, { propertyName: "dataView", first: true, predicate: ["vdv"], descendants: true }], ngImport: i0, template: "<div class=\"space-y-8\">\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 isCreate: false,\n isToggle: true,\n }\"\n [buttonClass]=\"'my-custom-button-class'\"\n [iconClass]=\"'my-icon-class'\"\n [activeIconClass]=\"'my-active-icon-class'\"\n [selectedColumnCount]=\"0\"\n [selectedSortCount]=\"0\"\n [selectedFilterTableCount]=\"0\"\n (viewChange)=\"onViewChange($event)\"\n (stateChange)=\"onStateChange($event)\"\n (onSearchChange)=\"handleSearch($event)\"\n >\n <div table-content>\n <lib-data-table\n [data]=\"data()\"\n [columns]=\"visibleColumnDef\"\n [styleConfig]=\"styles\"\n (selectionChange)=\"onSelectionChange($event)\"\n >\n <ng-container libColumn=\"createdAt\">\n <ng-template #cell let-value>\n {{ value | date }}\n </ng-template>\n </ng-container>\n <ng-container libColumn=\"status\">\n <ng-template #cell let-value>\n <lib-user-access-request-status-badge\n [status]=\"value\"\n ></lib-user-access-request-status-badge>\n </ng-template>\n </ng-container>\n\n <ng-container libColumn=\"actions\">\n <ng-template #cell let-value let-deleteRow>\n <div class=\"flex gap-6\">\n <verben-svg\n (click)=\"openDetailView(value)\"\n icon=\"edit\"\n [width]=\"15\"\n [height]=\"15\"\n class=\"cursor-pointer\"\n ></verben-svg>\n <!-- <button (click)=\"openDetailView(value)\">Open</button>\n <button (click)=\"selected = cardData[rowIndex]; vdv.toggleView()\">\n Switch\n </button> -->\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 #header>\n <strong>Actions</strong>\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=\"20px\"\n >\n <verben-left-card-data-view class=\"space-y-7\">\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 <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 gap-1\">\n <label for=\"phone\" class=\"text-[10px] font-light\"\n >Medium:</label\n >\n <span id=\"phone\" class=\"text-sm truncate\">{{\n item.data.SignupType\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 >Medium:</label\n >\n <span id=\"role\" class=\"text-sm font-medium\">{{\n item.data?.SignupType\n }}</span>\n </p> -->\n\n <lib-user-access-request-status-badge\n [status]=\"item.data.RequestStatus\"\n ></lib-user-access-request-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 <lib-user-request-form\n [roles]=\"roles()\"\n [showDelete]=\"showDelete\"\n [currentData]=\"currentData\"\n (switchView)=\"vdv.toggleView()\"\n (onDeleteRequest)=\"onDelete($event)\"\n (onApproval)=\"onApprove($event)\"\n ></lib-user-request-form>\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 (filtersApplied)=\"onFilterSet($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=\"420px\"\n textColor=\"black\"\n pd=\"1rem\"\n primaryColor=\"#FFE681\"\n secondaryColor=\"#3479E9\"\n tertiaryColor=\"#404040\"\n [filterOptions]=\"filterArray\"\n [maxFilterLength]=\"3\"\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]=\"visibleColumnDef\"\n [data]=\"data()\"\n (exportDataEvent)=\"handleExport($event)\"\n >\n </lib-data-xport>\n </div>\n </verben-data-view>\n\n <div *ngIf=\"vdv.isTableView\" class=\"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}.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}.m-0{margin:0}.my-0{margin-top:0;margin-bottom:0}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.mb-0{margin-bottom:0}.mb-2{margin-bottom:.5rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.h-\\[100\\%\\]{height:100%}.h-\\[max-content\\]{height:-moz-max-content;height:max-content}.h-full{height:100%}.w-3{width:.75rem}.w-full{width:100%}.flex-1{flex:1 1 0%}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-20{gap:5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.gap-6{gap:1.5rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-y-1{row-gap:.25rem}.gap-y-2{row-gap:.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-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * 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-7>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.75rem * 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))}.overflow-auto{overflow:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.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, 1))}.border-secondary-200{border-color:#d7dbe6}.bg-primary{--tw-bg-opacity: 1;background-color:rgb(212 160 7 / var(--tw-bg-opacity, 1))}.bg-secondary{--tw-bg-opacity: 1;background-color:rgb(232 234 241 / var(--tw-bg-opacity, 1))}.bg-secondary-100{--tw-bg-opacity: 1;background-color:rgb(245 246 249 / var(--tw-bg-opacity, 1))}.bg-secondary-200{background-color:#d7dbe6}.p-3{padding:.75rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pr-1{padding-right:.25rem}.\\!text-\\[10px\\]{font-size:10px!important}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\\[10px\\]{font-size:10px}.text-\\[12px\\]{font-size:12px}.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-bold{font-weight:700}.font-light{font-weight:300}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.lowercase{text-transform:lowercase}.leading-6{line-height:1.5rem}.leading-\\[12\\.1px\\]{line-height:12.1px}.leading-\\[16\\.6px\\]{line-height:16.6px}.leading-\\[19\\.5px\\]{line-height:19.5px}.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, 1))}.text-\\[\\#3479E9\\]{--tw-text-opacity: 1;color:rgb(52 121 233 / var(--tw-text-opacity, 1))}.text-\\[\\#404040\\]{--tw-text-opacity: 1;color:rgb(64 64 64 / var(--tw-text-opacity, 1))}.text-\\[black\\]{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity, 1))}.text-muted{color:#0009}.underline{text-decoration-line:underline}.outline-none{outline:2px solid transparent;outline-offset:2px}.blur{--tw-blur: blur(8px);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)}.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)}.view-links{color:#3479e9;cursor:pointer}\n"], dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4.DataTableComponent, selector: "lib-data-table", inputs: ["data", "columns", "dataKey", "formGroupConfig", "groupBy", "useVirtualScroll", "virtualScrollItemSize", "styleConfig"], outputs: ["rowEdit", "rowSave", "rowRevert", "rowDelete", "selectionChange"] }, { kind: "directive", type: i4.ColumnDirective, selector: "[libColumn]", inputs: ["libColumn"] }, { kind: "component", type: i4.SvgComponent, selector: "verben-svg", inputs: ["icon", "width", "height", "fill", "stroke", "type", "size"] }, { kind: "component", type: i4.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: i4.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: i4.LeftCardDataComponent, selector: "verben-left-card-data", inputs: ["pd", "mg", "height", "weight", "activeCss", "inActiveCss", "cardDataList", "iconCollapse", "iconExpanded", "parent", "useVirtualScroll", "virtualScrollItemSize", "dataId"] }, { kind: "component", type: i4.LeftCardDataViewComponent, selector: "verben-left-card-data-view", inputs: ["cardDataList"] }, { kind: "component", type: i4.RightCardDataViewComponent, selector: "verben-right-card-data-view", inputs: ["parentData", "chilData", "meth"] }, { kind: "component", type: i4.CardDataViewFooterComponent, selector: "verben-card-data-view-footer" }, { kind: "component", type: i4.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: i4.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: i4.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: i4.DataXportComponent, selector: "lib-data-xport", inputs: ["data", "columns", "useImportKey", "dataFetchUrl", "dataQueryParameters", "dataQueryFunction"], outputs: ["exportDataEvent", "exportDataRangeEvent"] }, { kind: "component", type: UserRequestFormComponent, selector: "lib-user-request-form", inputs: ["roles", "showDelete", "currentData"], outputs: ["switchView", "onApproval", "onDeleteRequest"] }, { kind: "component", type: UserAccessRequestStatusBadgeComponent, selector: "lib-user-access-request-status-badge", inputs: ["status"] }, { kind: "pipe", type: i3.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
502
|
+
ngOnInit() {
|
|
503
|
+
this.facade.cardSelectionCleared$
|
|
504
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
505
|
+
.subscribe(() => this.clearCardView());
|
|
506
|
+
this.facade.loadData();
|
|
507
|
+
this.facade.loadRoles();
|
|
508
|
+
}
|
|
509
|
+
clearCardView() {
|
|
510
|
+
const view = this.cardDataView;
|
|
511
|
+
if (!view)
|
|
512
|
+
return;
|
|
513
|
+
view.clearData();
|
|
514
|
+
if (view.rightContent) {
|
|
515
|
+
view.rightContent.parentData = null;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
// ===== Filter / Sort / Search =====
|
|
519
|
+
onFilterApplied(filters) {
|
|
520
|
+
this.facade.applyFilters(filters);
|
|
521
|
+
}
|
|
522
|
+
onSortApplied(sorts) {
|
|
523
|
+
this.facade.applySorts(sorts);
|
|
524
|
+
}
|
|
525
|
+
onSearch(term) {
|
|
526
|
+
this.facade.onSearch(term);
|
|
527
|
+
}
|
|
528
|
+
onColumnsUpdated(columns) {
|
|
529
|
+
this.facade.handleColumnsUpdated(columns);
|
|
530
|
+
}
|
|
531
|
+
onLoadMore() {
|
|
532
|
+
this.facade.loadMore();
|
|
533
|
+
}
|
|
534
|
+
// ===== Table events =====
|
|
535
|
+
onViewRequest(request) {
|
|
536
|
+
this.facade.openForm(request);
|
|
537
|
+
this.vdv.toggleView();
|
|
538
|
+
}
|
|
539
|
+
requestCardClicked(selectedCard) {
|
|
540
|
+
this.facade.selectCard(selectedCard);
|
|
541
|
+
}
|
|
542
|
+
onDeleteFromTable(request) {
|
|
543
|
+
const name = `${request.FirstName} ${request.LastName}`.trim() || request.MailAddress;
|
|
544
|
+
if (confirm(`Delete request from ${name}?`)) {
|
|
545
|
+
this.facade.deleteRequest(request);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
// ===== Form events =====
|
|
549
|
+
onApprove(event) {
|
|
550
|
+
this.facade.approveRequest(event.request, event.roleId);
|
|
551
|
+
this.vdv.toggleView();
|
|
552
|
+
}
|
|
553
|
+
onReject(event) {
|
|
554
|
+
this.facade.rejectRequest(event.request, event.comment);
|
|
555
|
+
this.vdv.toggleView();
|
|
556
|
+
}
|
|
557
|
+
onDeleteRequest(request) {
|
|
558
|
+
this.facade.deleteRequest(request);
|
|
559
|
+
this.vdv.toggleView();
|
|
560
|
+
}
|
|
561
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserRequestApprovalComponent, deps: [{ token: UserAccessRequestFacade }], target: i0.ɵɵFactoryTarget.Component });
|
|
562
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: UserRequestApprovalComponent, isStandalone: true, selector: "lib-user-request-approval", inputs: { showDelete: "showDelete" }, providers: [
|
|
563
|
+
UserAccessRequestFacade,
|
|
564
|
+
UserAccessRequestState,
|
|
565
|
+
UserAccessRequestService,
|
|
566
|
+
SearchHandlerService,
|
|
567
|
+
], viewQueries: [{ propertyName: "vdv", first: true, predicate: ["vdv"], descendants: true }, { propertyName: "cardDataView", first: true, predicate: ["vdcv"], descendants: true }], ngImport: i0, template: "<div class=\"user-request-approval-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-request-approval-table [requests]=\"(facade.items$ | async) ?? []\"\n [columns]=\"(facade.visibleColumns$ | async) ?? []\" [isLoading]=\"(facade.isLoading$ | async) ?? false\"\n [showDelete]=\"showDelete\" (view)=\"onViewRequest($event)\" (delete)=\"onDeleteFromTable($event)\">\n </lib-user-request-approval-table>\n </div>\n\n <!-- Card View -->\n <div card-content>\n <verben-card-data-view #vdcv [cardDataList]=\"facade.cardData()\" borderRadius=\"12px\" dataId=\"MailAddress\"\n [border]=\"'5px'\" 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=\"MailAddress\"\n class=\"bg-secondary-100 rounded-xl border-primary border-[1px]\" [cardDataList]=\"facade.cardData()\">\n <ng-template #card let-item>\n <div (click)=\"requestCardClicked(vdcv.onItemClick(item))\" class=\"cursor-pointer h-[max-content]\">\n <lib-user-request-approval-card [request]=\"item.data\" [selected]=\"item.selected\">\n </lib-user-request-approval-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-request-approval-form [request]=\"facade.currentCardData()?.data ?? facade.emptyRequest\"\n [roles]=\"(facade.roles$ | async) ?? []\" [showDelete]=\"showDelete\" (approve)=\"onApprove($event)\"\n (reject)=\"onReject($event)\" (deleteRequest)=\"onDeleteRequest($event)\"\n (switchToTable)=\"vdv.toggleView()\">\n </lib-user-request-approval-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-request-approval-page{width:100%}.paginator-text{color:var(--vbn-color-text-muted);font-size:.875rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.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: UserRequestApprovalTableComponent, selector: "lib-user-request-approval-table", inputs: ["requests", "columns", "isLoading", "showDelete"], outputs: ["view", "delete"] }, { kind: "component", type: UserRequestApprovalCardComponent, selector: "lib-user-request-approval-card", inputs: ["request", "selected"] }, { kind: "component", type: UserRequestApprovalFormComponent, selector: "lib-user-request-approval-form", inputs: ["request", "roles", "showDelete"], outputs: ["approve", "reject", "deleteRequest", "switchToTable"] }] });
|
|
967
568
|
}
|
|
968
569
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UserRequestApprovalComponent, decorators: [{
|
|
969
570
|
type: Component,
|
|
970
|
-
args: [{ selector: 'lib-user-request-approval', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"space-y-8\">\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 isCreate: false,\n isToggle: true,\n }\"\n [buttonClass]=\"'my-custom-button-class'\"\n [iconClass]=\"'my-icon-class'\"\n [activeIconClass]=\"'my-active-icon-class'\"\n [selectedColumnCount]=\"0\"\n [selectedSortCount]=\"0\"\n [selectedFilterTableCount]=\"0\"\n (viewChange)=\"onViewChange($event)\"\n (stateChange)=\"onStateChange($event)\"\n (onSearchChange)=\"handleSearch($event)\"\n >\n <div table-content>\n <lib-data-table\n [data]=\"data()\"\n [columns]=\"visibleColumnDef\"\n [styleConfig]=\"styles\"\n (selectionChange)=\"onSelectionChange($event)\"\n >\n <ng-container libColumn=\"createdAt\">\n <ng-template #cell let-value>\n {{ value | date }}\n </ng-template>\n </ng-container>\n <ng-container libColumn=\"status\">\n <ng-template #cell let-value>\n <lib-user-access-request-status-badge\n [status]=\"value\"\n ></lib-user-access-request-status-badge>\n </ng-template>\n </ng-container>\n\n <ng-container libColumn=\"actions\">\n <ng-template #cell let-value let-deleteRow>\n <div class=\"flex gap-6\">\n <verben-svg\n (click)=\"openDetailView(value)\"\n icon=\"edit\"\n [width]=\"15\"\n [height]=\"15\"\n class=\"cursor-pointer\"\n ></verben-svg>\n <!-- <button (click)=\"openDetailView(value)\">Open</button>\n <button (click)=\"selected = cardData[rowIndex]; vdv.toggleView()\">\n Switch\n </button> -->\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 #header>\n <strong>Actions</strong>\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=\"20px\"\n >\n <verben-left-card-data-view class=\"space-y-7\">\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 <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 gap-1\">\n <label for=\"phone\" class=\"text-[10px] font-light\"\n >Medium:</label\n >\n <span id=\"phone\" class=\"text-sm truncate\">{{\n item.data.SignupType\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 >Medium:</label\n >\n <span id=\"role\" class=\"text-sm font-medium\">{{\n item.data?.SignupType\n }}</span>\n </p> -->\n\n <lib-user-access-request-status-badge\n [status]=\"item.data.RequestStatus\"\n ></lib-user-access-request-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 <lib-user-request-form\n [roles]=\"roles()\"\n [showDelete]=\"showDelete\"\n [currentData]=\"currentData\"\n (switchView)=\"vdv.toggleView()\"\n (onDeleteRequest)=\"onDelete($event)\"\n (onApproval)=\"onApprove($event)\"\n ></lib-user-request-form>\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 (filtersApplied)=\"onFilterSet($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=\"420px\"\n textColor=\"black\"\n pd=\"1rem\"\n primaryColor=\"#FFE681\"\n secondaryColor=\"#3479E9\"\n tertiaryColor=\"#404040\"\n [filterOptions]=\"filterArray\"\n [maxFilterLength]=\"3\"\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]=\"visibleColumnDef\"\n [data]=\"data()\"\n (exportDataEvent)=\"handleExport($event)\"\n >\n </lib-data-xport>\n </div>\n </verben-data-view>\n\n <div *ngIf=\"vdv.isTableView\" class=\"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}.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}.m-0{margin:0}.my-0{margin-top:0;margin-bottom:0}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.mb-0{margin-bottom:0}.mb-2{margin-bottom:.5rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.h-\\[100\\%\\]{height:100%}.h-\\[max-content\\]{height:-moz-max-content;height:max-content}.h-full{height:100%}.w-3{width:.75rem}.w-full{width:100%}.flex-1{flex:1 1 0%}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-20{gap:5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.gap-6{gap:1.5rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-y-1{row-gap:.25rem}.gap-y-2{row-gap:.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-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * 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-7>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.75rem * 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))}.overflow-auto{overflow:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.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, 1))}.border-secondary-200{border-color:#d7dbe6}.bg-primary{--tw-bg-opacity: 1;background-color:rgb(212 160 7 / var(--tw-bg-opacity, 1))}.bg-secondary{--tw-bg-opacity: 1;background-color:rgb(232 234 241 / var(--tw-bg-opacity, 1))}.bg-secondary-100{--tw-bg-opacity: 1;background-color:rgb(245 246 249 / var(--tw-bg-opacity, 1))}.bg-secondary-200{background-color:#d7dbe6}.p-3{padding:.75rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pr-1{padding-right:.25rem}.\\!text-\\[10px\\]{font-size:10px!important}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\\[10px\\]{font-size:10px}.text-\\[12px\\]{font-size:12px}.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-bold{font-weight:700}.font-light{font-weight:300}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.lowercase{text-transform:lowercase}.leading-6{line-height:1.5rem}.leading-\\[12\\.1px\\]{line-height:12.1px}.leading-\\[16\\.6px\\]{line-height:16.6px}.leading-\\[19\\.5px\\]{line-height:19.5px}.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, 1))}.text-\\[\\#3479E9\\]{--tw-text-opacity: 1;color:rgb(52 121 233 / var(--tw-text-opacity, 1))}.text-\\[\\#404040\\]{--tw-text-opacity: 1;color:rgb(64 64 64 / var(--tw-text-opacity, 1))}.text-\\[black\\]{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity, 1))}.text-muted{color:#0009}.underline{text-decoration-line:underline}.outline-none{outline:2px solid transparent;outline-offset:2px}.blur{--tw-blur: blur(8px);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)}.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)}.view-links{color:#3479e9;cursor:pointer}\n"] }]
|
|
971
|
-
|
|
571
|
+
args: [{ selector: 'lib-user-request-approval', standalone: true, imports: [
|
|
572
|
+
CommonModule,
|
|
573
|
+
DataViewModule,
|
|
574
|
+
DataColumnsModule,
|
|
575
|
+
DataFilterModule,
|
|
576
|
+
DataSortModule,
|
|
577
|
+
DataXportModule,
|
|
578
|
+
CardDataViewModule,
|
|
579
|
+
UserRequestApprovalTableComponent,
|
|
580
|
+
UserRequestApprovalCardComponent,
|
|
581
|
+
UserRequestApprovalFormComponent,
|
|
582
|
+
], providers: [
|
|
583
|
+
UserAccessRequestFacade,
|
|
584
|
+
UserAccessRequestState,
|
|
585
|
+
UserAccessRequestService,
|
|
586
|
+
SearchHandlerService,
|
|
587
|
+
], template: "<div class=\"user-request-approval-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-request-approval-table [requests]=\"(facade.items$ | async) ?? []\"\n [columns]=\"(facade.visibleColumns$ | async) ?? []\" [isLoading]=\"(facade.isLoading$ | async) ?? false\"\n [showDelete]=\"showDelete\" (view)=\"onViewRequest($event)\" (delete)=\"onDeleteFromTable($event)\">\n </lib-user-request-approval-table>\n </div>\n\n <!-- Card View -->\n <div card-content>\n <verben-card-data-view #vdcv [cardDataList]=\"facade.cardData()\" borderRadius=\"12px\" dataId=\"MailAddress\"\n [border]=\"'5px'\" 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=\"MailAddress\"\n class=\"bg-secondary-100 rounded-xl border-primary border-[1px]\" [cardDataList]=\"facade.cardData()\">\n <ng-template #card let-item>\n <div (click)=\"requestCardClicked(vdcv.onItemClick(item))\" class=\"cursor-pointer h-[max-content]\">\n <lib-user-request-approval-card [request]=\"item.data\" [selected]=\"item.selected\">\n </lib-user-request-approval-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-request-approval-form [request]=\"facade.currentCardData()?.data ?? facade.emptyRequest\"\n [roles]=\"(facade.roles$ | async) ?? []\" [showDelete]=\"showDelete\" (approve)=\"onApprove($event)\"\n (reject)=\"onReject($event)\" (deleteRequest)=\"onDeleteRequest($event)\"\n (switchToTable)=\"vdv.toggleView()\">\n </lib-user-request-approval-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-request-approval-page{width:100%}.paginator-text{color:var(--vbn-color-text-muted);font-size:.875rem}\n"] }]
|
|
588
|
+
}], ctorParameters: () => [{ type: UserAccessRequestFacade }], propDecorators: { showDelete: [{
|
|
972
589
|
type: Input
|
|
590
|
+
}], vdv: [{
|
|
591
|
+
type: ViewChild,
|
|
592
|
+
args: ['vdv']
|
|
973
593
|
}], cardDataView: [{
|
|
974
594
|
type: ViewChild,
|
|
975
595
|
args: ['vdcv']
|
|
976
|
-
}], dataView: [{
|
|
977
|
-
type: ViewChild,
|
|
978
|
-
args: ['vdv']
|
|
979
596
|
}] } });
|
|
980
597
|
|
|
598
|
+
/**
|
|
599
|
+
* Backward-compatibility shim. The components are standalone; this module keeps
|
|
600
|
+
* the historical `LibUserRequestApprovalModule` name so existing NgModule-based
|
|
601
|
+
* consumers keep working after the rebuild.
|
|
602
|
+
*/
|
|
981
603
|
class LibUserRequestApprovalModule {
|
|
982
604
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibUserRequestApprovalModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
983
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: LibUserRequestApprovalModule,
|
|
984
|
-
|
|
985
|
-
UserAccessRequestStatusBadgeComponent], imports: [CommonModule,
|
|
986
|
-
VerbenDialogueModule,
|
|
987
|
-
DataTableModule,
|
|
988
|
-
CardModule,
|
|
989
|
-
SvgModule,
|
|
990
|
-
DataViewModule,
|
|
991
|
-
CardDataViewModule,
|
|
992
|
-
SortTableModule,
|
|
993
|
-
VisibleColumnModule,
|
|
994
|
-
TableFilterModule,
|
|
995
|
-
DataExportModule,
|
|
996
|
-
DataXportModule,
|
|
997
|
-
FormsModule,
|
|
998
|
-
ReactiveFormsModule,
|
|
999
|
-
VerbenaInputModule,
|
|
1000
|
-
VerbenaButtonModule,
|
|
1001
|
-
VerbenaBadgeModule,
|
|
1002
|
-
DropDownModule], exports: [UserRequestApprovalComponent,
|
|
1003
|
-
UserAccessRequestStatusBadgeComponent] });
|
|
1004
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibUserRequestApprovalModule, imports: [CommonModule,
|
|
1005
|
-
VerbenDialogueModule,
|
|
1006
|
-
DataTableModule,
|
|
1007
|
-
CardModule,
|
|
1008
|
-
SvgModule,
|
|
1009
|
-
DataViewModule,
|
|
1010
|
-
CardDataViewModule,
|
|
1011
|
-
SortTableModule,
|
|
1012
|
-
VisibleColumnModule,
|
|
1013
|
-
TableFilterModule,
|
|
1014
|
-
DataExportModule,
|
|
1015
|
-
DataXportModule,
|
|
1016
|
-
FormsModule,
|
|
1017
|
-
ReactiveFormsModule,
|
|
1018
|
-
VerbenaInputModule,
|
|
1019
|
-
VerbenaButtonModule,
|
|
1020
|
-
VerbenaBadgeModule,
|
|
1021
|
-
DropDownModule] });
|
|
605
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: LibUserRequestApprovalModule, imports: [UserRequestApprovalComponent, UserAccessRequestStatusBadgeComponent], exports: [UserRequestApprovalComponent, UserAccessRequestStatusBadgeComponent] });
|
|
606
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibUserRequestApprovalModule, imports: [UserRequestApprovalComponent, UserAccessRequestStatusBadgeComponent] });
|
|
1022
607
|
}
|
|
1023
608
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibUserRequestApprovalModule, decorators: [{
|
|
1024
609
|
type: NgModule,
|
|
1025
610
|
args: [{
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
UserRequestFormComponent,
|
|
1029
|
-
UserAccessRequestStatusBadgeComponent,
|
|
1030
|
-
],
|
|
1031
|
-
imports: [
|
|
1032
|
-
CommonModule,
|
|
1033
|
-
VerbenDialogueModule,
|
|
1034
|
-
DataTableModule,
|
|
1035
|
-
CardModule,
|
|
1036
|
-
SvgModule,
|
|
1037
|
-
DataViewModule,
|
|
1038
|
-
CardDataViewModule,
|
|
1039
|
-
SortTableModule,
|
|
1040
|
-
VisibleColumnModule,
|
|
1041
|
-
TableFilterModule,
|
|
1042
|
-
DataExportModule,
|
|
1043
|
-
DataXportModule,
|
|
1044
|
-
FormsModule,
|
|
1045
|
-
ReactiveFormsModule,
|
|
1046
|
-
VerbenaInputModule,
|
|
1047
|
-
VerbenaButtonModule,
|
|
1048
|
-
VerbenaBadgeModule,
|
|
1049
|
-
DropDownModule,
|
|
1050
|
-
],
|
|
1051
|
-
providers: [],
|
|
1052
|
-
exports: [
|
|
1053
|
-
UserRequestApprovalComponent,
|
|
1054
|
-
UserAccessRequestStatusBadgeComponent,
|
|
1055
|
-
],
|
|
611
|
+
imports: [UserRequestApprovalComponent, UserAccessRequestStatusBadgeComponent],
|
|
612
|
+
exports: [UserRequestApprovalComponent, UserAccessRequestStatusBadgeComponent],
|
|
1056
613
|
}]
|
|
1057
614
|
}] });
|
|
1058
615
|
|