@ieeesa-npm/dashboard 0.0.2 → 0.0.4

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 (33) hide show
  1. package/esm2022/lib/assets/constants.json +7 -3
  2. package/esm2022/lib/components/event-group-card/event-group-card.component.mjs +103 -13
  3. package/esm2022/lib/components/meeting-attendance-row/meeting-attendance-row.component.mjs +101 -23
  4. package/esm2022/lib/components/upcoming-meetings-events/upcoming-meetings-events.component.mjs +70 -6
  5. package/esm2022/lib/components/your-groups/your-groups.component.mjs +132 -23
  6. package/esm2022/lib/dashboard.component.mjs +93 -9
  7. package/esm2022/lib/models/attendance-state.model.mjs +8 -1
  8. package/esm2022/lib/models/dashboard-route-config.model.mjs +1 -1
  9. package/esm2022/lib/models/event-meeting-list-item.model.mjs +1 -1
  10. package/esm2022/lib/models/event-meeting-list-payload.model.mjs +7 -5
  11. package/esm2022/lib/models/meeting-row.model.mjs +1 -1
  12. package/esm2022/lib/models/upcoming-event.model.mjs +1 -1
  13. package/esm2022/lib/services/dashboard.service.mjs +71 -126
  14. package/esm2022/lib/services/user-permissions.service.mjs +23 -9
  15. package/esm2022/lib/utils/event-meeting-mapper.util.mjs +47 -41
  16. package/fesm2022/ieeesa-npm-dashboard.mjs +657 -306
  17. package/fesm2022/ieeesa-npm-dashboard.mjs.map +1 -1
  18. package/lib/components/event-group-card/event-group-card.component.d.ts +75 -6
  19. package/lib/components/meeting-attendance-row/meeting-attendance-row.component.d.ts +61 -7
  20. package/lib/components/member-level-badge/member-level-badge.component.d.ts +12 -1
  21. package/lib/components/upcoming-meetings-events/upcoming-meetings-events.component.d.ts +51 -3
  22. package/lib/components/your-groups/your-groups.component.d.ts +72 -14
  23. package/lib/dashboard.component.d.ts +53 -3
  24. package/lib/models/attendance-state.model.d.ts +8 -1
  25. package/lib/models/dashboard-route-config.model.d.ts +14 -0
  26. package/lib/models/event-meeting-list-item.model.d.ts +68 -68
  27. package/lib/models/event-meeting-list-payload.model.d.ts +14 -25
  28. package/lib/models/meeting-row.model.d.ts +2 -0
  29. package/lib/models/upcoming-event.model.d.ts +9 -0
  30. package/lib/services/dashboard.service.d.ts +25 -53
  31. package/lib/services/user-permissions.service.d.ts +8 -4
  32. package/lib/utils/event-meeting-mapper.util.d.ts +15 -21
  33. package/package.json +1 -1
