@ieeesa-npm/groups 0.15.9 → 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.
- package/esm2022/lib/assets/constants.json +87 -4
- package/esm2022/lib/components/interest-form/interest-form.component.mjs +104 -0
- package/esm2022/lib/components/interest-form-management/interest-form-management.component.mjs +63 -0
- package/esm2022/lib/components/interested-rosters/interested-rosters.component.mjs +28 -0
- package/esm2022/lib/components/roster-import/roster-import.component.mjs +243 -84
- package/esm2022/lib/components/roster-import-history/roster-import-history.component.mjs +232 -0
- package/esm2022/lib/components/tree-view/tree-view.component.mjs +26 -5
- package/esm2022/lib/components/view-roster/view-roster.component.mjs +10 -3
- package/esm2022/lib/groups.component.mjs +82 -6
- package/esm2022/lib/models/group-action.model.mjs +2 -1
- package/esm2022/lib/models/group-function-type.model.mjs +2 -1
- package/esm2022/lib/models/permission-type.model.mjs +2 -1
- package/esm2022/lib/models/roster-import.model.mjs +34 -17
- package/esm2022/lib/services/groups.service.mjs +24 -1
- package/esm2022/lib/services/roster-import-api.service.mjs +174 -0
- package/esm2022/public-api.mjs +6 -1
- package/fesm2022/ieeesa-npm-groups.mjs +1081 -213
- package/fesm2022/ieeesa-npm-groups.mjs.map +1 -1
- package/lib/components/interest-form/interest-form.component.d.ts +75 -0
- package/lib/components/interest-form-management/interest-form-management.component.d.ts +31 -0
- package/lib/components/interested-rosters/interested-rosters.component.d.ts +17 -0
- package/lib/components/roster-import/roster-import.component.d.ts +116 -37
- package/lib/components/roster-import-history/roster-import-history.component.d.ts +102 -0
- package/lib/components/tree-view/tree-view.component.d.ts +6 -3
- package/lib/components/view-roster/view-roster.component.d.ts +5 -0
- package/lib/groups.component.d.ts +31 -1
- package/lib/models/group-action.model.d.ts +2 -1
- package/lib/models/group-function-type.model.d.ts +2 -1
- package/lib/models/permission-type.model.d.ts +2 -1
- package/lib/models/roster-import.model.d.ts +107 -21
- package/lib/services/groups.service.d.ts +24 -0
- package/lib/services/roster-import-api.service.d.ts +108 -0
- package/package.json +1 -1
- package/public-api.d.ts +5 -0
- package/esm2022/lib/assets/roster-import-mocks.mjs +0 -98
- package/lib/assets/roster-import-mocks.d.ts +0 -27
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { OnInit } from '@angular/core';
|
|
2
|
+
import { MatDialogRef } from '@angular/material/dialog';
|
|
3
|
+
import { RadioOption, SlideToggleOption } from '@ieeesa-npm/presentation';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
/**
|
|
6
|
+
* Standard (locked) question row shown in the Interest Form tab.
|
|
7
|
+
* @export
|
|
8
|
+
* @interface StandardQuestionRow
|
|
9
|
+
*/
|
|
10
|
+
export interface StandardQuestionRow {
|
|
11
|
+
id: number;
|
|
12
|
+
label: string;
|
|
13
|
+
tag: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* "Interest Form" tab content of the Roster Interests dialog (SP3M-317). The
|
|
17
|
+
* group admin configures the interest form here: enable/disable the form, view
|
|
18
|
+
* the locked standard questions, choose the default membership level and manage
|
|
19
|
+
* custom questions. Interactive controls reuse the shared presentation
|
|
20
|
+
* components (slide toggle, radio). Persistence via a mocked service and the
|
|
21
|
+
* custom-question builder will be added in subsequent increments.
|
|
22
|
+
* @export
|
|
23
|
+
* @class InterestFormComponent
|
|
24
|
+
*/
|
|
25
|
+
export declare class InterestFormComponent implements OnInit {
|
|
26
|
+
private dialogRef;
|
|
27
|
+
constants: any;
|
|
28
|
+
interestFormTexts: any;
|
|
29
|
+
changesNotice: any;
|
|
30
|
+
sectionTitle: any;
|
|
31
|
+
sectionDescription: any;
|
|
32
|
+
standardQuestionsTitle: any;
|
|
33
|
+
standardQuestionsHint: any;
|
|
34
|
+
defaultMembershipTitle: any;
|
|
35
|
+
defaultMembershipDescription: any;
|
|
36
|
+
customQuestionsTitle: any;
|
|
37
|
+
addQuestionLabel: any;
|
|
38
|
+
standardTag: any;
|
|
39
|
+
cancelLabel: any;
|
|
40
|
+
previewLabel: any;
|
|
41
|
+
enableFormToggle: SlideToggleOption;
|
|
42
|
+
standardQuestions: StandardQuestionRow[];
|
|
43
|
+
membershipLevels: RadioOption[];
|
|
44
|
+
isFormEnabled: boolean;
|
|
45
|
+
constructor(dialogRef: MatDialogRef<unknown>);
|
|
46
|
+
/**
|
|
47
|
+
* Initializes the toggle, locked standard questions and default membership
|
|
48
|
+
* level options from constants.
|
|
49
|
+
* @memberof InterestFormComponent
|
|
50
|
+
*/
|
|
51
|
+
ngOnInit(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Updates the form-enabled state when the toggle changes so the dependent
|
|
54
|
+
* sections show or hide accordingly.
|
|
55
|
+
* @param {SlideToggleOption} toggle
|
|
56
|
+
* @memberof InterestFormComponent
|
|
57
|
+
*/
|
|
58
|
+
onEnableFormToggle(toggle: SlideToggleOption): void;
|
|
59
|
+
/**
|
|
60
|
+
* Closes the Roster Interests dialog (Cancel action).
|
|
61
|
+
* @memberof InterestFormComponent
|
|
62
|
+
*/
|
|
63
|
+
onCancel(): void;
|
|
64
|
+
/**
|
|
65
|
+
* Returns the unique identifier for a standard question row for ngFor
|
|
66
|
+
* tracking.
|
|
67
|
+
* @param {number} index
|
|
68
|
+
* @param {StandardQuestionRow} question
|
|
69
|
+
* @return {number}
|
|
70
|
+
* @memberof InterestFormComponent
|
|
71
|
+
*/
|
|
72
|
+
trackByFn(index: number, question: StandardQuestionRow): number;
|
|
73
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<InterestFormComponent, [{ optional: true; }]>;
|
|
74
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<InterestFormComponent, "ieeesa-interest-form", never, {}, {}, never, never, true, never>;
|
|
75
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { MatDialogRef } from '@angular/material/dialog';
|
|
2
|
+
import { Tab } from '@ieeesa-npm/presentation';
|
|
3
|
+
import { GroupInfo } from '../../models/group-info.model';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
/**
|
|
6
|
+
* Roster Interests dialog host (SP3M-317). Opened from the "Manage Interest
|
|
7
|
+
* Form" action on a group row. Renders a two-tab layout using the shared
|
|
8
|
+
* TabsComponent: "Interested Rosters" (submissions list) and "Interest Form"
|
|
9
|
+
* (admin configuration). The group being managed is provided via the dialog
|
|
10
|
+
* data. The tab content components are rendered dynamically by TabsComponent
|
|
11
|
+
* through each tab's componentRef.
|
|
12
|
+
* @export
|
|
13
|
+
* @class InterestFormManagementComponent
|
|
14
|
+
*/
|
|
15
|
+
export declare class InterestFormManagementComponent {
|
|
16
|
+
dialogRef: MatDialogRef<InterestFormManagementComponent>;
|
|
17
|
+
group: GroupInfo;
|
|
18
|
+
constants: any;
|
|
19
|
+
rosterInterestsTexts: any;
|
|
20
|
+
heading: any;
|
|
21
|
+
closeAriaLabel: any;
|
|
22
|
+
tabs: Tab[];
|
|
23
|
+
constructor(dialogRef: MatDialogRef<InterestFormManagementComponent>, group: GroupInfo);
|
|
24
|
+
/**
|
|
25
|
+
* Closes the Roster Interests dialog.
|
|
26
|
+
* @memberof InterestFormManagementComponent
|
|
27
|
+
*/
|
|
28
|
+
onClose(): void;
|
|
29
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<InterestFormManagementComponent, never>;
|
|
30
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<InterestFormManagementComponent, "ieeesa-interest-form-management", never, {}, {}, never, never, true, never>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
/**
|
|
3
|
+
* "Interested Rosters" tab content of the Roster Interests dialog (SP3M-317).
|
|
4
|
+
* Displays the list of users who expressed interest in the group. This is a
|
|
5
|
+
* placeholder shell for now; the submissions table will be implemented in a
|
|
6
|
+
* later increment once the backend is available (data will be mocked in the
|
|
7
|
+
* service layer meanwhile).
|
|
8
|
+
* @export
|
|
9
|
+
* @class InterestedRostersComponent
|
|
10
|
+
*/
|
|
11
|
+
export declare class InterestedRostersComponent {
|
|
12
|
+
constants: any;
|
|
13
|
+
interestedRostersTexts: any;
|
|
14
|
+
placeholderMessage: any;
|
|
15
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<InterestedRostersComponent, never>;
|
|
16
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<InterestedRostersComponent, "ieeesa-interested-rosters", never, {}, {}, never, never, true, never>;
|
|
17
|
+
}
|
|
@@ -1,22 +1,46 @@
|
|
|
1
|
-
import { EventEmitter, OnDestroy } from '@angular/core';
|
|
1
|
+
import { EventEmitter, OnDestroy, OnInit } from '@angular/core';
|
|
2
2
|
import { Subject } from 'rxjs';
|
|
3
|
-
import {
|
|
3
|
+
import { RosterImportJob } from '../../models/roster-import.model';
|
|
4
|
+
import { RosterImportApiService } from '../../services/roster-import-api.service';
|
|
5
|
+
import { GroupsService } from '../../services/groups.service';
|
|
4
6
|
import * as i0 from "@angular/core";
|
|
5
7
|
/** States of the roster import flow. */
|
|
6
8
|
type RosterImportState = 'upload' | 'processing' | 'result';
|
|
7
9
|
/**
|
|
8
|
-
*
|
|
10
|
+
* View-model for the result screen. Populated from the confirmed
|
|
11
|
+
* {@link RosterImportJob} returned by the backend.
|
|
12
|
+
*/
|
|
13
|
+
interface RosterImportResult {
|
|
14
|
+
totalRecords: number;
|
|
15
|
+
successCount: number;
|
|
16
|
+
failureCount: number;
|
|
17
|
+
}
|
|
18
|
+
/** Row error shown on the result screen (mapped from the BE error report). */
|
|
19
|
+
interface RosterImportRowError {
|
|
20
|
+
rowNumber: number;
|
|
21
|
+
field?: string;
|
|
22
|
+
errorMessage: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Roster Import dialog.
|
|
9
26
|
*
|
|
10
|
-
* Lets an admin upload a CSV/
|
|
27
|
+
* Lets an admin upload a CSV/XLSX roster file, shows a processing progress
|
|
11
28
|
* bar, then a result summary (added / skipped) with per-row errors and an
|
|
12
|
-
* error-log download.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
29
|
+
* error-log download.
|
|
30
|
+
*
|
|
31
|
+
* Wired to the real backend roster-import state machine
|
|
32
|
+
* (sa-saapps-groups-api `RosterImportController`) via
|
|
33
|
+
* {@link RosterImportApiService}: on Import it runs
|
|
34
|
+
* upload → validate → confirm and renders the confirmed job's terminal counts
|
|
35
|
+
* and per-row errors. Server-side validation errors (1072 unsupported format,
|
|
36
|
+
* 1073 too large, 1074 row limit, 1075 invalid status) are surfaced inline.
|
|
15
37
|
*
|
|
16
38
|
* @export
|
|
17
39
|
* @class RosterImportComponent
|
|
18
40
|
*/
|
|
19
|
-
export declare class RosterImportComponent implements OnDestroy {
|
|
41
|
+
export declare class RosterImportComponent implements OnInit, OnDestroy {
|
|
42
|
+
private rosterImportApiService;
|
|
43
|
+
private groupService;
|
|
20
44
|
/** Carries the { groupId, groupName } payload from the opening dialog. */
|
|
21
45
|
componentData: any;
|
|
22
46
|
/** Emitted after an import that added at least one row (parent refreshes). */
|
|
@@ -32,12 +56,10 @@ export declare class RosterImportComponent implements OnDestroy {
|
|
|
32
56
|
selectedFile: File | null;
|
|
33
57
|
/** File drag-over state. */
|
|
34
58
|
isDragOver: boolean;
|
|
35
|
-
/**
|
|
36
|
-
|
|
37
|
-
/** Terminal upload result (mock). */
|
|
38
|
-
uploadResult: RosterUploadResponse | null;
|
|
59
|
+
/** Terminal upload result. */
|
|
60
|
+
uploadResult: RosterImportResult | null;
|
|
39
61
|
/** Row-level errors for the completed job. */
|
|
40
|
-
jobErrors:
|
|
62
|
+
jobErrors: RosterImportRowError[];
|
|
41
63
|
/** Inline validation / API error message. */
|
|
42
64
|
errorMessage: string | null;
|
|
43
65
|
/**
|
|
@@ -45,21 +67,62 @@ export declare class RosterImportComponent implements OnDestroy {
|
|
|
45
67
|
* (Figma: "No roster data found...").
|
|
46
68
|
*/
|
|
47
69
|
noDataMessage: string | null;
|
|
48
|
-
/**
|
|
49
|
-
|
|
50
|
-
/**
|
|
70
|
+
/** The import job id returned by upload (kept so cancel can clean it up). */
|
|
71
|
+
private importId;
|
|
72
|
+
/** Maximum file size in bytes (10 MB) — matches the BE 10MB limit. */
|
|
73
|
+
readonly MAX_FILE_SIZE = 10485760;
|
|
74
|
+
/** Accepted file extensions (must match the BE contract: only .csv / .xlsx). */
|
|
51
75
|
readonly ACCEPTED_EXTENSIONS: string[];
|
|
76
|
+
constructor(rosterImportApiService: RosterImportApiService, groupService: GroupsService);
|
|
52
77
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
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[]}
|
|
56
83
|
*/
|
|
57
|
-
private mockScenarios;
|
|
58
|
-
private mockScenarioIndex;
|
|
59
|
-
/** Required column headers for display. */
|
|
60
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;
|
|
61
117
|
/** Comma-separated accepted file types for the input element. */
|
|
62
118
|
get acceptedFileTypes(): string;
|
|
119
|
+
/** The target group id from the dialog payload (falls back to selection). */
|
|
120
|
+
private get groupId();
|
|
121
|
+
/**
|
|
122
|
+
* Sets the API base URL on the import service.
|
|
123
|
+
* @memberof RosterImportComponent
|
|
124
|
+
*/
|
|
125
|
+
ngOnInit(): void;
|
|
63
126
|
/**
|
|
64
127
|
* Cleans up subscriptions when the component is destroyed.
|
|
65
128
|
* @memberof RosterImportComponent
|
|
@@ -106,20 +169,43 @@ export declare class RosterImportComponent implements OnDestroy {
|
|
|
106
169
|
*/
|
|
107
170
|
onRemoveFile(): void;
|
|
108
171
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
172
|
+
* Runs the real import: upload → validate → confirm. The progress bar is
|
|
173
|
+
* shown in indeterminate mode while the chain is in flight, then the
|
|
174
|
+
* confirmed job's terminal counts + per-row errors drive the result screen.
|
|
112
175
|
* @memberof RosterImportComponent
|
|
113
176
|
*/
|
|
114
177
|
onImport(): void;
|
|
115
178
|
/**
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
* @param {
|
|
179
|
+
* Maps a failed import call to an inline error message and returns the UI to
|
|
180
|
+
* the upload state so the user can retry. Known BE error codes (1072–1075)
|
|
181
|
+
* are mapped via constants; anything else uses the generic message.
|
|
182
|
+
* @param {*} error - The HttpErrorResponse.
|
|
183
|
+
* @memberof RosterImportComponent
|
|
184
|
+
*/
|
|
185
|
+
private handleImportError;
|
|
186
|
+
/**
|
|
187
|
+
* Stores the terminal result and moves to the result state. When the job had
|
|
188
|
+
* no data rows, shows the "no roster data" info banner instead of the summary
|
|
189
|
+
* cards.
|
|
190
|
+
* @param {RosterImportJob} job - The confirmed import job.
|
|
120
191
|
* @memberof RosterImportComponent
|
|
121
192
|
*/
|
|
122
|
-
finalizeResult(
|
|
193
|
+
finalizeResult(job: RosterImportJob): void;
|
|
194
|
+
/**
|
|
195
|
+
* Normalizes the BE `error_report` into row-error view models.
|
|
196
|
+
*
|
|
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).
|
|
205
|
+
* @return {RosterImportRowError[]}
|
|
206
|
+
* @memberof RosterImportComponent
|
|
207
|
+
*/
|
|
208
|
+
private parseErrorReport;
|
|
123
209
|
/**
|
|
124
210
|
* Whether the result state should show the summary cards (added / skipped).
|
|
125
211
|
* Hidden for the "no data records" case.
|
|
@@ -166,13 +252,6 @@ export declare class RosterImportComponent implements OnDestroy {
|
|
|
166
252
|
* @memberof RosterImportComponent
|
|
167
253
|
*/
|
|
168
254
|
private triggerDownload;
|
|
169
|
-
/**
|
|
170
|
-
* MOCK ONLY: returns the next scenario in the cycle so repeated imports show
|
|
171
|
-
* every result state.
|
|
172
|
-
* @return {RosterImportMockScenario}
|
|
173
|
-
* @memberof RosterImportComponent
|
|
174
|
-
*/
|
|
175
|
-
private nextMockScenario;
|
|
176
255
|
static ɵfac: i0.ɵɵFactoryDeclaration<RosterImportComponent, never>;
|
|
177
256
|
static ɵcmp: i0.ɵɵComponentDeclaration<RosterImportComponent, "ieeesa-roster-import", never, { "componentData": { "alias": "componentData"; "required": false; }; }, { "submitFormResponse": "submitFormResponse"; "formCancel": "formCancel"; }, never, never, true, never>;
|
|
178
257
|
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { ChangeDetectorRef, OnDestroy, OnInit } from '@angular/core';
|
|
2
|
+
import { TableActions, TableColumnSchema } from '@ieeesa-npm/presentation';
|
|
3
|
+
import { GlobalErrorHandlerService } from '@ieeesa-npm/utility';
|
|
4
|
+
import { RosterImportApiService } from '../../services/roster-import-api.service';
|
|
5
|
+
import { GroupsService } from '../../services/groups.service';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
/** A single row shown in the "Imported Files" table. */
|
|
8
|
+
interface RosterImportHistoryRow {
|
|
9
|
+
timestamp: string;
|
|
10
|
+
personImported: string;
|
|
11
|
+
fileName: string;
|
|
12
|
+
addedRows: number | string;
|
|
13
|
+
errors: number | string;
|
|
14
|
+
targetGroup: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Roster import-history ("View History") dialog body.
|
|
18
|
+
*
|
|
19
|
+
* Rendered inside the shared ModalComponent (which supplies the
|
|
20
|
+
* "← Back to Rosters / View History" breadcrumb title row + X close). Shows the
|
|
21
|
+
* selected group's name and an "Imported Files" table listing prior roster
|
|
22
|
+
* imports.
|
|
23
|
+
*
|
|
24
|
+
* Data comes from the real BE endpoint via {@link RosterImportApiService}:
|
|
25
|
+
* `GET /v1/groups/roster/import/history/{groupId}`. The response is a list of
|
|
26
|
+
* `RosterImportJob` whose JSON view exposes `fileName`, `successRows`,
|
|
27
|
+
* `failedRows`, `status` and ids — but NOT `createdOn` / `createdBy` (both are
|
|
28
|
+
* `@JsonIgnore` on the BE entity). So the "Timestamp" and "Person Imported"
|
|
29
|
+
* columns render a placeholder until the BE exposes those fields. "Target
|
|
30
|
+
* Group" uses the current group's name (history is scoped to one group).
|
|
31
|
+
*
|
|
32
|
+
* @export
|
|
33
|
+
* @class RosterImportHistoryComponent
|
|
34
|
+
*/
|
|
35
|
+
export declare class RosterImportHistoryComponent implements OnInit, OnDestroy {
|
|
36
|
+
private rosterImportApiService;
|
|
37
|
+
private groupService;
|
|
38
|
+
private cdr;
|
|
39
|
+
private globalErrorHandlerService;
|
|
40
|
+
/** Carries the { groupId, groupName } payload from the opening dialog. */
|
|
41
|
+
componentData: any;
|
|
42
|
+
constants: any;
|
|
43
|
+
screenTexts: any;
|
|
44
|
+
private destroy$;
|
|
45
|
+
/** Table column definitions for the "Imported Files" table. */
|
|
46
|
+
columnSchema: TableColumnSchema[];
|
|
47
|
+
/** Import-history rows mapped for the table. */
|
|
48
|
+
tableData: RosterImportHistoryRow[];
|
|
49
|
+
/** True while the history request is in flight. */
|
|
50
|
+
isLoading: boolean;
|
|
51
|
+
/** Inline error message when the history request fails. */
|
|
52
|
+
errorMessage: string | null;
|
|
53
|
+
/** Read-only table — no search / filter / add / edit / delete actions. */
|
|
54
|
+
tableActions: TableActions;
|
|
55
|
+
/** Placeholder shown for fields the BE does not return (timestamp / person). */
|
|
56
|
+
private readonly placeholder;
|
|
57
|
+
constructor(rosterImportApiService: RosterImportApiService, groupService: GroupsService, cdr: ChangeDetectorRef, globalErrorHandlerService: GlobalErrorHandlerService);
|
|
58
|
+
/** The group name shown as the heading above the Imported Files table. */
|
|
59
|
+
get groupName(): string;
|
|
60
|
+
/** The group id whose history is fetched. */
|
|
61
|
+
private get groupId();
|
|
62
|
+
/**
|
|
63
|
+
* Builds the table schema and loads the import history from the BE.
|
|
64
|
+
* @memberof RosterImportHistoryComponent
|
|
65
|
+
*/
|
|
66
|
+
ngOnInit(): void;
|
|
67
|
+
/**
|
|
68
|
+
* Cleans up subscriptions when the component is destroyed.
|
|
69
|
+
* @memberof RosterImportHistoryComponent
|
|
70
|
+
*/
|
|
71
|
+
ngOnDestroy(): void;
|
|
72
|
+
/**
|
|
73
|
+
* Fetches the import history for the current group and maps it to table rows.
|
|
74
|
+
* @memberof RosterImportHistoryComponent
|
|
75
|
+
*/
|
|
76
|
+
loadImportHistory(): void;
|
|
77
|
+
/**
|
|
78
|
+
* Maps a BE import job to a table row. Timestamp and Person Imported are not
|
|
79
|
+
* present in the response (BE `@JsonIgnore`), so they render a placeholder.
|
|
80
|
+
* Target Group uses the current group's name (history is per-group).
|
|
81
|
+
* @param {RosterImportJob} job - The BE import job.
|
|
82
|
+
* @return {RosterImportHistoryRow}
|
|
83
|
+
* @memberof RosterImportHistoryComponent
|
|
84
|
+
*/
|
|
85
|
+
private mapJobToRow;
|
|
86
|
+
/**
|
|
87
|
+
* Maps a failed history request to a user-facing inline error message.
|
|
88
|
+
* A 403 gets the permission-specific message; other errors get the generic
|
|
89
|
+
* one and are forwarded to the global handler for logging/interceptors.
|
|
90
|
+
* @param {*} error - The HttpErrorResponse.
|
|
91
|
+
* @memberof RosterImportHistoryComponent
|
|
92
|
+
*/
|
|
93
|
+
private handleError;
|
|
94
|
+
/**
|
|
95
|
+
* Defines the "Imported Files" table columns.
|
|
96
|
+
* @memberof RosterImportHistoryComponent
|
|
97
|
+
*/
|
|
98
|
+
private buildColumnSchema;
|
|
99
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<RosterImportHistoryComponent, never>;
|
|
100
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<RosterImportHistoryComponent, "ieeesa-roster-import-history", never, { "componentData": { "alias": "componentData"; "required": false; }; }, {}, never, never, true, never>;
|
|
101
|
+
}
|
|
102
|
+
export {};
|
|
@@ -155,6 +155,7 @@ export declare class TreeViewComponent implements OnInit, AfterViewInit, OnDestr
|
|
|
155
155
|
editGroupClick: EventEmitter<EditGroupAndParentInfo>;
|
|
156
156
|
deleteGroupClick: EventEmitter<GroupInfo>;
|
|
157
157
|
viewRosterClick: EventEmitter<GroupInfo>;
|
|
158
|
+
manageInterestFormClick: EventEmitter<GroupInfo>;
|
|
158
159
|
isMobileView: boolean;
|
|
159
160
|
groupFunctionType: typeof GroupFunctionType;
|
|
160
161
|
constructor(database: Groups, elementRef: ElementRef, groupsService: GroupsService, breakpointObserverService: BreakpointObserverService);
|
|
@@ -263,8 +264,10 @@ export declare class TreeViewComponent implements OnInit, AfterViewInit, OnDestr
|
|
|
263
264
|
*/
|
|
264
265
|
getToggleButtonInfo(group: GroupNode): IconButton;
|
|
265
266
|
/**
|
|
266
|
-
* Handles the emitted group actions event
|
|
267
|
-
*
|
|
267
|
+
* Handles the emitted group actions event. Emits the corresponding output
|
|
268
|
+
* for the selected action: view roster, create sub group, edit group,
|
|
269
|
+
* delete group, or manage interest form.
|
|
270
|
+
* @param {GroupNode} group
|
|
268
271
|
* @memberof TreeViewComponent
|
|
269
272
|
*/
|
|
270
273
|
handleGroupActions(group: GroupNode): void;
|
|
@@ -289,5 +292,5 @@ export declare class TreeViewComponent implements OnInit, AfterViewInit, OnDestr
|
|
|
289
292
|
*/
|
|
290
293
|
ngOnDestroy(): void;
|
|
291
294
|
static ɵfac: i0.ɵɵFactoryDeclaration<TreeViewComponent, never>;
|
|
292
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<TreeViewComponent, "ieeesa-tree", never, { "parentGroupsInfo": { "alias": "parentGroupsInfo"; "required": false; }; "childGroupsInfo": { "alias": "childGroupsInfo"; "required": false; }; "isGroupSearchOrFilterActive": { "alias": "isGroupSearchOrFilterActive"; "required": false; }; "deletedGroupIdInfo": { "alias": "deletedGroupIdInfo"; "required": false; }; "userGroupPermissions": { "alias": "userGroupPermissions"; "required": false; }; }, { "toggleGroupClick": "toggleGroupClick"; "createGroupClick": "createGroupClick"; "editGroupClick": "editGroupClick"; "deleteGroupClick": "deleteGroupClick"; "viewRosterClick": "viewRosterClick"; }, never, never, true, never>;
|
|
295
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<TreeViewComponent, "ieeesa-tree", never, { "parentGroupsInfo": { "alias": "parentGroupsInfo"; "required": false; }; "childGroupsInfo": { "alias": "childGroupsInfo"; "required": false; }; "isGroupSearchOrFilterActive": { "alias": "isGroupSearchOrFilterActive"; "required": false; }; "deletedGroupIdInfo": { "alias": "deletedGroupIdInfo"; "required": false; }; "userGroupPermissions": { "alias": "userGroupPermissions"; "required": false; }; }, { "toggleGroupClick": "toggleGroupClick"; "createGroupClick": "createGroupClick"; "editGroupClick": "editGroupClick"; "deleteGroupClick": "deleteGroupClick"; "viewRosterClick": "viewRosterClick"; "manageInterestFormClick": "manageInterestFormClick"; }, never, never, true, never>;
|
|
293
296
|
}
|
|
@@ -188,6 +188,11 @@ export declare class ViewRosterComponent implements AfterViewInit, OnDestroy, On
|
|
|
188
188
|
* @memberof ViewRosterComponent
|
|
189
189
|
*/
|
|
190
190
|
onImportRoster(): void;
|
|
191
|
+
/**
|
|
192
|
+
* "View History" action — opens the roster import-history popup.
|
|
193
|
+
* @memberof ViewRosterComponent
|
|
194
|
+
*/
|
|
195
|
+
onViewHistory(): void;
|
|
191
196
|
/**
|
|
192
197
|
* Handles alerts for success, error, warning.
|
|
193
198
|
* @param {(string | string[])} message -error or warning message
|
|
@@ -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;
|
|
@@ -117,12 +130,29 @@ export declare class GroupsComponent implements OnInit, OnDestroy {
|
|
|
117
130
|
* @memberof GroupsComponent
|
|
118
131
|
*/
|
|
119
132
|
openRosterImportModal(selectedGroupInfo: GroupInfo): void;
|
|
133
|
+
/**
|
|
134
|
+
* Sets the dialog options for the roster import-history ("View History")
|
|
135
|
+
* modal and opens it. Passes the selected group's id/name to the
|
|
136
|
+
* dynamically-instantiated RosterImportHistoryComponent via the
|
|
137
|
+
* ModalComponent dynamic-input pattern.
|
|
138
|
+
* @param {GroupInfo} selectedGroupInfo
|
|
139
|
+
* @memberof GroupsComponent
|
|
140
|
+
*/
|
|
141
|
+
openRosterImportHistoryModal(selectedGroupInfo: GroupInfo): void;
|
|
120
142
|
/**
|
|
121
143
|
* Sets the dialog options for users modal and calls openModal method.
|
|
122
144
|
* @param {GroupInfo} group
|
|
123
145
|
* @memberof GroupsComponent
|
|
124
146
|
*/
|
|
125
147
|
viewRoster(group: GroupInfo): void;
|
|
148
|
+
/**
|
|
149
|
+
* Opens the Roster Interests dialog for the selected group (SP3M-317). The
|
|
150
|
+
* dialog hosts the "Interested Rosters" and "Interest Form" tabs and receives
|
|
151
|
+
* the group via the dialog data.
|
|
152
|
+
* @param {GroupInfo} group
|
|
153
|
+
* @memberof GroupsComponent
|
|
154
|
+
*/
|
|
155
|
+
openRosterInterests(group: GroupInfo): void;
|
|
126
156
|
/**
|
|
127
157
|
* Opens modal component with for received params and handles form submission success and errors.
|
|
128
158
|
* @param {*} dialogOptions
|
|
@@ -213,5 +243,5 @@ export declare class GroupsComponent implements OnInit, OnDestroy {
|
|
|
213
243
|
*/
|
|
214
244
|
ngOnDestroy(): void;
|
|
215
245
|
static ɵfac: i0.ɵɵFactoryDeclaration<GroupsComponent, never>;
|
|
216
|
-
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>;
|
|
217
247
|
}
|
|
@@ -8,5 +8,6 @@ export declare enum GroupFunctionType {
|
|
|
8
8
|
REASSIGN_PARENT_GROUP = "REASSIGN_PARENT_GROUP",
|
|
9
9
|
EDIT_ROSTER_USER_ROLE = "EDIT_ROSTER_USER_ROLE",
|
|
10
10
|
ADD_USER_TO_ROSTER = "ADD_USER_TO_ROSTER",
|
|
11
|
-
IMPORT_ROSTER = "IMPORT_ROSTER"
|
|
11
|
+
IMPORT_ROSTER = "IMPORT_ROSTER",
|
|
12
|
+
VIEW_IMPORT_HISTORY = "VIEW_IMPORT_HISTORY"
|
|
12
13
|
}
|
|
@@ -12,5 +12,6 @@ export declare enum PermissionType {
|
|
|
12
12
|
VIEW_ALL_GROUPS = "VIEW_ALL_GROUPS",
|
|
13
13
|
MANAGE_ALL_GROUPS = "MANAGE_ALL_GROUPS",
|
|
14
14
|
VIEW_ALL_ROSTERS = "VIEW_ALL_ROSTERS",
|
|
15
|
-
MANAGE_ALL_ROSTERS = "MANAGE_ALL_ROSTERS"
|
|
15
|
+
MANAGE_ALL_ROSTERS = "MANAGE_ALL_ROSTERS",
|
|
16
|
+
MANAGE_CUSTOM_INTEREST_QUESTIONS = "MANAGE_CUSTOM_INTEREST_QUESTIONS"
|
|
16
17
|
}
|