@ieeesa-npm/groups 0.8.2 → 0.8.3
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/esm2022/lib/assets/constants.json +13 -2
- package/esm2022/lib/assets/form-validations.mjs +3 -1
- package/esm2022/lib/components/add-user-roster/add-user-roster.component.mjs +158 -84
- package/esm2022/lib/models/add-or-edit-user-group.model.mjs +1 -1
- package/fesm2022/ieeesa-npm-groups.mjs +172 -85
- package/fesm2022/ieeesa-npm-groups.mjs.map +1 -1
- package/lib/assets/form-validations.d.ts +1 -0
- package/lib/components/add-user-roster/add-user-roster.component.d.ts +16 -1
- package/lib/models/add-or-edit-user-group.model.d.ts +3 -1
- package/lib/services/groups.service.d.ts +25 -1
- package/package.json +3 -3
|
@@ -28,6 +28,8 @@ var addUserRoster = {
|
|
|
28
28
|
leftButtonLabel: "Cancel",
|
|
29
29
|
saveButtonLabel: "Save",
|
|
30
30
|
fullName: "Name",
|
|
31
|
+
firstName: "First Name",
|
|
32
|
+
lastName: "Last Name",
|
|
31
33
|
role: "Role",
|
|
32
34
|
classification: "Classification",
|
|
33
35
|
representingOrganization: "Representing Organization",
|
|
@@ -35,6 +37,8 @@ var addUserRoster = {
|
|
|
35
37
|
ariaLabel: {
|
|
36
38
|
email: "Email Address",
|
|
37
39
|
fullName: "Full name",
|
|
40
|
+
firstName: "First Name",
|
|
41
|
+
lastName: "Last Name",
|
|
38
42
|
role: "Role",
|
|
39
43
|
classification: "Classification",
|
|
40
44
|
memberType: "Member Type",
|
|
@@ -43,6 +47,8 @@ var addUserRoster = {
|
|
|
43
47
|
ariaDescribedById: {
|
|
44
48
|
email: "ariaEmailAddress",
|
|
45
49
|
fullName: "ariaFullName",
|
|
50
|
+
firstName: "ariaFirstName",
|
|
51
|
+
lastName: "ariaLastName",
|
|
46
52
|
role: "ariaRole",
|
|
47
53
|
classification: "ariaClassification",
|
|
48
54
|
memberType: "ariaMemberType",
|
|
@@ -58,7 +64,8 @@ var addUserRoster = {
|
|
|
58
64
|
},
|
|
59
65
|
pattern: {
|
|
60
66
|
email: "Please enter valid email.",
|
|
61
|
-
representingOrganization: "Representing Organization contains invalid characters. Please enter alphanumeric, special characters and whitespace only."
|
|
67
|
+
representingOrganization: "Representing Organization contains invalid characters. Please enter alphanumeric, special characters and whitespace only.",
|
|
68
|
+
firstOrLastName: "This field is required."
|
|
62
69
|
}
|
|
63
70
|
},
|
|
64
71
|
success: {
|
|
@@ -68,6 +75,8 @@ var addUserRoster = {
|
|
|
68
75
|
supportText: {
|
|
69
76
|
emailAddress: "Please enter valid email address which includes @ symbol, dot (.) and domain. For example, user@ieee.org",
|
|
70
77
|
fullName: "Enter user full name.",
|
|
78
|
+
firstName: "Enter user's first name.",
|
|
79
|
+
lastName: "Enter user's last name.",
|
|
71
80
|
role: "<strong>Note:</strong> In order to remove all roles, please remove the user from the system user group.",
|
|
72
81
|
roleForIndividualRoster: "Select Role(s) from the options.",
|
|
73
82
|
classification: "Select Classification from the dropdown.",
|
|
@@ -293,7 +302,9 @@ var errors = {
|
|
|
293
302
|
"1032": "No record found!",
|
|
294
303
|
"1033": "Please enter at least 3 characters to perform search operation.",
|
|
295
304
|
"1034": "No record(s) found.",
|
|
296
|
-
"
|
|
305
|
+
"1035": "First name is required.",
|
|
306
|
+
"1036": "Last name is required.",
|
|
307
|
+
"2001": "No user found. Please add details for the new user.",
|
|
297
308
|
"2002": "Role does not belong to the group type.",
|
|
298
309
|
"2010": "User not found.",
|
|
299
310
|
"2011": "User not found.",
|
|
@@ -357,6 +368,8 @@ const GroupsValidationPatterns = {
|
|
|
357
368
|
representingOrgNameMinLength: 3,
|
|
358
369
|
// Representing Organization field regular expression which accept Alpha Numeric, Special Characters and whitespace.
|
|
359
370
|
representingOrganization: /^(?=.*[a-zA-Z])[\w\s!"#$%&'()*+,-.\/\:;<=>?@[\]^_`{|}~\\]+$/i,
|
|
371
|
+
// First or Last Name field regular expression which does not allow only whitespace or empty string.
|
|
372
|
+
firstOrLastName: /^(?!\s*$).+/
|
|
360
373
|
};
|
|
361
374
|
|
|
362
375
|
/* eslint-disable no-unused-vars */
|
|
@@ -2523,6 +2536,7 @@ class AddUserRosterComponent {
|
|
|
2523
2536
|
this.memberTypes = [];
|
|
2524
2537
|
this.organizations = [];
|
|
2525
2538
|
this.hasClassification = false;
|
|
2539
|
+
this.isUserExist = false;
|
|
2526
2540
|
this.submitFormResponse = new EventEmitter();
|
|
2527
2541
|
this.formCancel = new EventEmitter();
|
|
2528
2542
|
}
|
|
@@ -2536,12 +2550,7 @@ class AddUserRosterComponent {
|
|
|
2536
2550
|
this.hasClassification = groupType?.hasClassification ?? false;
|
|
2537
2551
|
this.groupRosterType = groupType?.rosterType;
|
|
2538
2552
|
if (!this.groupRosterType)
|
|
2539
|
-
this.
|
|
2540
|
-
status: 'custom',
|
|
2541
|
-
message: this.constants?.errors?.ER1001,
|
|
2542
|
-
alertType: AlertType.ERROR,
|
|
2543
|
-
isCloseNeeded: true,
|
|
2544
|
-
});
|
|
2553
|
+
this.showAlertMessage(this.constants?.errors?.ER1001, AlertType.ERROR);
|
|
2545
2554
|
else {
|
|
2546
2555
|
if (this.groupRosterType === GroupRosterType.INDIVIDUAL) {
|
|
2547
2556
|
if (this.hasClassification)
|
|
@@ -2605,12 +2614,34 @@ class AddUserRosterComponent {
|
|
|
2605
2614
|
next: (res) => {
|
|
2606
2615
|
if (res?.status) {
|
|
2607
2616
|
this.userInfo = res?.body;
|
|
2617
|
+
this.isUserExist = true;
|
|
2608
2618
|
this.validateUserExistence();
|
|
2609
2619
|
}
|
|
2610
2620
|
},
|
|
2611
2621
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2612
2622
|
error: (error) => {
|
|
2613
|
-
this.
|
|
2623
|
+
this.isUserExist = false;
|
|
2624
|
+
const errorCodes = error?.error?.body?.errorCodes;
|
|
2625
|
+
if (errorCodes?.includes('2001')) {
|
|
2626
|
+
this.isSearchUserForm = false;
|
|
2627
|
+
this.rightButtonLabel =
|
|
2628
|
+
this.addUserRosterTexts?.label?.saveButtonLabel;
|
|
2629
|
+
this.isSubmitButtonDisabled = true;
|
|
2630
|
+
if (!this.isAddUserFormEmailSearch) {
|
|
2631
|
+
this.createAddUserFormGroup(email);
|
|
2632
|
+
if (this.groupRosterType === GroupRosterType.INDIVIDUAL) {
|
|
2633
|
+
this.updateAddUserFormGroup();
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2636
|
+
else {
|
|
2637
|
+
this.addUserFormGroupRef?.get('firstName')?.setValue('');
|
|
2638
|
+
this.addUserFormGroupRef?.get('lastName')?.setValue('');
|
|
2639
|
+
}
|
|
2640
|
+
this.showAlertMessage(this.constants?.errors?.['2001'], AlertType.ERROR);
|
|
2641
|
+
}
|
|
2642
|
+
else {
|
|
2643
|
+
this.handleErrors(error);
|
|
2644
|
+
}
|
|
2614
2645
|
},
|
|
2615
2646
|
});
|
|
2616
2647
|
}
|
|
@@ -2630,12 +2661,7 @@ class AddUserRosterComponent {
|
|
|
2630
2661
|
.pipe(takeUntil$1(this.destroy$))
|
|
2631
2662
|
?.subscribe({
|
|
2632
2663
|
next: () => {
|
|
2633
|
-
this.
|
|
2634
|
-
status: 'custom',
|
|
2635
|
-
message: this.constants?.errors?.['1022'],
|
|
2636
|
-
alertType: AlertType.ERROR,
|
|
2637
|
-
isCloseNeeded: true,
|
|
2638
|
-
});
|
|
2664
|
+
this.showAlertMessage(this.constants?.errors?.['1022'], AlertType.ERROR);
|
|
2639
2665
|
},
|
|
2640
2666
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2641
2667
|
error: (error) => {
|
|
@@ -2647,66 +2673,7 @@ class AddUserRosterComponent {
|
|
|
2647
2673
|
if (!this.isAddUserFormEmailSearch) {
|
|
2648
2674
|
this.selectedUserRoles = [];
|
|
2649
2675
|
this.isSubmitButtonDisabled = true;
|
|
2650
|
-
this.
|
|
2651
|
-
formGroup: [
|
|
2652
|
-
{
|
|
2653
|
-
legend: '',
|
|
2654
|
-
controls: [
|
|
2655
|
-
{
|
|
2656
|
-
type: FormControlType.SEARCH,
|
|
2657
|
-
label: this.addUserRosterTexts?.label?.email + '*',
|
|
2658
|
-
controlName: 'emailSearch',
|
|
2659
|
-
value: this.userInfo?.email,
|
|
2660
|
-
searchType: SearchType.ON_CLICK,
|
|
2661
|
-
validation: [
|
|
2662
|
-
Validators.required,
|
|
2663
|
-
Validators.pattern(GroupsValidationPatterns.email),
|
|
2664
|
-
],
|
|
2665
|
-
supportMessage: this.addUserRosterTexts?.supportText?.emailAddress,
|
|
2666
|
-
requiredErrorMessage: this.addUserRosterTexts?.message?.error?.required,
|
|
2667
|
-
patternErrorMessage: this.addUserRosterTexts?.message?.error?.pattern
|
|
2668
|
-
?.email,
|
|
2669
|
-
ariaLabel: this.addUserRosterTexts?.label?.ariaLabel?.email,
|
|
2670
|
-
ariaDescribedById: this.addUserRosterTexts?.label?.ariaDescribedById
|
|
2671
|
-
?.email,
|
|
2672
|
-
},
|
|
2673
|
-
{
|
|
2674
|
-
type: FormControlType.TEXT_AREA,
|
|
2675
|
-
label: this.addUserRosterTexts?.label?.fullName + '*',
|
|
2676
|
-
controlName: 'fullName',
|
|
2677
|
-
value: this.userInfo?.name,
|
|
2678
|
-
validation: [Validators.required],
|
|
2679
|
-
requiredErrorMessage: this.addUserRosterTexts?.message?.error?.required,
|
|
2680
|
-
isReadonly: true,
|
|
2681
|
-
ariaMultiline: false,
|
|
2682
|
-
ariaLabel: this.addUserRosterTexts?.label?.ariaLabel?.fullName,
|
|
2683
|
-
ariaDescribedById: this.addUserRosterTexts?.label?.ariaDescribedById
|
|
2684
|
-
?.fullName,
|
|
2685
|
-
},
|
|
2686
|
-
{
|
|
2687
|
-
type: FormControlType.CHECKBOX,
|
|
2688
|
-
label: this.groupRosterType === GroupRosterType.INDIVIDUAL
|
|
2689
|
-
? this.addUserRosterTexts?.label?.role
|
|
2690
|
-
: this.addUserRosterTexts?.label?.role + '*',
|
|
2691
|
-
controlName: 'roles',
|
|
2692
|
-
checkboxOptions: this.userRoles,
|
|
2693
|
-
minSelectionRequired: 1,
|
|
2694
|
-
ariaLabel: this.addUserRosterTexts?.label?.ariaLabel?.role,
|
|
2695
|
-
ariaDescribedById: this.addUserRosterTexts?.label?.ariaDescribedById
|
|
2696
|
-
?.role,
|
|
2697
|
-
supportMessage: this.groupRosterType === GroupRosterType.INDIVIDUAL
|
|
2698
|
-
? this.addUserRosterTexts?.supportText
|
|
2699
|
-
?.roleForIndividualRoster
|
|
2700
|
-
: this.addUserRosterTexts?.supportText?.role,
|
|
2701
|
-
requiredErrorMessage: this.addUserRosterTexts?.message?.error?.required,
|
|
2702
|
-
validation: this.groupRosterType === GroupRosterType.INDIVIDUAL
|
|
2703
|
-
? []
|
|
2704
|
-
: [Validators.required],
|
|
2705
|
-
},
|
|
2706
|
-
],
|
|
2707
|
-
},
|
|
2708
|
-
],
|
|
2709
|
-
};
|
|
2676
|
+
this.createAddUserFormGroup();
|
|
2710
2677
|
if (this.groupRosterType === GroupRosterType.INDIVIDUAL) {
|
|
2711
2678
|
this.updateAddUserFormGroup();
|
|
2712
2679
|
}
|
|
@@ -2727,6 +2694,107 @@ class AddUserRosterComponent {
|
|
|
2727
2694
|
},
|
|
2728
2695
|
});
|
|
2729
2696
|
}
|
|
2697
|
+
/**
|
|
2698
|
+
* Initialize the add user form group array.
|
|
2699
|
+
* @param {string} [email]
|
|
2700
|
+
* @memberof AddUserRosterComponent
|
|
2701
|
+
*/
|
|
2702
|
+
createAddUserFormGroup(email) {
|
|
2703
|
+
this.addUserFormGroup = {
|
|
2704
|
+
formGroup: [
|
|
2705
|
+
{
|
|
2706
|
+
legend: '',
|
|
2707
|
+
controls: [
|
|
2708
|
+
{
|
|
2709
|
+
type: FormControlType.SEARCH,
|
|
2710
|
+
label: this.addUserRosterTexts?.label?.email + '*',
|
|
2711
|
+
controlName: 'emailSearch',
|
|
2712
|
+
value: this.isUserExist ? this.userInfo?.email : email,
|
|
2713
|
+
searchType: SearchType.ON_CLICK,
|
|
2714
|
+
validation: [
|
|
2715
|
+
Validators.required,
|
|
2716
|
+
Validators.pattern(GroupsValidationPatterns.email),
|
|
2717
|
+
],
|
|
2718
|
+
supportMessage: this.addUserRosterTexts?.supportText?.emailAddress,
|
|
2719
|
+
requiredErrorMessage: this.addUserRosterTexts?.message?.error?.required,
|
|
2720
|
+
patternErrorMessage: this.addUserRosterTexts?.message?.error?.pattern?.email,
|
|
2721
|
+
ariaLabel: this.addUserRosterTexts?.label?.ariaLabel?.email,
|
|
2722
|
+
ariaDescribedById: this.addUserRosterTexts?.label?.ariaDescribedById?.email,
|
|
2723
|
+
},
|
|
2724
|
+
...(this.isUserExist
|
|
2725
|
+
? [
|
|
2726
|
+
{
|
|
2727
|
+
type: FormControlType.TEXT_AREA,
|
|
2728
|
+
label: this.addUserRosterTexts?.label?.fullName + '*',
|
|
2729
|
+
controlName: 'fullName',
|
|
2730
|
+
value: this.userInfo?.name,
|
|
2731
|
+
validation: [Validators.required],
|
|
2732
|
+
requiredErrorMessage: this.addUserRosterTexts?.message?.error?.required,
|
|
2733
|
+
isReadonly: true,
|
|
2734
|
+
ariaMultiline: false,
|
|
2735
|
+
ariaLabel: this.addUserRosterTexts?.label?.ariaLabel?.fullName,
|
|
2736
|
+
ariaDescribedById: this.addUserRosterTexts?.label?.ariaDescribedById
|
|
2737
|
+
?.fullName,
|
|
2738
|
+
},
|
|
2739
|
+
]
|
|
2740
|
+
: [
|
|
2741
|
+
{
|
|
2742
|
+
type: FormControlType.INPUT,
|
|
2743
|
+
label: this.addUserRosterTexts?.label?.firstName + '*',
|
|
2744
|
+
controlName: 'firstName',
|
|
2745
|
+
validation: [
|
|
2746
|
+
Validators.required,
|
|
2747
|
+
Validators.pattern(GroupsValidationPatterns.firstOrLastName),
|
|
2748
|
+
],
|
|
2749
|
+
requiredErrorMessage: this.addUserRosterTexts?.message?.error?.required,
|
|
2750
|
+
patternErrorMessage: this.addUserRosterTexts?.message?.error?.pattern
|
|
2751
|
+
?.firstOrLastName,
|
|
2752
|
+
ariaLabel: this.addUserRosterTexts?.label?.ariaLabel?.firstName,
|
|
2753
|
+
ariaDescribedById: this.addUserRosterTexts?.label?.ariaDescribedById
|
|
2754
|
+
?.firstName,
|
|
2755
|
+
supportMessage: this.addUserRosterTexts?.supportText?.firstName,
|
|
2756
|
+
},
|
|
2757
|
+
{
|
|
2758
|
+
type: FormControlType.INPUT,
|
|
2759
|
+
label: this.addUserRosterTexts?.label?.lastName + '*',
|
|
2760
|
+
controlName: 'lastName',
|
|
2761
|
+
validation: [
|
|
2762
|
+
Validators.required,
|
|
2763
|
+
Validators.pattern(GroupsValidationPatterns.firstOrLastName),
|
|
2764
|
+
],
|
|
2765
|
+
requiredErrorMessage: this.addUserRosterTexts?.message?.error?.required,
|
|
2766
|
+
patternErrorMessage: this.addUserRosterTexts?.message?.error?.pattern
|
|
2767
|
+
?.firstOrLastName,
|
|
2768
|
+
ariaLabel: this.addUserRosterTexts?.label?.ariaLabel?.lastName,
|
|
2769
|
+
ariaDescribedById: this.addUserRosterTexts?.label?.ariaDescribedById
|
|
2770
|
+
?.lastName,
|
|
2771
|
+
supportMessage: this.addUserRosterTexts?.supportText?.lastName,
|
|
2772
|
+
},
|
|
2773
|
+
]),
|
|
2774
|
+
{
|
|
2775
|
+
type: FormControlType.CHECKBOX,
|
|
2776
|
+
label: this.groupRosterType === GroupRosterType.INDIVIDUAL
|
|
2777
|
+
? this.addUserRosterTexts?.label?.role
|
|
2778
|
+
: this.addUserRosterTexts?.label?.role + '*',
|
|
2779
|
+
controlName: 'roles',
|
|
2780
|
+
checkboxOptions: this.userRoles,
|
|
2781
|
+
minSelectionRequired: 1,
|
|
2782
|
+
ariaLabel: this.addUserRosterTexts?.label?.ariaLabel?.role,
|
|
2783
|
+
ariaDescribedById: this.addUserRosterTexts?.label?.ariaDescribedById?.role,
|
|
2784
|
+
supportMessage: this.groupRosterType === GroupRosterType.INDIVIDUAL
|
|
2785
|
+
? this.addUserRosterTexts?.supportText
|
|
2786
|
+
?.roleForIndividualRoster
|
|
2787
|
+
: this.addUserRosterTexts?.supportText?.role,
|
|
2788
|
+
requiredErrorMessage: this.addUserRosterTexts?.message?.error?.required,
|
|
2789
|
+
validation: this.groupRosterType === GroupRosterType.INDIVIDUAL
|
|
2790
|
+
? []
|
|
2791
|
+
: [Validators.required],
|
|
2792
|
+
},
|
|
2793
|
+
],
|
|
2794
|
+
},
|
|
2795
|
+
],
|
|
2796
|
+
};
|
|
2797
|
+
}
|
|
2730
2798
|
/**
|
|
2731
2799
|
* Adds classification, Member Type and Representing Organization form controls while adding new user to an individual group roster.
|
|
2732
2800
|
* @memberof AddUserRosterComponent
|
|
@@ -2965,12 +3033,7 @@ class AddUserRosterComponent {
|
|
|
2965
3033
|
if (Array.isArray(errorCodes) && !error?.error?.status) {
|
|
2966
3034
|
if (errorCodes[0] !== '3004') {
|
|
2967
3035
|
const errorMessage = this.groupService.parseErrorMessage(errorCodes);
|
|
2968
|
-
this.
|
|
2969
|
-
status: 'custom',
|
|
2970
|
-
message: errorMessage,
|
|
2971
|
-
alertType: AlertType.ERROR,
|
|
2972
|
-
isCloseNeeded: true,
|
|
2973
|
-
});
|
|
3036
|
+
this.showAlertMessage(errorMessage, AlertType.ERROR);
|
|
2974
3037
|
}
|
|
2975
3038
|
}
|
|
2976
3039
|
else if (error && error instanceof HttpErrorResponse) {
|
|
@@ -2999,8 +3062,9 @@ class AddUserRosterComponent {
|
|
|
2999
3062
|
if (this.groupRosterType === GroupRosterType.INDIVIDUAL) {
|
|
3000
3063
|
payload = {
|
|
3001
3064
|
payload: {
|
|
3002
|
-
email: this.
|
|
3003
|
-
|
|
3065
|
+
email: this.isUserExist
|
|
3066
|
+
? this.userInfo?.email
|
|
3067
|
+
: formData?.emailSearch,
|
|
3004
3068
|
roles: this.selectedUserRoles,
|
|
3005
3069
|
groupId: this.groupService.selectedGroupInfo?.groupId,
|
|
3006
3070
|
memberStatus: {
|
|
@@ -3024,12 +3088,20 @@ class AddUserRosterComponent {
|
|
|
3024
3088
|
else
|
|
3025
3089
|
payload = {
|
|
3026
3090
|
payload: {
|
|
3027
|
-
email: this.
|
|
3091
|
+
email: this.isUserExist
|
|
3092
|
+
? this.userInfo?.email
|
|
3093
|
+
: formData?.emailSearch,
|
|
3028
3094
|
roles: this.selectedUserRoles,
|
|
3029
|
-
userId: this.userInfo?.userId,
|
|
3030
3095
|
groupId: this.groupService.selectedGroupInfo?.groupId,
|
|
3031
3096
|
},
|
|
3032
3097
|
};
|
|
3098
|
+
if (this.isUserExist) {
|
|
3099
|
+
payload.payload.userId = this.userInfo?.userId;
|
|
3100
|
+
}
|
|
3101
|
+
else {
|
|
3102
|
+
payload.payload.firstName = formData?.firstName?.trim();
|
|
3103
|
+
payload.payload.lastName = formData?.lastName?.trim();
|
|
3104
|
+
}
|
|
3033
3105
|
return payload;
|
|
3034
3106
|
}
|
|
3035
3107
|
/**
|
|
@@ -3040,6 +3112,21 @@ class AddUserRosterComponent {
|
|
|
3040
3112
|
this.updateFormControlOptions('representingOrg', 'autoCompleteOptions', []);
|
|
3041
3113
|
this.isSubmitButtonDisabled = true;
|
|
3042
3114
|
}
|
|
3115
|
+
/**
|
|
3116
|
+
* Handles alerts for error, warning.
|
|
3117
|
+
* @param {(string | string[])} message -error or warning message
|
|
3118
|
+
* @param {AlertType} alertType
|
|
3119
|
+
* @return -returns nothing
|
|
3120
|
+
* @memberof AddUserRosterComponent
|
|
3121
|
+
*/
|
|
3122
|
+
showAlertMessage(message, alertType) {
|
|
3123
|
+
this.alertService?.showMessage({
|
|
3124
|
+
status: 'custom',
|
|
3125
|
+
message: message,
|
|
3126
|
+
alertType: alertType,
|
|
3127
|
+
isCloseNeeded: true,
|
|
3128
|
+
});
|
|
3129
|
+
}
|
|
3043
3130
|
/**
|
|
3044
3131
|
* NgOnDestroy performs necessary cleanup tasks, such as unsubscribing from subscription when the component is being destroyed.
|
|
3045
3132
|
* @memberof AddUserRosterComponent
|