@ieeesa-npm/groups 0.15.11 → 0.15.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/esm2022/lib/assets/constants.json +27 -5
  2. package/esm2022/lib/assets/country-calling-codes.mjs +83 -0
  3. package/esm2022/lib/assets/form-validations.mjs +7 -2
  4. package/esm2022/lib/components/add-user-roster/add-user-roster.component.mjs +160 -3
  5. package/esm2022/lib/components/edit-user-roles/edit-user-roles.component.mjs +102 -4
  6. package/esm2022/lib/components/roster-import/roster-import.component.mjs +31 -3
  7. package/esm2022/lib/components/view-roster/view-roster.component.mjs +13 -4
  8. package/esm2022/lib/models/add-new-user.model.mjs +1 -1
  9. package/esm2022/lib/models/add-or-edit-user-group.model.mjs +1 -1
  10. package/esm2022/lib/models/group-user-info.model.mjs +1 -1
  11. package/esm2022/lib/models/required-profile-fields.model.mjs +2 -0
  12. package/esm2022/lib/models/table-column-schema-user-group.model.mjs +3 -1
  13. package/esm2022/lib/models/user-info.model.mjs +1 -1
  14. package/esm2022/lib/models/user.model.mjs +1 -1
  15. package/esm2022/lib/services/groups.service.mjs +58 -7
  16. package/esm2022/public-api.mjs +2 -1
  17. package/fesm2022/ieeesa-npm-groups.mjs +473 -22
  18. package/fesm2022/ieeesa-npm-groups.mjs.map +1 -1
  19. package/lib/assets/country-calling-codes.d.ts +14 -0
  20. package/lib/assets/form-validations.d.ts +3 -0
  21. package/lib/components/add-user-roster/add-user-roster.component.d.ts +18 -0
  22. package/lib/components/create-group/create-group.component.d.ts +7 -2
  23. package/lib/components/edit-user-roles/edit-user-roles.component.d.ts +19 -0
  24. package/lib/components/roster-import/roster-import.component.d.ts +8 -0
  25. package/lib/models/add-new-user.model.d.ts +3 -0
  26. package/lib/models/add-or-edit-user-group.model.d.ts +3 -0
  27. package/lib/models/group-user-info.model.d.ts +3 -0
  28. package/lib/models/required-profile-fields.model.d.ts +20 -0
  29. package/lib/models/table-column-schema-user-group.model.d.ts +3 -1
  30. package/lib/models/user-info.model.d.ts +3 -0
  31. package/lib/models/user.model.d.ts +6 -0
  32. package/lib/services/groups.service.d.ts +29 -4
  33. package/package.json +1 -1
  34. package/public-api.d.ts +1 -0
@@ -0,0 +1,14 @@
1
+ import { SelectOption } from '@ieeesa-npm/models';
2
+ /**
3
+ * Frontend-only static list of country calling (dialing) codes used by the
4
+ * Phone Number field's country-code dropdown in the add-user-roster form.
5
+ *
6
+ * This is static reference data (it does not change per request), so it is kept
7
+ * on the frontend rather than fetched from an API — no extra dependency needed.
8
+ * Both `id` and `name` are the raw calling code (e.g. `+1`) so the dropdown
9
+ * shows only the code and that same code is what gets persisted/sent to the
10
+ * backend. Countries that share a calling code are represented once.
11
+ */
12
+ export declare const COUNTRY_CALLING_CODES: SelectOption[];
13
+ /** Default country calling code option id (US/Canada), used when none is set. */
14
+ export declare const DEFAULT_COUNTRY_CALLING_CODE = "+1";
@@ -27,4 +27,7 @@ export declare const GroupsValidationPatterns: {
27
27
  representingOrgNameMinLength: number;
28
28
  representingOrganization: RegExp;
29
29
  firstOrLastName: RegExp;
30
+ phoneNumber: RegExp;
31
+ phoneNumberMaxLength: number;
32
+ addressMaxLength: number;
30
33
  };
