feat(meetings): add ical subscribe + calendar view to meetings dashboard#697
Conversation
LFXV2-1771: Extend the iCal Subscribe modal (LFXV2-1714 / PR #689) and a List/Calendar view toggle to the global Meetings dashboard for the foundation and project lenses. Frontend (apps/lfx-one): - meetings-dashboard.component.ts: add viewMode signal + isListView / isCalendarView computeds; add calendarEvents signal projecting filteredMeetings into FullCalendar EventInput[]; add onSubscribe() that opens IcalSubscribeDialogComponent with the correct lens-aware feed URL; add onCalendarEventClick() (cancelled occurrences are inert). - meetings-dashboard.component.html: introduce the [List] [Calendar] [Subscribe] toggle row between the filter bar and the meeting list; render calendar legend + <lfx-fullcalendar> when isCalendarView() is active; Create Meeting stays at the top of the title row. - committee-meetings.component.ts: parity fix — cancelled occurrences no longer accept clicks and render with cursor-default. - ical-subscribe-dialog.component.ts + committees caller: rename dialog data key committeeName → name (dialog is no longer committee-specific). Shared infrastructure (apps/lfx-one/src/app/shared/components/fullcalendar): - fullcalendar.component.scss: scope the timegrid bg-gray-100 / bg-blue-50 forced backgrounds to .meeting-event-classed entries only. Previously the blanket !important override made any inline-coloured event invisible in Week view (white text on near-white background). This also fixes the latent Week-view visibility bug on the committee tab. - fullcalendar.component.ts: scrollTime fixed at 06:00 instead of the current hour, so Week view opens to a sensible starting hour. Backend (apps/lfx-one/src/server): - controllers/project.controller.ts: add getProjectCalendar that mirrors getCommitteeCalendar exactly — public access via M2M token, paginated upcoming + past meetings filtered by tag project_uid:<id>, helpers meetingsToVEvents + buildVCalendar, text/calendar response with 15-minute Cache-Control. - routes/public-projects.route.ts (NEW): single public route GET /:id/calendar.ics → projectController.getProjectCalendar. - server.ts (protected): wire app.use('/public/api/projects', publicProjectsRouter). Shared types (packages/shared/src/interfaces): - IcalSubscribeDialogData.committeeName → name to reflect the broader use case. Scope and follow-ups: - The "Me" lens is intentionally not implemented (parked in LFXV2-1772). A personal subscription URL needs a token design because calendar clients cannot carry session cookies. - The "Org" lens is parked in LFXV2-1770. - Foundation feed currently includes only meetings directly tagged to the foundation (project_uid:<foundation_uid>). Sub-project meetings are not yet rolled up; that requires either a new upstream tag or a cross-project fan-out and can be a follow-up. Signed-off-by: Manish Dixit <mdixit@linuxfoundation.org>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
WalkthroughAdds a calendar view and iCal subscription flow: shared interface rename to ChangesCalendar iCal Subscription and Meeting Calendar View
sequenceDiagram
participant User
participant MeetingsDashboard
participant IcalSubscribeDialog
participant PublicAPI
participant ProjectController
participant MeetingService
User->>MeetingsDashboard: click Subscribe / click calendar event
MeetingsDashboard->>IcalSubscribeDialog: open({ feedUrl, name })
MeetingsDashboard->>PublicAPI: GET /public/api/projects/:id/calendar.ics
PublicAPI->>ProjectController: handle getProjectCalendar(req)
ProjectController->>MeetingService: fetch upcoming & past meetings (paginated)
ProjectController->>ProjectController: filter to PUBLIC && !restricted
ProjectController->>PublicAPI: return .ics payload
MeetingsDashboard->>User: show calendar / navigate to meeting (unless cancelled)
🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@apps/lfx-one/src/app/modules/meetings/meetings-dashboard/meetings-dashboard.component.html`:
- Around line 225-245: The calendar branch in meetings-dashboard.component.html
(inside the isCalendarView() block that renders <lfx-fullcalendar> and the
loading spinner) doesn't trigger pagination, so calendar view only shows page 1
while list view calls loadMore(); update the calendar branch to invoke the same
pagination fallback used by list view: when (timeFilter() === 'upcoming' &&
meetingsLoading()) || (timeFilter() === 'past' && pastMeetingsLoading()) show
the spinner AND, when calendarEvents() is rendered, ensure you call or wire the
existing loadMore() mechanism (or expose the component method that triggers
loading additional pages) so additional pages are fetched as the calendar needs
them (use the same loadMore() helper used elsewhere to keep behavior consistent
with list mode).
In
`@apps/lfx-one/src/app/modules/meetings/meetings-dashboard/meetings-dashboard.component.ts`:
- Around line 252-253: The feed URL should encode the project ID to avoid
breaking links when it contains reserved characters; update the template that
builds feedUrl (the const feedUrl using projectCtx.uid in
meetings-dashboard.component.ts) to use an encoded ID (e.g., replace
projectCtx.uid with encodeURIComponent(projectCtx.uid)) so the path segment is
safely escaped while leaving the rest of the URL and the name assignment
unchanged.
In `@apps/lfx-one/src/server/controllers/project.controller.ts`:
- Around line 881-888: getProjectCalendar currently aggregates meetings via
fetchAllMeetingPages / meetingService.getMeetings but doesn't filter out
non-public items; after collecting upcoming and past (the variables upcoming and
past) combine them and filter to only include meetings where meeting.visibility
=== MeetingVisibility.PUBLIC and not meeting.restricted before rendering the
ICS. Apply the same change in getCommitteeCalendar: after fetching its
upcoming/past pages, replace the raw concatenation with a filtered list (use
MeetingVisibility.PUBLIC and the restricted flag) so private or restricted
meetings are excluded from the public calendar.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: bdf6de84-cdfe-4879-9745-fca34e991903
📒 Files selected for processing (10)
apps/lfx-one/src/app/modules/committees/components/committee-meetings/committee-meetings.component.tsapps/lfx-one/src/app/modules/committees/components/ical-subscribe-dialog/ical-subscribe-dialog.component.tsapps/lfx-one/src/app/modules/meetings/meetings-dashboard/meetings-dashboard.component.htmlapps/lfx-one/src/app/modules/meetings/meetings-dashboard/meetings-dashboard.component.tsapps/lfx-one/src/app/shared/components/fullcalendar/fullcalendar.component.scssapps/lfx-one/src/app/shared/components/fullcalendar/fullcalendar.component.tsapps/lfx-one/src/server/controllers/project.controller.tsapps/lfx-one/src/server/routes/public-projects.route.tsapps/lfx-one/src/server/server.tspackages/shared/src/interfaces/committee.interface.ts
There was a problem hiding this comment.
Pull request overview
Adds end-to-end iCal subscription for project/foundation meetings and introduces a calendar view on the Meetings dashboard, reusing the existing iCal Subscribe dialog and FullCalendar wrapper.
Changes:
- Frontend: Adds a List/Calendar toggle and Subscribe action to the Meetings dashboard; maps filtered meetings into FullCalendar events and handles event-click navigation (with cancelled occurrences intended to be inert).
- Backend: Adds a public
/public/api/projects/:id/calendar.icsICS feed endpoint (route + controller method) mirroring the existing committee calendar feed pattern. - Shared/UI: Generalizes the iCal Subscribe dialog data (
committeeName→name) and adjusts FullCalendar wrapper styling/behavior (scoped timegrid overrides + fixedscrollTime).
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/shared/src/interfaces/committee.interface.ts | Renames iCal subscribe dialog data field to be non-committee-specific (name). |
| apps/lfx-one/src/server/server.ts | Registers new public projects router under /public/api/projects. |
| apps/lfx-one/src/server/routes/public-projects.route.ts | Adds public route GET /:id/calendar.ics for project/foundation calendar feeds. |
| apps/lfx-one/src/server/controllers/project.controller.ts | Implements getProjectCalendar() ICS feed generation via MeetingService + ICS helpers. |
| apps/lfx-one/src/app/shared/components/fullcalendar/fullcalendar.component.ts | Sets week view scrollTime to a fixed 06:00:00. |
| apps/lfx-one/src/app/shared/components/fullcalendar/fullcalendar.component.scss | Scopes timegrid event background overrides to .meeting-event only. |
| apps/lfx-one/src/app/modules/meetings/meetings-dashboard/meetings-dashboard.component.ts | Adds viewMode, calendar event projection, calendar click handling, and Subscribe modal wiring. |
| apps/lfx-one/src/app/modules/meetings/meetings-dashboard/meetings-dashboard.component.html | Adds List/Calendar toggle UI, Subscribe button (foundation/project), and calendar view rendering + legend. |
| apps/lfx-one/src/app/modules/committees/components/ical-subscribe-dialog/ical-subscribe-dialog.component.ts | Updates dialog to use generalized name for Outlook deep-links. |
| apps/lfx-one/src/app/modules/committees/components/committee-meetings/committee-meetings.component.ts | Makes cancelled calendar occurrences inert (click short-circuit + attempts cursor change). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Address review comments from @coderabbitai and @copilot-pull-request-reviewer: - project.controller.ts, committee.controller.ts: filter PRIVATE / restricted meetings out of the public iCal feeds. The public endpoints previously returned ALL meetings matching the project_uid / committee_uid tag — anyone with the UID could subscribe and see private meeting titles + times. Now mirrors PublicMeetingController.getMeeting's visibility guard: `visibility === MeetingVisibility.PUBLIC && !restricted` (per @coderabbitai — security blocker) - meetings-dashboard.component.ts: switch the calendar event source from the list-view's paginated `filteredMeetings()` to the dashboard's non-paginated raw signals (rawUserMeetings + rawUserPastMeetings for the Me lens; rawFpUpcomingMeetings + rawFpPastMeetings for foundation/project). The calendar no longer silently misses meetings beyond the first scroll page (per @coderabbitai — major) - meetings-dashboard.component.ts: wrap projectCtx.uid with encodeURIComponent in the feed URL so reserved characters in IDs don't break links (per @coderabbitai — minor) - project.controller.ts: fix JSDoc route comment — was `GET /projects/:id/...`, now matches the actual public path `GET /public/api/projects/:id/calendar.ics` (per @copilot-pull-request-reviewer) - fullcalendar.component.scss: add explicit `.fc-event.cursor-default { cursor: default !important; }` override so cancelled occurrences (and the vote/survey markers on the committee tab) actually drop the pointer cursor — the wrapper's `.fc .fc-event { cursor: pointer }` rule has higher specificity than Tailwind's `.cursor-default` utility, so classNames: ['cursor-default'] alone wouldn't win. Also disable the hover-lift on inert events (per @copilot-pull-request-reviewer) - meetings-dashboard.component.html, committee-meetings.component.html: legend dot for "Meeting (default)" changed from bg-blue-600 → bg-blue-500 so it matches MEETING_TYPE_COLORS.default (#3b82f6 — Tailwind blue-500) (per @copilot-pull-request-reviewer) Resolves 7 review threads. Signed-off-by: Manish Dixit <mdixit@linuxfoundation.org>
Review Feedback AddressedCommit: bfd0993 Security fix (data leakage)
Calendar correctness
Polish
Threads Resolved7 of 7 unresolved threads addressed in this iteration. |
|
I'll kick off a fresh review against the updated commit. (◕‿◕✿) 🐇 ✅ Actions performedReview triggered.
|
Comment-style fixes per @MRashad26 — collapse multi-line comments/JSDoc to one line, delete WHAT-style section headers, extract inline computed() to a private init function per the repo's one-line-max rule. - meetings-dashboard.component.html: drop view-toggle section-header comment - meetings-dashboard.component.ts: drop viewMode 3-line block, collapse calendarEvents 8-line block (and extract inline computed() to initCalendarEvents() matching the existing init pattern), collapse onSubscribe JSDoc, collapse meetingToEvents JSDoc, collapse cursor-default comment - committee-meetings.component.ts: collapse cursor-default comment - fullcalendar.component.scss: collapse the two 5-line dimming/cursor override comments - fullcalendar.component.ts: collapse scrollTime 2-line comment - committee.controller.ts: collapse 3-line PRIVATE-filter comment - project.controller.ts: collapse meetingService injection comment, delete Calendar ICS section-header, collapse getProjectCalendar JSDoc, collapse M2M-token / pagination / visibility-filter comments Also quote "\$1" in .husky/commit-msg so the hook works on paths that contain spaces. Resolves 17 review threads. Signed-off-by: Manish Dixit <mdixit@linuxfoundation.org>
Review Feedback Addressed (Round 2)Commit: All 17 unresolved threads from @MRashad26 were enforcing the same one-line-max comment rule (per CLAUDE.md / Comment-style fixes
Bonus: hook quoting fix
Threads Resolved17 of 17 unresolved threads resolved in this iteration. No questions, no discussion items, no deferred work. Validation
|
asithade
left a comment
There was a problem hiding this comment.
LGTM — approving.
What I verified
- Prior review threads all resolved in code (verified by reading the PR-branch files, not relying on "resolved" status):
- coderabbit's security blocker:
getProjectCalendar(project.controller.ts:891) andgetCommitteeCalendar(committee.controller.ts:1048) both filterm.visibility === MeetingVisibility.PUBLIC && !m.restricted, mirroringPublicMeetingController's visibility guard. Thefiltered_outcount is also logged for observability. - Calendar view pagination gap:
initCalendarEvents()now reads non-paginated raw signals (rawUserMeetings/rawFpUpcomingMeetingsetc.), so the calendar reflects the full set regardless of scroll position. - URL hygiene:
encodeURIComponent(projectCtx.uid)in the feed URL. - JSDoc route path corrected.
cursor-defaultspecificity fix: explicit.fc-event.cursor-default { cursor: default !important; }override added infullcalendar.component.scss.- Legend color matches
MEETING_TYPE_COLORS.default(bg-blue-500). - All 17 MRashad26 comment-style fixes applied (one-line max, inline
computed()extracted toinitCalendarEvents()private init).
- coderabbit's security blocker:
- Upstream API contract: validated against
lfx-v2-query-serviceandlfx-v2-meeting-serviceOpenAPI specs —tags,page_size,page_token,filters,visibility,restrictedall match. - M2M usage: appropriate —
/public/api/projects/:id/calendar.icsis a genuinely public route with no user session, mirroringgetCommitteeCalendar's established pattern.
Protected files touched (acknowledged)
apps/lfx-one/src/server/server.ts— one import + oneapp.use('/public/api/projects', publicProjectsRouter)mount that cleanly mirrors thepublicCommitteesRouterline directly above. Safe..husky/commit-msg—$1→"$1", the correct shellcheck SC2086 hardening for commit-message paths containing whitespace. Safe.
Optional nit (non-blocking)
'#ffffff'hard-coded for FullCalendarEventInput.textColorinmeetings-dashboard.component.ts:791,807. Consistent with the same literal already used incommittee-meetings.component.ts. If you ever want to centralize, anEVENT_TEXT_COLORconstant alongsideMEETING_TYPE_COLORSin@lfx-one/shared/constantswould do it — but leaving as-is is fine.
Nice work threading the security fix and the cursor-specificity fix through both controllers / both calendar surfaces.
asithade
left a comment
There was a problem hiding this comment.
LGTM — approving.
What I verified
- Prior review threads all resolved in code (verified by reading the PR-branch files, not relying on "resolved" status):
- coderabbit's security blocker:
getProjectCalendar(project.controller.ts:891) andgetCommitteeCalendar(committee.controller.ts:1048) both filterm.visibility === MeetingVisibility.PUBLIC && !m.restricted, mirroringPublicMeetingController's visibility guard. Thefiltered_outcount is also logged for observability. - Calendar view pagination gap:
initCalendarEvents()now reads non-paginated raw signals (rawUserMeetings/rawFpUpcomingMeetingsetc.), so the calendar reflects the full set regardless of scroll position. - URL hygiene:
encodeURIComponent(projectCtx.uid)in the feed URL. - JSDoc route path corrected.
cursor-defaultspecificity fix: explicit.fc-event.cursor-default { cursor: default !important; }override added infullcalendar.component.scss.- Legend color matches
MEETING_TYPE_COLORS.default(bg-blue-500). - All 17 MRashad26 comment-style fixes applied (one-line max, inline
computed()extracted toinitCalendarEvents()private init).
- coderabbit's security blocker:
- Upstream API contract: validated against
lfx-v2-query-serviceandlfx-v2-meeting-serviceOpenAPI specs —tags,page_size,page_token,filters,visibility,restrictedall match. - M2M usage: appropriate —
/public/api/projects/:id/calendar.icsis a genuinely public route with no user session, mirroringgetCommitteeCalendar's established pattern.
Protected files touched (acknowledged)
apps/lfx-one/src/server/server.ts— one import + oneapp.use('/public/api/projects', publicProjectsRouter)mount that cleanly mirrors thepublicCommitteesRouterline directly above. Safe..husky/commit-msg—$1→"$1", the correct shellcheck SC2086 hardening for commit-message paths containing whitespace. Safe.
Optional nit (non-blocking)
'#ffffff'hard-coded for FullCalendarEventInput.textColorinmeetings-dashboard.component.ts:791,807. Consistent with the same literal already used incommittee-meetings.component.ts. If you ever want to centralize, anEVENT_TEXT_COLORconstant alongsideMEETING_TYPE_COLORSin@lfx-one/shared/constantswould do it — but leaving as-is is fine.
Nice work threading the security fix and the cursor-specificity fix through both controllers / both calendar surfaces.
asithade
left a comment
There was a problem hiding this comment.
LGTM — approving.
What I verified
- Prior review threads all resolved in code (verified by reading the PR-branch files, not relying on "resolved" status):
- coderabbit's security blocker:
getProjectCalendar(project.controller.ts:891) andgetCommitteeCalendar(committee.controller.ts:1048) both filterm.visibility === MeetingVisibility.PUBLIC && !m.restricted, mirroringPublicMeetingController's visibility guard. Thefiltered_outcount is also logged for observability. - Calendar view pagination gap:
initCalendarEvents()now reads non-paginated raw signals (rawUserMeetings/rawFpUpcomingMeetingsetc.), so the calendar reflects the full set regardless of scroll position. - URL hygiene:
encodeURIComponent(projectCtx.uid)in the feed URL. - JSDoc route path corrected.
cursor-defaultspecificity fix: explicit.fc-event.cursor-default { cursor: default !important; }override added infullcalendar.component.scss.- Legend color matches
MEETING_TYPE_COLORS.default(bg-blue-500). - All 17 MRashad26 comment-style fixes applied (one-line max, inline
computed()extracted toinitCalendarEvents()private init).
- coderabbit's security blocker:
- Upstream API contract: validated against
lfx-v2-query-serviceandlfx-v2-meeting-serviceOpenAPI specs —tags,page_size,page_token,filters,visibility,restrictedall match. - M2M usage: appropriate —
/public/api/projects/:id/calendar.icsis a genuinely public route with no user session, mirroringgetCommitteeCalendar's established pattern.
Protected files touched (acknowledged)
apps/lfx-one/src/server/server.ts— one import + oneapp.use('/public/api/projects', publicProjectsRouter)mount that cleanly mirrors thepublicCommitteesRouterline directly above. Safe..husky/commit-msg—$1→"$1", the correct shellcheck SC2086 hardening for commit-message paths containing whitespace. Safe.
Optional nit (non-blocking)
'#ffffff'hard-coded for FullCalendarEventInput.textColorinmeetings-dashboard.component.ts:791,807. Consistent with the same literal already used incommittee-meetings.component.ts. If you ever want to centralize, anEVENT_TEXT_COLORconstant alongsideMEETING_TYPE_COLORSin@lfx-one/shared/constantswould do it — but leaving as-is is fine.
Nice work threading the security fix and the cursor-specificity fix through both controllers / both calendar surfaces.
Address review comments from @copilot-pull-request-reviewer: - meetings-dashboard.component.ts: initCalendarEvents now uses filterMeLensMeetings on the Me lens so Calendar applies the same foundation/project/pendingRsvp filters as the List view; FP lens keeps filterBySearchAndType since those filters aren't exposed there. - meetings-dashboard.component.ts / committee-meetings.component.ts: meetingToEvents now adds 'meeting-event' to classNames (alongside 'cursor-default' for cancelled occurrences). The shared FullCalendar SCSS scopes dimming + future-event coloring to .meeting-event, so meeting events need the class for the styling to apply. - meetings-dashboard.component.{ts,html}: new calendarLoading computed reflects the actual source loading state (fpUpcomingLoading/fpPastLoading on FP lens, meetingsLoading/pastMeetingsLoading on Me lens) and drives the calendar spinner. Previously the spinner used the paginated list loaders, so FP calendar could appear empty while the raw fetch was still in flight. - ics.helper.ts: buildVCalendar accepts an optional prodId (default '-//LFX//Calendar//EN'); committee.controller passes '-//LFX//Committee Calendar//EN', project.controller passes '-//LFX//Project Calendar//EN' so each feed identifies itself accurately. Resolves 5 review threads. Signed-off-by: Manish Dixit <mdixit@linuxfoundation.org>
Review Feedback Addressed (Round 3)Commit: Five new substantive findings from @copilot-pull-request-reviewer, all valid and addressed in a single commit. Changes Made
Threads Resolved5 of 5 unresolved threads addressed in this iteration. No questions, no discussion items, no deferred work. Validation
|
LFXV2-1771 Address review comment from @copilot-pull-request-reviewer on meetings-dashboard.component.html:208 — the Calendar toggle was rendered on every lens, but the Me lens skips the raw project/foundation fetch that clears `meetingsLoading` / `pastMeetingsLoading`. As a result, opening Calendar on the Me lens showed the spinner indefinitely because `calendarLoading` ORs those two flags and both stay `true` forever for that lens. Match the Subscribe button's existing gating: introduce a `canShowCalendarView` computed (`activeLens === 'foundation' || === 'project'`) and use it to (a) hide the Calendar toggle button, (b) tighten `isCalendarView` so the calendar view div doesn't render either when viewMode is 'calendar' on the Me lens (which can happen if the user toggles calendar on foundation then switches lens). `viewMode` itself is left alone so the user's calendar selection is restored when they switch back to a supported lens. The Subscribe button's inline lens check is also collapsed to use the new computed for consistency. Resolves 1 review thread. Generated with [Claude Code](https://claude.com/claude-code) Signed-off-by: Manish Dixit <mdixit@linuxfoundation.org>
Review feedback addressed (round 4)Commit: 27fb478 Changes Made
Threads Resolved1 of 1 remaining unresolved thread addressed in this iteration. Re-reviewRe-requested from @asithade (their previous approval was dismissed by the main-merge, not by a new finding; the rest of the prior fixes still stand per their 17:09 UTC verification). 🤖 Generated with Claude Code |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
apps/lfx-one/src/app/shared/components/fullcalendar/fullcalendar.component.scss:32
- This selector also matches cancelled meeting occurrences because they now include both
meeting-eventandcursor-default. In Week view a future cancelled occurrence will have its inlineCANCELLED_COLORgray background overridden bybg-blue-50, so it no longer matches the cancelled legend or visual state. Exclude cancelled/cursor-default meeting events from the future/past background override, or give cancelled events a dedicated class with its own override.
.fc-timegrid-event.meeting-event {
&:not(.fc-event-future) {
@apply bg-gray-100 #{!important};
}
&.fc-event-future {
@apply bg-blue-50 #{!important};
| : this.filterBySearchAndType([...this.rawFpUpcomingMeetings(), ...this.rawFpPastMeetings()], search, meetingType); | ||
| return filtered.flatMap((m) => this.meetingToEvents(m)); |
dealako
left a comment
There was a problem hiding this comment.
Enough punishment. Time to approve.
Summary
Extends the iCal Subscribe modal shipped in LFXV2-1714 / PR #689 and adds a
[List] [Calendar]view toggle to the global Meetings dashboard for the foundation and project lenses. Also delivers the BFF backend endpoint so the Subscribe links actually resolve end-to-end.Related JIRAs: LFXV2-1771 (this), LFXV2-1770 (org lens, deferred), LFXV2-1772 (me lens, parked).
What changed
Frontend
meetings-dashboard.component.ts/.html): newviewModesignal +isListView/isCalendarViewcomputeds; newcalendarEventssignal that projects the existingfilteredMeetings()into FullCalendarEventInput[]; newonSubscribe()opensIcalSubscribeDialogComponentwith the lens-appropriate feed URL and aSubscribe — <name>header. The[List] [Calendar] [Subscribe]toggle row sits between the filter bar and the meeting list; Create Meeting stays in the title row.IcalSubscribeDialogData.committeeName→name(the dialog is no longer committee-specific). The existing committee caller is updated.Shared infrastructure
fullcalendar.component.scss): the blanketbg-gray-100/bg-blue-50 !importantoverrides on.fc-timegrid-eventare now scoped to.fc-timegrid-event.meeting-eventonly. Without this, every event with an inlinebackgroundColorrendered with white text on a near-white background in Week view, making the calendar look empty. This also fixes the same latent Week-view bug on the committee tab.scrollTimefixed at'06:00:00'(was scrolling to the current hour, which overshoots past the morning when checking after lunch). This also affects all other calendars in the app.Backend (BFF — Express in this repo)
controllers/project.controller.ts: newgetProjectCalendarmirroringgetCommitteeCalendarexactly — public access via M2M token, paginated upcoming + past meetings filtered bytags: project_uid:<id>, reusesmeetingsToVEvents+buildVCalendar, returnstext/calendarwithCache-Control: public, max-age=900.routes/public-projects.route.ts(new): single public routeGET /:id/calendar.ics.server.ts(protected file): wiresapp.use('/public/api/projects', publicProjectsRouter). Required for the route to work; flagged for code-owner attention.Shared types
packages/shared/src/interfaces/committee.interface.ts:IcalSubscribeDialogData.committeeName→name.Out of scope (intentional)
project_uid:<foundation_uid>). Sub-project meetings are not yet rolled up — would need a new upstream tag or a cross-project fan-out. Suitable for a follow-up.Notes for reviewers
server.tschange is protected — only adds one import and oneapp.use(...)line; pattern matches the existingpublicCommitteesRouterregistration./public/api/committees/:id/calendar.icsalready works.🤖 Generated with Claude Code