@ieeesa-npm/groups 0.15.10 → 0.15.11

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.
@@ -74,8 +74,46 @@ export declare class RosterImportComponent implements OnInit, OnDestroy {
74
74
  /** Accepted file extensions (must match the BE contract: only .csv / .xlsx). */
75
75
  readonly ACCEPTED_EXTENSIONS: string[];
76
76
  constructor(rosterImportApiService: RosterImportApiService, groupService: GroupsService);
77
- /** Required column headers for display. */
77
+ /**
78
+ * Required column headers for display and the sample file. This is the static
79
+ * base set from constants PLUS any tenant-level required profile fields the
80
+ * host app configured (e.g. phone / address / employer), mapped to friendly
81
+ * headers and de-duplicated (case-insensitive) against the base columns.
82
+ * @return {string[]}
83
+ */
78
84
  get requiredColumns(): string[];
85
+ /**
86
+ * Appends the tenant-configured columns (from {@link tenantExtraColumns}) to
87
+ * the base column headers.
88
+ * @param {string[]} base - The static base column headers.
89
+ * @return {string[]}
90
+ * @memberof RosterImportComponent
91
+ */
92
+ private mergeTenantColumns;
93
+ /**
94
+ * Resolves the tenant-configured required profile fields into the EXTRA
95
+ * columns to append after the base set — the single source of truth shared by
96
+ * both the header list ({@link requiredColumns}) and the sample file
97
+ * ({@link downloadSampleFile}) so the two never drift out of alignment.
98
+ *
99
+ * Each field becomes one column with its friendly `label` (known keys use the
100
+ * label map; unknown keys fall back to a title-cased key) and a `sampleValue`
101
+ * for the sample row. Fields whose label already exists in the base set
102
+ * (case-insensitive) are skipped so a tenant field like "employer" that is
103
+ * already a base column is not duplicated.
104
+ * @param {string[]} base - The static base column headers.
105
+ * @return {{ label: string; sampleValue: string }[]}
106
+ * @memberof RosterImportComponent
107
+ */
108
+ private tenantExtraColumns;
109
+ /**
110
+ * Maps a tenant field key to its display header. Known keys use the configured
111
+ * label map; unknown keys fall back to a title-cased key.
112
+ * @param {string} field - The tenant field key (e.g. 'phone').
113
+ * @return {string}
114
+ * @memberof RosterImportComponent
115
+ */
116
+ private tenantFieldLabel;
79
117
  /** Comma-separated accepted file types for the input element. */
80
118
  get acceptedFileTypes(): string;
81
119
  /** The target group id from the dialog payload (falls back to selection). */
@@ -154,14 +192,16 @@ export declare class RosterImportComponent implements OnInit, OnDestroy {
154
192
  */
155
193
  finalizeResult(job: RosterImportJob): void;
156
194
  /**
157
- * Parses the BE `errorReport` raw JSON string into row-error view models.
195
+ * Normalizes the BE `error_report` into row-error view models.
158
196
  *
159
- * The BE stores the report as a JSONB document wrapping the per-row entries:
160
- * `{ "rows": [ { "row": 2, "field": "Email", "message": "..." } ] }`
161
- * (serialized by its `ErrorReportWrapper`) and returns it verbatim via
162
- * `@JsonRawValue`. So we read `parsed.rows`. A bare top-level array is also
163
- * accepted as a fallback in case the contract is ever flattened.
164
- * @param {(string | undefined)} errorReport - Raw JSON error report string.
197
+ * The BE wraps the per-row entries in a `{ rows: [ { row, field, message } ] }`
198
+ * document, but that value has been observed to arrive in MULTIPLE shapes:
199
+ * - a parsed object `{ rows: [...] }` (confirm response — the common case),
200
+ * - a raw JSON string of the same object (JSONB passthrough), or
201
+ * - a bare array `[ { row, field, message } ]`.
202
+ * This handles all three (and `null`) so the error log renders regardless of
203
+ * how the field is serialized.
204
+ * @param {*} errorReport - The BE error_report (object, string, array, or null).
165
205
  * @return {RosterImportRowError[]}
166
206
  * @memberof RosterImportComponent
167
207
  */
@@ -62,6 +62,19 @@ export declare class GroupsComponent implements OnInit, OnDestroy {
62
62
  apiBaseURL: string;
63
63
  userPermissions: UserPermission[];
64
64
  userInfo: LoggedInUserInfo;
65
+ private _requiredProfileFields;
66
+ /**
67
+ * Tenant-level required profile fields (e.g. ['phone','address','employer'])
68
+ * supplied by the host app from its cached tenant configuration. Passed to
69
+ * GroupsService so the roster import appends them to its required columns and
70
+ * sample file. Optional — defaults to none.
71
+ *
72
+ * Implemented as a setter so EVERY input update (including a late,
73
+ * async-resolved value that arrives after ngOnInit) is propagated to the
74
+ * singleton GroupsService — not just the initial binding.
75
+ */
76
+ set requiredProfileFields(value: string[] | null | undefined);
77
+ get requiredProfileFields(): string[];
65
78
  permissionType: typeof PermissionType;
66
79
  functionType: GroupFunctionType;
67
80
  alignmentType: typeof AlignType;
@@ -230,5 +243,5 @@ export declare class GroupsComponent implements OnInit, OnDestroy {
230
243
  */
231
244
  ngOnDestroy(): void;
232
245
  static ɵfac: i0.ɵɵFactoryDeclaration<GroupsComponent, never>;
233
- static ɵcmp: i0.ɵɵComponentDeclaration<GroupsComponent, "ieeesa-groups", never, { "groupsPageInfo": { "alias": "groupsPageInfo"; "required": false; }; "applicationId": { "alias": "applicationId"; "required": false; }; "apiBaseURL": { "alias": "apiBaseURL"; "required": false; }; "userPermissions": { "alias": "userPermissions"; "required": false; }; "userInfo": { "alias": "userInfo"; "required": false; }; }, {}, never, never, true, never>;
246
+ static ɵcmp: i0.ɵɵComponentDeclaration<GroupsComponent, "ieeesa-groups", never, { "groupsPageInfo": { "alias": "groupsPageInfo"; "required": false; }; "applicationId": { "alias": "applicationId"; "required": false; }; "apiBaseURL": { "alias": "apiBaseURL"; "required": false; }; "userPermissions": { "alias": "userPermissions"; "required": false; }; "userInfo": { "alias": "userInfo"; "required": false; }; "requiredProfileFields": { "alias": "requiredProfileFields"; "required": false; }; }, {}, never, never, true, never>;
234
247
  }
@@ -55,10 +55,13 @@ export interface RosterImportJob {
55
55
  /** Rows skipped due to validation errors. */
56
56
  failedRows?: number;
57
57
  /**
58
- * Row-level errors as a RAW JSON string (BE `error_report` JSONB passthrough).
59
- * Parse with `JSON.parse(...)` into {@link RosterImportErrorReport}[].
58
+ * Row-level errors from the BE `error_report` JSONB column. Observed to arrive
59
+ * EITHER as a parsed object `{ rows: RosterImportErrorReport[] }` OR as a raw
60
+ * JSON string of the same shape (depending on serialization). A bare array is
61
+ * also tolerated. `null` when there are no row errors. The client normalizes
62
+ * all of these — see RosterImportComponent.parseErrorReport.
60
63
  */
61
- errorReport?: string;
64
+ errorReport?: any;
62
65
  }
63
66
  /**
64
67
  * Per-row validation outcome in a validate/preview response. Mirrors the BE
@@ -77,6 +77,7 @@ export declare class GroupsService {
77
77
  "1037": string;
78
78
  "1038": string;
79
79
  "1039": string;
80
+ "1071": string;
80
81
  "1072": string;
81
82
  "1073": string;
82
83
  "1074": string;
@@ -106,6 +107,13 @@ export declare class GroupsService {
106
107
  };
107
108
  apiBaseUrl: string;
108
109
  userPermission: any;
110
+ /**
111
+ * Tenant-level required profile fields (e.g. ['phone','address','employer'])
112
+ * supplied by the host app from its cached tenant configuration. Consumed by
113
+ * the roster import to append tenant-mandated columns to the required-column
114
+ * list and the sample file. Empty when the tenant has none configured.
115
+ */
116
+ requiredProfileFields: string[];
109
117
  selectedGroupInfo: GroupInfo | undefined;
110
118
  groupFunctionType: GroupFunctionType;
111
119
  selectedGroupParentInfo: GroupInfo | undefined;
@@ -122,6 +130,18 @@ export declare class GroupsService {
122
130
  representingOrganizations: RepresentingOrganization[];
123
131
  constructor(httpService: HttpService, userPermissionsService: UserPermissionsService, groupPermissionsService: GroupPermissionsMapService, alertService: AlertsService);
124
132
  setAppConfig(apiBaseUrl: string, userPermission: any): void;
133
+ /**
134
+ * Stores the tenant-level required profile fields provided by the host app.
135
+ * @param {string[]} requiredProfileFields - Field keys (e.g. 'phone').
136
+ * @memberof GroupsService
137
+ */
138
+ setRequiredProfileFields(requiredProfileFields: string[]): void;
139
+ /**
140
+ * Returns the tenant-level required profile fields (never null).
141
+ * @return {string[]}
142
+ * @memberof GroupsService
143
+ */
144
+ getRequiredProfileFields(): string[];
125
145
  /**
126
146
  * Gets application group types from API and returns it as an observable.
127
147
  * @return {Observable<GroupTypeResponse>} -It returns group types if success else error.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ieeesa-npm/groups",
3
- "version": "0.15.10",
3
+ "version": "0.15.11",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^16.1.0",
6
6
  "@angular/core": "^16.1.0"