@@ -44,6 +44,8 @@ export declare class AddUserRosterComponent implements OnInit, OnDestroy {
44
44
  groupRosterType: GroupRosterType;
45
45
  isUserExist: boolean;
46
46
  selectedOrganizations: AutoCompleteOption[];
47
+ countryCallingCodes: SelectOption[];
48
+ requiredProfileFields: string[];
47
49
  timeOutId: ReturnType<typeof setTimeout>;
48
50
  /**
49
51
  * True when the selected group's roster type is INDIVIDUAL (the only roster
@@ -173,6 +175,12 @@ export declare class AddUserRosterComponent implements OnInit, OnDestroy {
173
175
  * @memberof AddUserRosterComponent
174
176
  */
175
177
  onFormCancel(): void;
178
+ /**
179
+ * Gets the tenant's required profile fields so the add-user form only shows
180
+ * the phone/address fields the tenant has configured as required.
181
+ * @memberof AddUserRosterComponent
182
+ */
183
+ getRequiredProfileFields(): void;
176
184
  /**
177
185
  * Gets the classifications from master data.
178
186
  * @memberof AddUserRosterComponent
@@ -239,6 +247,16 @@ export declare class AddUserRosterComponent implements OnInit, OnDestroy {
239
247
  * @memberof AddUserRosterComponent
240
248
  */
241
249
  getAddNewUserPayload(formData: any): AddOrEditUserPayload | AddOrEditUserIndividualRosterPayload;
250
+ /**
251
+ * Appends the optional contact fields (phone country code, phone number and
252
+ * address) to the payload. The country code is sent only when a phone number
253
+ * is provided; phone number and address are included only when the user
254
+ * entered a value (so nulls/empties are not sent to the backend).
255
+ * @param {(AddOrEditUserPayload | AddOrEditUserIndividualRosterPayload)} payload
256
+ * @param {*} formData
257
+ * @memberof AddUserRosterComponent
258
+ */
259
+ appendContactDetailsToPayload(payload: AddOrEditUserPayload | AddOrEditUserIndividualRosterPayload, formData: any): void;
242
260
  /**
243
261
  * Disables form submit button when org name length is less than minCharToSearch and greater than zero.
244
262
  * @memberof AddUserRosterComponent
@@ -35,7 +35,7 @@ export declare class CreateGroupComponent implements OnInit, OnDestroy {
35
35
  createGroupText: {
36
36
  heading: string;
37
37
  reciprocalCredit: {
38
- selectAtLeastOneGroup: string;
38
+ selectAtLeastOneGroup: string; /** Reciprocal credit state (Working Group only) — captured for Save. */
39
39
  };
