fix(committees): align onScheduleMeeting with surveys/votes permission-check pattern#1042
Conversation
|
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)
WalkthroughThe committee meetings schedule action now tracks in-flight state, uses the active lens to choose the denial route, and binds the button loading state in the template. ChangesSchedule Meeting Loading and Routing
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration. Comment |
There was a problem hiding this comment.
Pull request overview
Aligns the committee Meetings “Schedule Meeting” CTA behavior with the established stale-permission mitigation pattern used elsewhere (surveys/votes/mailing-lists), ensuring fresh permission validation at click time and consistent, lens-aware access-denied redirects.
Changes:
- Switches the schedule flow to use
CommitteeService.fetchCommittee()(no shared-signal mutation) for a fresh writer permission check before navigation. - Adds lens-aware access-denied redirect (
/foundation/overviewvs/project/overview) with_notice=meetings. - Introduces a
creatingsignal and binds it to the CTA’s[loading]to prevent rapid repeat submissions; updates template to use<lfx-button>’s(onClick)output.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| apps/lfx-one/src/app/modules/committees/components/committee-meetings/committee-meetings.component.ts | Adds lens-aware redirect + fresh permission check via fetchCommittee(), plus a creating loading guard for the CTA. |
| apps/lfx-one/src/app/modules/committees/components/committee-meetings/committee-meetings.component.html | Wires the Schedule Meeting CTA to (onClick) and binds [loading]="creating()". |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/lfx-one/src/app/modules/committees/components/committee-meetings/committee-meetings.component.ts (1)
99-99: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd an explicit type to the new signal.
creatingis a public component field used by the template; annotate it explicitly, e.g.public creating: WritableSignal<boolean> = signal(false);. As per coding guidelines,**/*.{ts,tsx}: Use type annotations in TypeScript files.Suggested change
- public creating = signal(false); + public creating: WritableSignal<boolean> = signal(false);🤖 Prompt for 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. In `@apps/lfx-one/src/app/modules/committees/components/committee-meetings/committee-meetings.component.ts` at line 99, The public component field creating in committee-meetings.component.ts is missing an explicit type annotation. Update the class property declaration in CommitteeMeetingsComponent to use a typed signal, such as WritableSignal<boolean>, while keeping the existing signal(false) initialization so the template-facing field remains clear and compliant with TypeScript typing guidelines.Source: Coding guidelines
🤖 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/committees/components/committee-meetings/committee-meetings.component.ts`:
- Around line 180-193: The onScheduleMeeting handler can still start multiple
fetchCommittee calls if it is clicked again before the UI disables it. Add an
early return at the start of CommitteeMeetingsComponent.onScheduleMeeting that
checks creating() and exits immediately when a scheduling request is already in
progress, so the method stays idempotent even before this.creating is set.
---
Nitpick comments:
In
`@apps/lfx-one/src/app/modules/committees/components/committee-meetings/committee-meetings.component.ts`:
- Line 99: The public component field creating in
committee-meetings.component.ts is missing an explicit type annotation. Update
the class property declaration in CommitteeMeetingsComponent to use a typed
signal, such as WritableSignal<boolean>, while keeping the existing
signal(false) initialization so the template-facing field remains clear and
compliant with TypeScript typing guidelines.
🪄 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: 8b3efe89-f579-4f9b-95fc-59ab1c598bf0
📒 Files selected for processing (2)
apps/lfx-one/src/app/modules/committees/components/committee-meetings/committee-meetings.component.htmlapps/lfx-one/src/app/modules/committees/components/committee-meetings/committee-meetings.component.ts
Add `if (this.creating()) return;` early exit so repeated fast clicks cannot launch concurrent in-flight permission checks even if the loading binding on the button were bypassed (per @coderabbitai on PR #1042). Signed-off-by: Rashad <mrashad@contractor.linuxfoundation.org>
Review Feedback AddressedCommit: 6fbd228 Changes Made
Threads Resolved
Context for reviewersThis PR aligns
@dealako ready for review when you're free! |
|
Tip For best results, initiate chat on the files or code changes.
🐇✅ |
dealako
left a comment
There was a problem hiding this comment.
@MRashad26 — clean, focused patch. Five well-reasoned fixes that bring committee-meetings into full parity with the surveys/votes/mailing-list permission-check pattern. The (onClick) fix alone is worth the PR — the silent (click) no-op meant the guard was being bypassed entirely on the async path. The fetchCommittee switch, lens-aware redirect, and creating guard all read naturally and follow the established pattern correctly.
Summary
🟡 Minor: 2 issues
⚪ Nit: 1 issue
🟡 Minor — JSDoc removed on non-obvious method
onScheduleMeeting does something a future reader will find surprising: it makes a network call before navigating, purely to check fresh permissions. The original JSDoc explained why (stale writer role, writerGuard parity). That was removed in the refactor, but the WHY is still non-obvious.
Per project conventions (CLAUDE.md): "Only add a comment when the WHY is non-obvious: a hidden constraint, a subtle invariant, a workaround for a specific bug, behavior that would surprise a reader."
A one-liner covers it:
/** Checks writer permission fresh before navigating — prevents a demoted member from reaching /meetings/create. */
protected onScheduleMeeting(): void {🟡 Minor — Missing ai-assisted label
Per CLAUDE.md policy, PRs where AI helped generate or review code should carry the ai-assisted label. The PR body has the Generated with Claude Code footer, but the label is not applied. Easy fix:
gh pr edit 1042 --add-label ai-assisted⚪ Nit — JIRA ticket absent from commit messages
.claude/rules/commit-workflow.md says to include the JIRA ticket in commit messages. Both commits omit LFXV2-2252. Branch name has it, commits don't. Worth noting for future hygiene.
AI Bot Reconciliation
CodeRabbit round 1 — actionable: missing if (this.creating()) return; early guard. Resolved by commit 6fbd228. ✅
CodeRabbit round 1 — nit: add WritableSignal<boolean> type annotation to creating. Disagree. component-organization.md explicitly shows public loading = signal(false) (no annotation) as the convention for simple WritableSignals. Other signals in this same component (meetingsLoading, pastMeetingsLoading, calendarLoading) all use the same untyped form. This suggestion contradicts local convention.
CodeRabbit round 2 — no actionable comments after the idempotency fix.
Copilot — no inline comments; clean summary.
Final Decision
✅ Approved with minor comments
Logic is correct. Operator ordering (finalize before takeUntilDestroyed) is safe — finalize fires on destroy-triggered unsubscription, and calling .set(false) on a signal post-destroy is harmless in Angular. No security findings, no SSR concerns. The two minor items are addressable as a follow-up or squash note; they do not block merge.
…s/votes pattern Five improvements to bring committee-meetings up to parity with the pattern established in the surveys (#1000), votes (#997), and mailing-list (#1016) PRs: 1. fetchCommittee() over getCommittee() — avoids the tap() side-effect that mutates the shared CommitteeService.committee signal during a permission-only check 2. Lens-aware redirect — injects LensService and uses activeLens() to select /foundation/overview vs /project/overview, matching writerGuard behaviour 3. creating = signal(false) guard — set before fetchCommittee() and cleared in finalize(), bound as [loading]="creating()" on the Schedule Meeting button to block rapid double-clicks and show a spinner 4. (onClick) over (click) — ButtonComponent emits (onClick), not a native click event 5. protected visibility on onScheduleMeeting() — template-only method; protected makes intent clear and prevents unintended external calls Signed-off-by: Rashad <mrashad@contractor.linuxfoundation.org>
Add `if (this.creating()) return;` early exit so repeated fast clicks cannot launch concurrent in-flight permission checks even if the loading binding on the button were bypassed (per @coderabbitai on PR #1042). Signed-off-by: Rashad <mrashad@contractor.linuxfoundation.org>
6fbd228 to
dd6b9c3
Compare
Review Feedback AddressedCommit: 3942e92 Changes Made
Threads Resolved1/1 @dealako thread resolved ✅ This completes the iteration. The branch is now aligned with the surveys/votes pattern across all five dimensions: Ready for review, @dealako! |
dealako
left a comment
There was a problem hiding this comment.
Re-review after commit 3942e92d and main merge 2086b18f.
Revision tracking
Round 1 findings (my prior review):
- 🟡 JSDoc removed on non-obvious method → ✅ resolved by commit
3942e92d— one-liner restored verbatim as suggested - 🟡 Missing
ai-assistedlabel → ✅ resolved (applied in round 1) - ⚪ JIRA ticket absent from commit messages → still a nit, not a blocker
CodeRabbit actionable (round 1): if (this.creating()) return; → ✅ resolved by commit 6fbd228
Copilot (post-push): no new comments — clean
New commits
3942e92d— single line addition restoring the intent JSDoc; correct and minimal2086b18f— merge from main; no code changes
Final Decision
✅ Approved — all prior round findings addressed, security audit clean, Copilot clean. Ready to merge.
Summary
Brings
CommitteeMeetingsComponent.onScheduleMeeting()to full parity with the pattern established in the parallel PRs for surveys (#1000), votes (#997), and mailing-list (#1016).Five changes — all identified during review of those sibling PRs:
fetchCommittee()overgetCommittee()— avoids thetap()side-effect that mutates the sharedCommitteeService.committeesignal during a permission-only check; matches the surveys/votes approachLensServiceand usesactiveLens()to select/foundation/overviewvs/project/overview; meetings was the only committee tab still using a hardcoded/project/overviewcreating = signal(false)double-click guard — set beforefetchCommittee(), cleared infinalize(), bound as[loading]="creating()"on the Schedule Meeting button; prevents rapid double-clicks queuing multiple in-flight permission checks(onClick)over(click)—ButtonComponentemits(onClick), not a native click event; the previous(click)binding was silently a no-op on the async check (therouterLinkstill navigated, bypassing the guard)protectedvisibility ononScheduleMeeting()— template-only method;protectedmakes intent clear and matches the surveys/votes conventionRelated PRs
Test plan
/meetings/createfor a committee writerfetchCommittee()call — rapid double-clicks are blocked/foundation/overviewon denial; project-lens redirects to/project/overviewyarn buildpasses (SSR safety)🤖 Generated with Claude Code