@@ -44,6 +44,8 @@ export declare class EventGroupCardComponent {
44
44
  inFlightMeetingIds: ReadonlySet<string>;
45
45
  /** Whether the host has determined the viewport is at/below the mobile breakpoint. */
46
46
  isMobileView: boolean;
47
+ /** Whether this event's child meetings are currently loading (drill-down API). */
48
+ meetingsLoading: boolean;
47
49
  /** Emits the event id when the "View Event" button is activated (Req 6.4). */
48
50
  viewEvent: EventEmitter<string>;
49
51
  /** Bubbles the meeting id when a row's meeting-name link is activated (Req 6.7, 7.4). */
@@ -59,9 +61,25 @@ export declare class EventGroupCardComponent {
59
61
  * so the container can lazily fetch the event's child meetings from the
60
62
  * backend. Standalone-meeting cards never emit this.
61
63
  */
62
- loadMeetings: EventEmitter<number>;
64
+ loadMeetings: EventEmitter<{
65
+ page: number;
66
+ size: number;
67
+ }>;
68
+ /**
69
+ * Bubbles the owning event id + meeting id when an attendance button is
70
+ * activated for an In-Progress meeting, so the host can navigate to the
71
+ * view-meeting screen (where the real Log Attendance popup opens).
72
+ */
73
+ navigateToMeeting: EventEmitter<{
74
+ eventId: string;
75
+ meetingId: string;
76
+ logAttendance?: boolean | undefined;
77
+ leaveMeeting?: boolean | undefined;
78
+ }>;
63
79
  /** The default page size for the per-card meeting paginator. */
64
80
  readonly defaultPageSize = 5;
81
+ /** Page-size options shown in the paginator dropdown (matches the app-wide paginator). */
82
+ readonly pageSizeOptions: number[];
65
83
  /** The current zero-based page index of the meeting list. */
66
84
  pageIndex: number;
67
85
  /** The current page size of the meeting list. */
@@ -175,19 +193,70 @@ export declare class EventGroupCardComponent {
175
193
  */
176
194
  get isStandaloneAttending(): boolean;
177
195
  /**
178
- * Whether the STANDALONE meeting's Log Attendance button is shown (not
179
- * attending and the host grants the permission).
196
+ * Whether the STANDALONE meeting's Log Attendance button is shown (whenever
197
+ * not currently attending). No permission gating — mirrors the attendance
198
+ * library.
180
199
  * @return {boolean} True when the log-attendance button is visible.
181
200
  * @memberof EventGroupCardComponent
182
201
  */
183
202
  get showStandaloneLog(): boolean;
184
203
  /**
185
- * Whether the STANDALONE meeting's Leave Meeting button is shown (attending
186
- * and the host grants the permission).
204
+ * Whether the STANDALONE meeting's Leave Meeting button is shown — only while
205
+ * the meeting is currently attending AND active.
187
206
  * @return {boolean} True when the leave-meeting button is visible.
188
207
  * @memberof EventGroupCardComponent
189
208
  */
190
209
  get showStandaloneLeave(): boolean;
210
+ /**
211
+ * Whether the STANDALONE meeting is eligible for an attendance action. The
212
+ * backend supplies an `attendanceState` only for attendance-eligible meetings
213
+ * (open for attendance), so its presence is the eligibility signal.
214
+ * @return {boolean} True when the standalone meeting is attendance-eligible.
215
+ * @memberof EventGroupCardComponent
216
+ */
217
+ get isStandaloneEligible(): boolean;
218
+ /**
219
+ * Whether the STANDALONE meeting is currently In Progress — the attendance
220
+ * button is only ENABLED during the meeting (disabled otherwise, mirroring the
221
+ * view-meeting page).
222
+ * @return {boolean} True when the standalone meeting status is 'In Progress'.
223
+ * @memberof EventGroupCardComponent
224
+ */
225
+ get isStandaloneActive(): boolean;
226
+ /**
227
+ * Whether the STANDALONE Log Attendance button is disabled (outside meeting
228
+ * time), matching the view-meeting page's inactive state.
229
+ * @return {boolean} True when the standalone log button should be disabled.
230
+ * @memberof EventGroupCardComponent
231
+ */
232
+ get isStandaloneLogDisabled(): boolean;
233
+ /** The inactive-button message shown when the standalone meeting is not active. */
234
+ get inactiveMessage(): string;
235
+ /**
236
+ * Bubbles a row's navigate-to-meeting request upward unchanged so the host can
237
+ * route to the view-meeting screen.
238
+ * @param {{ eventId: string; meetingId: string }} request - The meeting identity.
239
+ * @memberof EventGroupCardComponent
240
+ */
241
+ onNavigateToMeeting(request: {
242
+ eventId: string;
243
+ meetingId: string;
244
+ logAttendance?: boolean;
245
+ leaveMeeting?: boolean;
246
+ }): void;
247
+ /**
248
+ * Emits the navigate-to-meeting intent for a STANDALONE meeting's attendance
249
+ * action (Log Attendance or Leave Meeting, requesting the matching popup
250
+ * auto-open). Its own id is the meeting id; it has no parent event.
251
+ * @memberof EventGroupCardComponent
252
+ */
253
+ onNavigateToStandalone(): void;
254
+ /**
255
+ * Emits the navigate-to-meeting intent for a STANDALONE meeting's name link
256
+ * (view only — no popup auto-open).
257
+ * @memberof EventGroupCardComponent
258
+ */
259
+ onOpenStandalone(): void;
191
260
  /** The luxon-formatted start date of the event (ISO or epoch ms) (Req 6.2). */
192
261
  get formattedStartDate(): string;
193
262
  /** The luxon-formatted end date of the event (ISO or epoch ms) (Req 6.2). */
@@ -264,5 +333,5 @@ export declare class EventGroupCardComponent {
264
333
  */
265
334
  private formatDate;
266
335
  static ɵfac: i0.ɵɵFactoryDeclaration<EventGroupCardComponent, never>;
267
- static ɵcmp: i0.ɵɵComponentDeclaration<EventGroupCardComponent, "ieeesa-event-group-card", never, { "event": { "alias": "event"; "required": false; }; "permissions": { "alias": "permissions"; "required": false; }; "attendanceStates": { "alias": "attendanceStates"; "required": false; }; "inFlightMeetingIds": { "alias": "inFlightMeetingIds"; "required": false; }; "isMobileView": { "alias": "isMobileView"; "required": false; }; }, { "viewEvent": "viewEvent"; "openMeeting": "openMeeting"; "logAttendance": "logAttendance"; "leaveMeeting": "leaveMeeting"; "pageChange": "pageChange"; "loadMeetings": "loadMeetings"; }, never, never, true, never>;
336
+ static ɵcmp: i0.ɵɵComponentDeclaration<EventGroupCardComponent, "ieeesa-event-group-card", never, { "event": { "alias": "event"; "required": false; }; "permissions": { "alias": "permissions"; "required": false; }; "attendanceStates": { "alias": "attendanceStates"; "required": false; }; "inFlightMeetingIds": { "alias": "inFlightMeetingIds"; "required": false; }; "isMobileView": { "alias": "isMobileView"; "required": false; }; "meetingsLoading": { "alias": "meetingsLoading"; "required": false; }; }, { "viewEvent": "viewEvent"; "openMeeting": "openMeeting"; "logAttendance": "logAttendance"; "leaveMeeting": "leaveMeeting"; "pageChange": "pageChange"; "loadMeetings": "loadMeetings"; "navigateToMeeting": "navigateToMeeting"; }, never, never, true, never>;
268
337
  }
@@ -39,8 +39,39 @@ export declare class MeetingAttendanceRowComponent {
39
39
  logAttendance: EventEmitter<string>;
40
40
  /** Emits the meeting id to request leaving the meeting (Req 7.8). */
41
41
  leaveMeeting: EventEmitter<string>;
42
+ /**
43
+ * Emits the owning event id + meeting id when the attendance button is
44
+ * activated for an In-Progress meeting, so the host can navigate to the
45
+ * view-meeting screen (where the real Log Attendance popup opens).
46
+ */
47
+ navigateToMeeting: EventEmitter<{
48
+ eventId: string;
49
+ meetingId: string;
50
+ logAttendance?: boolean | undefined;
51
+ leaveMeeting?: boolean | undefined;
52
+ }>;
42
53
  /** Expose the enum to the template for state comparisons. */
43
54
  readonly AttendanceState: typeof AttendanceState;
55
+ /**
56
+ * Whether the meeting is eligible for an attendance action (an attendance
57
+ * button is rendered at all). The backend supplies an `attendanceState` for
58
+ * every loggable meeting, so its presence is the eligibility signal. Rows the
59
+ * backend deems ineligible carry no state and render no button.
60
+ * @return {boolean} True when the meeting is attendance-eligible.
61
+ * @memberof MeetingAttendanceRowComponent
62
+ */
63
+ get isEligibleForAttendance(): boolean;
64
+ /**
65
+ * Whether the meeting is currently In Progress. Mirrors the attendance
66
+ * library's `isMeetingActive`: the attendance button is only ENABLED during
67
+ * the meeting; outside the meeting time it renders disabled with the inactive
68
+ * message.
69
+ * @return {boolean} True when the meeting status is 'In Progress'.
70
+ * @memberof MeetingAttendanceRowComponent
71
+ */
72
+ get isMeetingActive(): boolean;
73
+ /** The inactive-button message shown when the meeting is not In Progress. */
74
+ get inactiveMessage(): string;
44
75
  /**
45
76
  * Whether this row is actionable — a non-empty `meetingId` is required for the
46
77
  * meeting-name link and action button to emit anything (Req 7.10).
@@ -56,17 +87,26 @@ export declare class MeetingAttendanceRowComponent {
56
87
  */
57
88
  get isCurrentlyAttending(): boolean;
58
89
  /**
59
- * Whether the log-attendance button should be shown: only when the row is in
60
- * the log state (not currently attending) and the host grants
61
- * `canLogAttendance` (Req 7.6, 12.1).
90
+ * Whether the log-attendance button should be shown: whenever the row is not
91
+ * currently attending. Mirrors the attendance library, which toggles between
92
+ * Log Attendance and Leave Meeting purely on attendance state (no permission
93
+ * gating).
62
94
  * @return {boolean} True when the log-attendance button is visible.
63
95
  * @memberof MeetingAttendanceRowComponent
64
96
  */
65
97
  get showLogAttendanceButton(): boolean;
66
98
  /**
67
- * Whether the leave-meeting button should be shown: only when the row is in
68
- * the currently-attending state and the host grants `canLeaveMeeting`
69
- * (Req 7.5, 12.2).
99
+ * Whether the Log Attendance button is disabled: outside the meeting time
100
+ * (not In Progress) or while an attendance action is in flight. Matches the
101
+ * view-meeting page, which disables the button with an inactive message when
102
+ * the meeting is not active.
103
+ * @return {boolean} True when the Log Attendance button should be disabled.
104
+ * @memberof MeetingAttendanceRowComponent
105
+ */
106
+ get isLogDisabled(): boolean;
107
+ /**
108
+ * Whether the leave-meeting button should be shown: whenever the row is
109
+ * currently attending. Mirrors the attendance library (no permission gating).
70
110
  * @return {boolean} True when the leave-meeting button is visible.
71
111
  * @memberof MeetingAttendanceRowComponent
72
112
  */
@@ -95,6 +135,20 @@ export declare class MeetingAttendanceRowComponent {
95
135
  * @memberof MeetingAttendanceRowComponent
96
136
  */
97
137
  get formattedTime(): string;
138
+ /**
139
+ * The bold time range only (e.g. "10:00–11:00"), 12-hour with meridiem,
140
+ * rendered dark per Figma.
141
+ * @return {string} The formatted start–end time range.
142
+ * @memberof MeetingAttendanceRowComponent
143
+ */
144
+ get timeRange(): string;
145
+ /**
146
+ * The timezone label only (light grey per Figma), wrapped in parentheses, or
147
+ * an empty string when no timezone is present.
148
+ * @return {string} The parenthesised timezone, or an empty string.
149
+ * @memberof MeetingAttendanceRowComponent
150
+ */
151
+ get timezoneDisplay(): string;
98
152
  /**
99
153
  * Handles activation of the attendance action button. Delegates to the pure
100
154
  * `resolveAttendanceAction` handler and emits exactly one event based on the
@@ -111,5 +165,5 @@ export declare class MeetingAttendanceRowComponent {
111
165
  */
112
166
  onOpenMeeting(): void;
113
167
  static ɵfac: i0.ɵɵFactoryDeclaration<MeetingAttendanceRowComponent, never>;
114
- static ɵcmp: i0.ɵɵComponentDeclaration<MeetingAttendanceRowComponent, "ieeesa-meeting-attendance-row", never, { "meeting": { "alias": "meeting"; "required": false; }; "attendanceState": { "alias": "attendanceState"; "required": false; }; "isInFlight": { "alias": "isInFlight"; "required": false; }; "permissions": { "alias": "permissions"; "required": false; }; "compact": { "alias": "compact"; "required": false; }; }, { "openMeeting": "openMeeting"; "logAttendance": "logAttendance"; "leaveMeeting": "leaveMeeting"; }, never, never, true, never>;
168
+ static ɵcmp: i0.ɵɵComponentDeclaration<MeetingAttendanceRowComponent, "ieeesa-meeting-attendance-row", never, { "meeting": { "alias": "meeting"; "required": false; }; "attendanceState": { "alias": "attendanceState"; "required": false; }; "isInFlight": { "alias": "isInFlight"; "required": false; }; "permissions": { "alias": "permissions"; "required": false; }; "compact": { "alias": "compact"; "required": false; }; }, { "openMeeting": "openMeeting"; "logAttendance": "logAttendance"; "leaveMeeting": "leaveMeeting"; "navigateToMeeting": "navigateToMeeting"; }, never, never, true, never>;
115
169
  }
@@ -39,6 +39,7 @@ export declare class MemberLevelBadgeComponent {
39
39
  };
40
40
  emptyMessage: string;
41
41
  errorMessage: string;
42
+ collapsedSummaryTemplate: string;
42
43
  paginator: {
43
44
  rangeTemplate: string;
44
45
  };
@@ -47,7 +48,14 @@ export declare class MemberLevelBadgeComponent {
47
48
  eventBadge: string;
48
49
  standaloneBadge: string;
49
50
  viewLabel: string;
50
- viewEventLabel: string;
51
+ viewEventLabel: string; /**
52
+ * Builds the single-item Legend list for the supplied member level, resolving
53
+ * the pill color from the `constants.json` color map and falling back to the
54
+ * configured default color when the level has no explicit mapping.
55
+ * @param {string} memberLevel - The member-level label to render.
56
+ * @return {Legend[]} A single-element Legend array for the Legend component.
57
+ * @memberof MemberLevelBadgeComponent
58
+ */
51
59
  eventDatesLabel: string;
52
60
  meetingDateLabel: string;
53
61
  timeTimezoneLabel: string;
@@ -76,6 +84,7 @@ export declare class MemberLevelBadgeComponent {
76
84
  currentlyAttendingIndicator: string;
77
85
  logAttendanceLabel: string;
78
86
  leaveMeetingLabel: string;
87
+ inactiveMessage: string;
79
88
  ariaLabel: {
80
89
  meetingNameLink: string;
81
90
  logAttendance: string;
@@ -139,6 +148,8 @@ export declare class MemberLevelBadgeComponent {
139
148
  groupDetail: string;
140
149
  viewAllEvents: string;
141
150
  viewAllGroups: string;
151
+ viewMeeting: string;
152
+ viewMeetingUnderEvent: string;
142
153
  };
143
154
  };
144
155
  private memberLevelValue;
@@ -42,6 +42,8 @@ export declare class UpcomingMeetingsEventsComponent {
42
42
  inFlightMeetingIds: ReadonlySet<string>;
43
43
  /** Whether the host has determined the viewport is at/below the mobile breakpoint. */
44
44
  isMobileView: boolean;
45
+ /** Event ids whose drill-down meetings are currently loading (spinner). */
46
+ loadingEventIds: ReadonlySet<string>;
45
47
  /** Emits when the "View All" link is activated (Req 5.2). */
46
48
  viewAll: EventEmitter<void>;
47
49
  /** Bubbles the event id when a card's "View Event" button is activated (Req 6.4). */
@@ -56,10 +58,18 @@ export declare class UpcomingMeetingsEventsComponent {
56
58
  meetingPageChange: EventEmitter<{
57
59
  eventId: string;
58
60
  } & PageChange>;
59
- /** Emits the event id + one-based page to lazily load an event's child meetings. */
61
+ /** Emits the event id + one-based page + size to lazily load an event's child meetings. */
60
62
  loadEventMeetings: EventEmitter<{
61
63
  eventId: string;
62
64
  page: number;
65
+ size: number;
66
+ }>;
67
+ /** Bubbles a navigate-to-meeting request (eventId + meetingId [+ logAttendance]) for the host to route. */
68
+ navigateToMeeting: EventEmitter<{
69
+ eventId: string;
70
+ meetingId: string;
71
+ logAttendance?: boolean | undefined;
72
+ leaveMeeting?: boolean | undefined;
63
73
  }>;
64
74
  /** Whether the section's card list is currently expanded; starts collapsed. */
65
75
  isExpanded: boolean;
@@ -94,6 +104,30 @@ export declare class UpcomingMeetingsEventsComponent {
94
104
  * @memberof UpcomingMeetingsEventsComponent
95
105
  */
96
106
  onSectionPageChange(event: PageEvent): void;
107
+ /** Number of EVENT rows in the list (for the collapsed summary). */
108
+ get eventCount(): number;
109
+ /**
110
+ * Total number of meetings across the list: each event's `meetingCount` plus
111
+ * one per standalone meeting (for the collapsed summary).
112
+ * @return {number} The total meeting count.
113
+ * @memberof UpcomingMeetingsEventsComponent
114
+ */
115
+ get totalMeetingCount(): number;
116
+ /**
117
+ * Total number of meetings open for attendance across the list (for the
118
+ * collapsed summary): each event's open count plus any standalone meeting that
119
+ * is attendance-eligible.
120
+ * @return {number} The total open-for-attendance count.
121
+ * @memberof UpcomingMeetingsEventsComponent
122
+ */
123
+ get totalOpenForAttendanceCount(): number;
124
+ /**
125
+ * The collapsed summary line (e.g. "3 events · 50 meetings · 21 open for
126
+ * attendance") built from the `constants.json` template and the counts.
127
+ * @return {string} The formatted collapsed summary.
128
+ * @memberof UpcomingMeetingsEventsComponent
129
+ */
130
+ get collapsedSummary(): string;
97
131
  /**
98
132
  * Allows the host/container to open or close the section (e.g. a "Jump to"
99
133
  * shortcut opens it). Writing the input mirrors the value onto the internal
@@ -169,7 +203,21 @@ export declare class UpcomingMeetingsEventsComponent {
169
203
  * @param {number} page - The one-based page requested by the card.
170
204
  * @memberof UpcomingMeetingsEventsComponent
171
205
  */
172
- onLoadEventMeetings(eventId: string, page: number): void;
206
+ onLoadEventMeetings(eventId: string, request: {
207
+ page: number;
208
+ size: number;
209
+ }): void;
210
+ /**
211
+ * Bubbles a card's navigate-to-meeting request upward unchanged.
212
+ * @param {{ eventId: string; meetingId: string }} request - The meeting identity.
213
+ * @memberof UpcomingMeetingsEventsComponent
214
+ */
215
+ onNavigateToMeeting(request: {
216
+ eventId: string;
217
+ meetingId: string;
218
+ logAttendance?: boolean;
219
+ leaveMeeting?: boolean;
220
+ }): void;
173
221
  static ɵfac: i0.ɵɵFactoryDeclaration<UpcomingMeetingsEventsComponent, never>;
174
- static ɵcmp: i0.ɵɵComponentDeclaration<UpcomingMeetingsEventsComponent, "ieeesa-upcoming-meetings-events", never, { "events": { "alias": "events"; "required": false; }; "sectionState": { "alias": "sectionState"; "required": false; }; "permissions": { "alias": "permissions"; "required": false; }; "attendanceStates": { "alias": "attendanceStates"; "required": false; }; "inFlightMeetingIds": { "alias": "inFlightMeetingIds"; "required": false; }; "isMobileView": { "alias": "isMobileView"; "required": false; }; "expanded": { "alias": "expanded"; "required": false; }; }, { "viewAll": "viewAll"; "viewEvent": "viewEvent"; "openMeeting": "openMeeting"; "logAttendance": "logAttendance"; "leaveMeeting": "leaveMeeting"; "meetingPageChange": "meetingPageChange"; "loadEventMeetings": "loadEventMeetings"; "expandedChange": "expandedChange"; }, never, never, true, never>;
222
+ static ɵcmp: i0.ɵɵComponentDeclaration<UpcomingMeetingsEventsComponent, "ieeesa-upcoming-meetings-events", never, { "events": { "alias": "events"; "required": false; }; "sectionState": { "alias": "sectionState"; "required": false; }; "permissions": { "alias": "permissions"; "required": false; }; "attendanceStates": { "alias": "attendanceStates"; "required": false; }; "inFlightMeetingIds": { "alias": "inFlightMeetingIds"; "required": false; }; "isMobileView": { "alias": "isMobileView"; "required": false; }; "loadingEventIds": { "alias": "loadingEventIds"; "required": false; }; "expanded": { "alias": "expanded"; "required": false; }; }, { "viewAll": "viewAll"; "viewEvent": "viewEvent"; "openMeeting": "openMeeting"; "logAttendance": "logAttendance"; "leaveMeeting": "leaveMeeting"; "meetingPageChange": "meetingPageChange"; "loadEventMeetings": "loadEventMeetings"; "navigateToMeeting": "navigateToMeeting"; "expandedChange": "expandedChange"; }, never, never, true, never>;
175
223
  }
@@ -1,19 +1,24 @@
1
1
  import { EventEmitter } from '@angular/core';
2
2
  import { PageEvent } from '@angular/material/paginator';
3
+ import { IconButton } from '@ieeesa-npm/presentation';
3
4
  import { DashboardSectionState } from '../../models/dashboard-section-state.model';
4
5
  import { GroupHierarchyNode, GroupRow } from '../../models/group-row.model';
5
6
  import { PageChange } from '../../models/page-change.model';
6
7
  import * as i0 from "@angular/core";
7
8
  /**
8
9
  * A single rendered table row. Either a top-level group row (`kind: 'group'`,
9
- * carrying the full {@link GroupRow}) or a hierarchy (ancestor) row revealed
10
- * when a group is expanded (`kind: 'hierarchy'`, carrying the ancestor node and
11
- * its depth for indentation).
10
+ * carrying the full {@link GroupRow}) or a hierarchy node row (`kind:
11
+ * 'hierarchy'`) revealed step-by-step as the user drills down. `nodeIndex` is
12
+ * the node's position in the group's `hierarchy[]`, used to drive the next
13
+ * drill-down level and the per-node toggle (matching the Groups module, where
14
+ * each level reveals only its next child and that child carries its own +/−).
12
15
  */
13
16
  interface TableRow {
14
17
  kind: 'group' | 'hierarchy';
15
18
  group?: GroupRow;
16
19
  node?: GroupHierarchyNode;
20
+ /** Index of this node within the group's hierarchy[] (hierarchy rows only). */
21
+ nodeIndex?: number;
17
22
  level: number;
18
23
  }
19
24
  /**
@@ -42,6 +47,24 @@ export declare class YourGroupsComponent {
42
47
  readonly indentPerLevel = 28;
43
48
  /** Selectable "Items per page" page sizes. */
44
49
  readonly pageSizeOptions: number[];
50
+ /**
51
+ * Expand (+) icon button — the SAME sprite icon the Groups package uses for
52
+ * its tree expand toggle (icon-expand-collapse-plus), rendered via the shared
53
+ * IconButtonComponent for a consistent look across the app.
54
+ */
55
+ readonly expandIconButton: IconButton;
56
+ /** Collapse (−) icon button — the Groups package's icon-expand-collapse-minus. */
57
+ readonly collapseIconButton: IconButton;
58
+ /**
59
+ * Returns the +/- toggle icon button for a level, matching the Groups tree:
60
+ * the minus (collapse) icon when that level is expanded, otherwise the plus
61
+ * (expand) icon.
62
+ * @param {GroupRow} group
63
+ * @param {number} index - -1 for the group row, else the node index.
64
+ * @return {IconButton}
65
+ * @memberof YourGroupsComponent
66
+ */
67
+ getToggleButton(group: GroupRow, index: number): IconButton;
45
68
  private groupsValue;
46
69
  /** The groups rendered in the table. */
47
70
  set groups(value: GroupRow[]);
@@ -80,9 +103,15 @@ export declare class YourGroupsComponent {
80
103
  */
81
104
  set expanded(value: boolean);
82
105
  get expanded(): boolean;
83
- /** GroupIds of the top-level groups whose hierarchy is currently expanded. */
84
- private readonly expandedGroupIds;
85
- /** The flattened rows currently rendered (group rows + any expanded hierarchy rows). */
106
+ /**
107
+ * Keys of the hierarchy levels currently expanded, each `"<groupId>:<index>"`.
108
+ * Index -1 is the group row itself (its toggle reveals the first hierarchy
109
+ * node); index N is the Nth hierarchy node (its toggle reveals node N+1). A
110
+ * level only reveals the NEXT node, matching the Groups module's step-by-step
111
+ * drill-down.
112
+ */
113
+ private readonly expandedKeys;
114
+ /** The flattened rows currently rendered (group rows + any revealed hierarchy rows). */
86
115
  visibleRows: TableRow[];
87
116
  /**
88
117
  * The count shown in the header subtitle — the server total when provided,
@@ -92,26 +121,53 @@ export declare class YourGroupsComponent {
92
121
  */
93
122
  get groupCount(): number;
94
123
  /**
95
- * Whether a group row can expand: it has an ancestor hierarchy (more than the
96
- * group's own node). A single-node hierarchy (the group itself) is a leaf.
124
+ * Builds the expand/collapse key for a hierarchy level. Index -1 is the group
125
+ * row itself; index N is the Nth hierarchy node.
126
+ * @param {GroupRow} group
127
+ * @param {number} index
128
+ * @return {string}
129
+ * @memberof YourGroupsComponent
130
+ */
131
+ private levelKey;
132
+ /**
133
+ * Whether a level shows a +/- toggle.
134
+ *
135
+ * - Group row (index -1): expandable when it has ANY hierarchy node, matching
136
+ * the Groups module which shows the toggle on every group that has related
137
+ * hierarchy (driven by hasChildren, true for all these groups).
138
+ * - Hierarchy node (index N): expandable only when there is a further node
139
+ * after it (step-by-step drill-down); the deepest node is a leaf, no toggle.
140
+ * @param {GroupRow} group
141
+ * @param {number} index - -1 for the group row, else the node index.
142
+ * @return {boolean}
143
+ * @memberof YourGroupsComponent
144
+ */
145
+ isLevelExpandable(group: GroupRow, index: number): boolean;
146
+ /**
147
+ * Whether the group row shows a toggle (has related hierarchy to drill into).
97
148
  * @param {GroupRow} group
98
149
  * @return {boolean}
99
150
  * @memberof YourGroupsComponent
100
151
  */
101
152
  hasHierarchy(group: GroupRow): boolean;
102
153
  /**
103
- * Whether the given group row is currently expanded.
154
+ * Whether a given level is currently expanded (its next node is revealed).
104
155
  * @param {GroupRow} group
156
+ * @param {number} index
105
157
  * @return {boolean}
106
158
  * @memberof YourGroupsComponent
107
159
  */
160
+ isLevelExpanded(group: GroupRow, index: number): boolean;
161
+ /** Convenience for the group row (level -1). */
108
162
  isGroupExpanded(group: GroupRow): boolean;
109
163
  /**
110
- * Toggles a group's hierarchy expansion and rebuilds the visible rows.
164
+ * Toggles a level's expansion (reveals/hides its next node). Collapsing a
165
+ * level also collapses everything deeper under it so re-opening starts fresh.
111
166
  * @param {GroupRow} group
167
+ * @param {number} index - -1 for the group row, else the node index.
112
168
  * @memberof YourGroupsComponent
113
169
  */
114
- onToggleHierarchy(group: GroupRow): void;
170
+ onToggleLevel(group: GroupRow, index: number): void;
115
171
  /**
116
172
  * Toggles the card's expanded/collapsed state (whole table visibility) and
117
173
  * emits the new state so the host's two-way binding stays in sync.
@@ -147,9 +203,11 @@ export declare class YourGroupsComponent {
147
203
  */
148
204
  trackByRow(index: number, row: TableRow): string;
149
205
  /**
150
- * Rebuilds the flat list of visible rows: the current page of top-level group
151
- * rows, each optionally followed by its hierarchy (ancestor) rows when the
152
- * group is expanded. The hierarchy path is shown root→leaf, indented by depth.
206
+ * Rebuilds the visible rows for the current page. Each group reveals its
207
+ * hierarchy ONE level at a time (Groups-module style): the group row reveals
208
+ * node 0 only when its own level (-1) is expanded; node 0 reveals node 1 only
209
+ * when node 0's level is expanded; and so on. Each revealed node that still
210
+ * has a child carries its own +/- toggle.
153
211
  * @memberof YourGroupsComponent
154
212
  */
155
213
  private rebuildRows;
@@ -25,6 +25,8 @@ export interface DashboardNavigationIntent {
25
25
  path: string;
26
26
  /** The identifier that triggered the navigation (event/meeting/group id), when applicable. */
27
27
  id?: string;
28
+ /** Query params to attach to the navigation (e.g. eventId/meetingId/actionType). */
29
+ queryParams?: Record<string, string>;
28
30
  }
29
31
  /**
30
32
  * Dashboard (`ieeesa-dashboard`) is the root container and single host entry
@@ -86,6 +88,7 @@ export declare class DashboardComponent implements OnInit, OnDestroy {
86
88
  };
87
89
  emptyMessage: string;
88
90
  errorMessage: string;
91
+ collapsedSummaryTemplate: string;
89
92
  paginator: {
90
93
  rangeTemplate: string;
91
94
  };
@@ -98,6 +101,12 @@ export declare class DashboardComponent implements OnInit, OnDestroy {
98
101
  eventDatesLabel: string;
99
102
  meetingDateLabel: string;
100
103
  timeTimezoneLabel: string;
104
+ /**
105
+ * A navigation intent emitted by {@link DashboardComponent} for the host
106
+ * application to act on. The library never performs navigation itself; it emits
107
+ * the resolved target `path` (from the {@link DashboardRouteConfig}) together
108
+ * with the triggering identifier so the host can route accordingly (Req 11.1).
109
+ */
101
110
  meetingsLabel: string;
102
111
  openForAttendanceTemplate: string;
103
112
  meetingListToggle: {
@@ -109,7 +118,7 @@ export declare class DashboardComponent implements OnInit, OnDestroy {
109
118
  ariaLabel: {
110
119
  view: string;
111
120
  viewEvent: string;
112
- meetingListToggle: string; /** The resolved target route path from the active {@link DashboardRouteConfig}. */
121
+ meetingListToggle: string; /** The identifier that triggered the navigation (event/meeting/group id), when applicable. */
113
122
  };
114
123
  paginator: {
115
124
  rangeTemplate: string;
@@ -123,6 +132,7 @@ export declare class DashboardComponent implements OnInit, OnDestroy {
123
132
  currentlyAttendingIndicator: string;
124
133
  logAttendanceLabel: string;
125
134
  leaveMeetingLabel: string;
135
+ inactiveMessage: string;
126
136
  ariaLabel: {
127
137
  meetingNameLink: string;
128
138
  logAttendance: string;
@@ -186,6 +196,8 @@ export declare class DashboardComponent implements OnInit, OnDestroy {
186
196
  groupDetail: string;
187
197
  viewAllEvents: string;
188
198
  viewAllGroups: string;
199
+ viewMeeting: string;
200
+ viewMeetingUnderEvent: string;
189
201
  };
190
202
  };
191
203
  /** Host navigation paths; falls back to the `constants.json` default when omitted (Req 11.1, 11.5). */
@@ -214,6 +226,8 @@ export declare class DashboardComponent implements OnInit, OnDestroy {
214
226
  attendancePermissions: AttendanceActionPermissions;
215
227
  /** Whether the viewport is at/below the mobile breakpoint (Req 15.1, 15.2). */
216
228
  isMobileView: boolean;
229
+ /** Event ids whose drill-down meetings are currently loading (spinner). */
230
+ loadingEventIds: ReadonlySet<string>;
217
231
  /** Whether the Upcoming Meetings & Events card is expanded. Starts collapsed. */
218
232
  meetingsExpanded: boolean;
219
233
  /** Whether the Your Groups card is expanded. Starts collapsed. */
@@ -295,8 +309,11 @@ export declare class DashboardComponent implements OnInit, OnDestroy {
295
309
  */
296
310
  onViewEvent(eventId: string): void;
297
311
  /**
298
- * Emits the open-meeting navigation intent, targeting the `meetingDetail`
299
- * route with the meeting id (Req 7.4, 11.1).
312
+ * Emits the open-meeting navigation intent to the view-meeting screen,
313
+ * matching the reference list: a meeting under an event targets
314
+ * `viewMeetingUnderEvent` with `eventId` + `meetingId` + `actionType=edit`; a
315
+ * standalone meeting targets `viewMeeting` with `meetingId` + `actionType=edit`.
316
+ * (Retained for the legacy string `openMeeting` output.)
300
317
  * @param {string} meetingId - The id of the meeting to open.
301
318
  * @return {void}
302
319
  * @memberof DashboardComponent
@@ -336,6 +353,39 @@ export declare class DashboardComponent implements OnInit, OnDestroy {
336
353
  onLoadEventMeetings(request: {
337
354
  eventId: string;
338
355
  page: number;
356
+ size: number;
357
+ }): void;
358
+ /**
359
+ * Updates the set of events whose drill-down meetings are currently loading,
360
+ * so each event card can show a spinner while its page resolves.
361
+ * @param {string} eventId - The event being loaded.
362
+ * @param {boolean} loading - Whether the load is in progress.
363
+ * @return {void}
364
+ * @memberof DashboardComponent
365
+ */
366
+ private setEventLoading;
367
+ /**
368
+ * Whether the given event's drill-down meetings are currently loading.
369
+ * @param {string} eventId - The event id.
370
+ * @return {boolean} True while the event's meetings are loading.
371
+ * @memberof DashboardComponent
372
+ */
373
+ isEventLoading(eventId: string): boolean;
374
+ /**
375
+ * Handles an attendance-button activation for an In-Progress meeting by
376
+ * emitting a navigation intent to the view-meeting screen with `eventId`,
377
+ * `meetingId`, and `actionType=edit` query params — producing a URL like
378
+ * `/events-and-meetings/view-event/view-meeting?eventId=...&meetingId=...&actionType=edit`.
379
+ * The Log Attendance popup is opened by that destination page.
380
+ * @param {{ eventId: string; meetingId: string }} request - The meeting identity.
381
+ * @return {void}
382
+ * @memberof DashboardComponent
383
+ */
384
+ onNavigateToMeeting(request: {
385
+ eventId: string;
386
+ meetingId: string;
387
+ logAttendance?: boolean;
388
+ leaveMeeting?: boolean;
339
389
  }): void;
340
390
  /**
341
391
  * Delegates a log-attendance request to the service, surfacing the
@@ -1,4 +1,11 @@
1
+ /**
2
+ * Per-meeting attendance state as returned by the home endpoints.
3
+ * - NOT_ATTENDING: the user has not logged attendance (shows Log Attendance).
4
+ * - CURRENTLY_ATTENDING: the user is logged in (shows Leave Meeting + pill).
5
+ * - ATTENDED: the user attended and has since logged out.
6
+ */
1
7
  export declare enum AttendanceState {
2
8
  CURRENTLY_ATTENDING = "CURRENTLY_ATTENDING",
3
- NOT_ATTENDING = "NOT_ATTENDING"
9
+ NOT_ATTENDING = "NOT_ATTENDING",
10
+ ATTENDED = "ATTENDED"
4
11
  }
@@ -1,7 +1,21 @@
1
1
  export interface DashboardRouteConfig {
2
+ /** View-event screen; the dashboard appends `?eventId=`. e.g. `/events-and-meetings/view-event`. */
2
3
  eventDetail: string;
4
+ /** Legacy meeting-detail route (kept for backward compatibility). */
3
5
  meetingDetail: string;
4
6
  groupDetail: string;
5
7
  viewAllEvents: string;
6
8
  viewAllGroups: string;
9
+ /**
10
+ * Standalone view-meeting screen. The dashboard appends `meetingId` and
11
+ * `actionType=edit` (and `logAttendance=true` for the Log Attendance action),
12
+ * e.g. `/events-and-meetings/view-meeting`.
13
+ */
14
+ viewMeeting?: string;
15
+ /**
16
+ * View-meeting-under-event screen. The dashboard appends `eventId`,
17
+ * `meetingId`, and `actionType=edit`,
18
+ * e.g. `/events-and-meetings/view-event/view-meeting`.
19
+ */
20
+ viewMeetingUnderEvent?: string;
7
21
  }