40
40
  label: {
41
41
  parentGroup: string;
@@ -60,7 +60,12 @@ export declare class CreateGroupComponent implements OnInit, OnDestroy {
60
60
  parentGroup: string;
61
61
  changeParentGroup: string;
62
62
  newParentGroup: string;
63
- groupType: string; /** Config ids of previously-saved reciprocal rows removed locally — for soft-delete on Save. */
63
+ groupType: string;
64
+ /**
65
+ * Initialize the create group form group array and component.
66
+ * @return -returns nothing
67
+ * @memberof CreateGroupComponent
68
+ */
64
69
  groupName: string;
65
70
  shortName: string;
66
71
  groupScope: string;
@@ -39,7 +39,9 @@ export declare class EditUserRolesComponent implements OnInit, OnDestroy {
39
39
  hasClassification: boolean;
40
40
  groupRosterType: GroupRosterType;
41
41
  representingOrganizations: SelectOption[];
42
+ countryCallingCodes: SelectOption[];
42
43
  orgSearchValue: string;
44
+ requiredProfileFields: string[];
43
45
  /**
44
46
  * True when the selected group's roster type is INDIVIDUAL (the only roster
45
47
  * type that shows the Representing Organization field).
@@ -111,6 +113,16 @@ export declare class EditUserRolesComponent implements OnInit, OnDestroy {
111
113
  * @memberof EditUserRolesComponent
112
114
  */
113
115
  getEditUserRolePayload(formData: any): AddOrEditUserPayload | AddOrEditUserIndividualRosterPayload;
116
+ /**
117
+ * Appends the optional contact fields (phone country code, phone number and
118
+ * address) to the payload. Reads from the combined PHONE control value
119
+ * ({ countryCode, phoneNumber }) and the address control. Sends the country
120
+ * code only when a number is present; omits empty values.
121
+ * @param {(AddOrEditUserPayload | AddOrEditUserIndividualRosterPayload)} payload
122
+ * @param {*} formData
123
+ * @memberof EditUserRolesComponent
124
+ */
125
+ appendContactDetailsToPayload(payload: AddOrEditUserPayload | AddOrEditUserIndividualRosterPayload, formData: any): void;
114
126
  /**
115
127
  * Emits form cancel event.
116
128
  * @memberof EditUserRolesComponent
@@ -140,6 +152,13 @@ export declare class EditUserRolesComponent implements OnInit, OnDestroy {
140
152
  * @memberof editUserRoleFormGroupRef
141
153
  */
142
154
  onEditUserRoleFormChange(form: FormGroup[]): void;
155
+ /**
156
+ * Gets the tenant's required profile fields so the edit-user form only shows
157
+ * the phone/address fields the tenant has configured as required. Builds the
158
+ * form once resolved (or immediately if the appId isn't available).
159
+ * @memberof EditUserRolesComponent
160
+ */
161
+ getRequiredProfileFields(): void;
143
162
  /**
144
163
  * Gets the classifications from master data.
145
164
  * @memberof EditUserRolesComponent
@@ -168,6 +168,14 @@ export declare class RosterImportComponent implements OnInit, OnDestroy {
168
168
  * @memberof RosterImportComponent
169
169
  */
170
170
  onRemoveFile(): void;
171
+ /**
172
+ * Returns from the result screen to a clean upload state so the user can
173
+ * upload a corrected file (e.g. after downloading the error log) without
174
+ * closing and reopening the import dialog. Clears the previous file,
175
+ * result, errors and job id.
176
+ * @memberof RosterImportComponent
177
+ */
178
+ onUploadNewFile(): void;
171
179
  /**
172
180
  * Runs the real import: upload → validate → confirm. The progress bar is
173
181
  * shown in indeterminate mode while the chain is in flight, then the
@@ -5,6 +5,9 @@ export interface SearchUserByEmailResponse {
5
5
  userId: string | null;
6
6
  email: string;
7
7
  name: string;
8
+ phoneCountryCode?: string | null;
9
+ phoneNumber?: string | null;
10
+ address?: string | null;
8
11
  };
9
12
  }
10
13
  export interface GetUserDetailsPayload {
@@ -13,6 +13,9 @@ export interface AddOrEditUserRolePayload {
13
13
  email: string;
14
14
  firstName?: string;
15
15
  lastName?: string;
16
+ phoneCountryCode?: string;
17
+ phoneNumber?: string;
18
+ address?: string;
16
19
  }
17
20
  export interface AddOrEditIndividualRosterPayload extends AddOrEditUserRolePayload {
18
21
  classification?: {
@@ -7,4 +7,7 @@ export interface GroupUserInfo {
7
7
  organization?: string;
8
8
  memberStatus?: string;
9
9
  canDelete?: boolean;
10
+ phoneCountryCode?: string | null;
11
+ phoneNumber?: string | null;
12
+ address?: string | null;
10
13
  }
@@ -0,0 +1,20 @@
1
+ export interface RequiredProfileFieldsConfiguration {
2
+ configFieldValue?: {
3
+ requiredFields?: string[];
4
+ };
5
+ }
6
+ export interface RequiredProfileFieldsResponse {
7
+ status: boolean;
8
+ message?: string;
9
+ body?: RequiredProfileFieldsConfiguration[];
10
+ }
11
+ /**
12
+ * Shape of the tenant required-profile-fields value cached in local storage by
13
+ * the hosting application at login (storage key `REQUIRED_PROFILE_FIELDS`). The
14
+ * add-user / edit-user forms read this cache to decide which optional fields
15
+ * (phone/address/employer) to show.
16
+ */
17
+ export interface CachedRequiredProfileFields {
18
+ appId: string;
19
+ requiredFields: string[];
20
+ }
@@ -5,5 +5,7 @@ export declare enum TableColumnSchemaUserGroup {
5
5
  EMPLOYER = "employer",
6
6
  CLASSIFICATION = "classification",
7
7
  ORGANIZATION = "org_name",
8
- MEMBER_TYPE = "memberType"
8
+ MEMBER_TYPE = "memberType",
9
+ PHONE_NUMBER = "phone_number",
10
+ ADDRESS = "address"
9
11
  }
@@ -2,4 +2,7 @@ export interface UserInfo {
2
2
  email: string;
3
3
  name: string;
4
4
  userId: string | null;
5
+ phoneCountryCode?: string | null;
6
+ phoneNumber?: string | null;
7
+ address?: string | null;
5
8
  }
@@ -10,6 +10,9 @@ export interface User {
10
10
  memberStatus: string | null;
11
11
  organization: string | null;
12
12
  employer: string | null;
13
+ phoneCountryCode: string | null;
14
+ phoneNumber: string | null;
15
+ address: string | null;
13
16
  checked?: boolean;
14
17
  canDelete?: boolean;
15
18
  }
@@ -28,6 +31,9 @@ export interface GetGroupUsersResponse {
28
31
  classification: Classification | null;
29
32
  organizations: Organization[] | null;
30
33
  employer: Employer | null;
34
+ phoneCountryCode?: string | null;
35
+ phoneNumber?: string | null;
36
+ address?: string | null;
31
37
  canDelete?: boolean;
32
38
  }[];
33
39
  }
@@ -1,7 +1,7 @@
1
1
  import { Observable, BehaviorSubject } from 'rxjs';
2
2
  import { CreateGroupPayload, CreateGroupResponse } from '../models/create-group.model';
3
3
  import { BusinessRule, GroupTypeConfiguration, GroupTypeConfigValue, GroupTypeResponse } from '../models/group-types.model';
4
- import { AlertsService, HttpService } from '@ieeesa-npm/utility';
4
+ import { AlertsService, HttpService, StorageService } from '@ieeesa-npm/utility';
5
5
  import { GetGroupResponse, GetGroupsPayload } from '../models/view-group.model';
6
6
  import { DeleteGroupPayload } from '../models/delete-group.model';
7
7
  import { GroupInfo } from '../models/group-info.model';
@@ -18,7 +18,7 @@ import { GetUserDetailsPayload, SearchUserByEmailResponse } from '../models/add-
18
18
  import { OrganizationRequestPayload, OrganizationResponse } from '../models/organization.model';
19
19
  import { ClassificationResponse } from '../models/classification.model';
20
20
  import { GroupRosterType } from '../models/roster-type.model';
21
- import { CheckboxOption } from '@ieeesa-npm/models';
21
+ import { CheckboxOption, SelectOption } from '@ieeesa-npm/models';
22
22
  import { FormControlStatus } from '@angular/forms';
23
23
  import { GroupPermission, UserPermission } from '../models/group-permissions.model';
24
24
  import { PermissionType } from '../models/permission-type.model';
@@ -35,6 +35,7 @@ export declare class GroupsService {
35
35
  private userPermissionsService;
36
36
  private groupPermissionsService;
37
37
  alertService: AlertsService;
38
+ private storageService;
38
39
  groupsText: {
39
40
  ER1000: string;
40
41
  ER1001: string;
@@ -128,7 +129,7 @@ export declare class GroupsService {
128
129
  userInfo: LoggedInUserInfo;
129
130
  memberTypes: Role[];
130
131
  representingOrganizations: RepresentingOrganization[];
131
- constructor(httpService: HttpService, userPermissionsService: UserPermissionsService, groupPermissionsService: GroupPermissionsMapService, alertService: AlertsService);
132
+ constructor(httpService: HttpService, userPermissionsService: UserPermissionsService, groupPermissionsService: GroupPermissionsMapService, alertService: AlertsService, storageService: StorageService);
132
133
  setAppConfig(apiBaseUrl: string, userPermission: any): void;
133
134
  /**
134
135
  * Stores the tenant-level required profile fields provided by the host app.
@@ -138,6 +139,21 @@ export declare class GroupsService {
138
139
  setRequiredProfileFields(requiredProfileFields: string[]): void;
139
140
  /**
140
141
  * Returns the tenant-level required profile fields (never null).
142
+ *
143
+ * Reads the local storage cache the hosting application writes at login (key
144
+ * `REQUIRED_PROFILE_FIELDS`) as the source of truth, so the add-user /
145
+ * edit-user forms always reflect the tenant configuration regardless of the
146
+ * @Input/resolver timing.
147
+ *
148
+ * The cache is only trusted when it is well-formed for the active
149
+ * application: its `appId` must match the current user's `appId` and its
150
+ * `requiredFields` must be an array. This guards against (a) a stale cache
151
+ * from a previously opened application applying another tenant's fields, and
152
+ * (b) a malformed cache crashing the forms when callers run
153
+ * `requiredFields.includes(...)` on a non-array value. When the cache is
154
+ * missing, for another app, or malformed, it falls back to the in-memory
155
+ * value set via {@link setRequiredProfileFields} (the host @Input), then to
156
+ * an empty list.
141
157
  * @return {string[]}
142
158
  * @memberof GroupsService
143
159
  */
@@ -384,7 +400,9 @@ export declare class GroupsService {
384
400
  */
385
401
  setUserInfo(userInfo: LoggedInUserInfo): void;
386
402
  /**
387
- * Returns the logged in user information.
403
+ * Returns the logged in user information. Falls back to the USER_INFO blob
404
+ * the host app persists to local storage when the userInfo input hasn't
405
+ * been set yet (e.g. host wiring not completed or timing race on init).
388
406
  * @return {LoggedInUserInfo}
389
407
  * @memberof GroupsService
390
408
  */
@@ -456,6 +474,13 @@ export declare class GroupsService {
456
474
  * @memberof GroupsService
457
475
  */
458
476
  getMemberTypes(): Role[];
477
+ /**
478
+ * Returns the frontend-only static list of country calling codes for the
479
+ * Phone Number field's country-code dropdown.
480
+ * @return {SelectOption[]}
481
+ * @memberof GroupsService
482
+ */
483
+ getCountryCallingCodes(): SelectOption[];
459
484
  /** Path prefix (relative to apiBaseUrl) for the reciprocal-credit endpoints. */
460
485
  private readonly RECIPROCAL_BASE_PATH;
461
486
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ieeesa-npm/groups",
3
- "version": "0.15.11",
3
+ "version": "0.15.13",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^16.1.0",
6
6
  "@angular/core": "^16.1.0"
package/public-api.d.ts CHANGED
@@ -28,6 +28,7 @@ export * from './lib/models/roster-type.model';
28
28
  export * from './lib/models/table-column-schema-user-group.model';
29
29
  export * from './lib/models/parent-groups-info.model';
30
30
  export * from './lib/models/reciprocal-credit.model';
31
+ export * from './lib/models/required-profile-fields.model';
31
32
  export * from './lib/services/groups.service';
32
33
  export * from './lib/services/roster-export.service';
33
34
  export * from './lib/services/roster-import-api.service';