-
Notifications
You must be signed in to change notification settings - Fork 0
feat(permissions): implement role-based permission system #72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -102,4 +102,12 @@ | |
| } | ||
| } | ||
| } | ||
|
|
||
| .p-menu { | ||
| .p-menu-item-link { | ||
| .p-menu-item-icon { | ||
| @apply w-5; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -20,14 +20,16 @@ <h2 class="text-[16px] font-bold text-gray-900">Committee Management</h2> | |||||||||||||||||||||||||||||||||||||
| Manage committees, their settings, and organizational structure. Sub-committees are indicated with indentation. | ||||||||||||||||||||||||||||||||||||||
| </p> | ||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||
| <lfx-button | ||||||||||||||||||||||||||||||||||||||
| label="New Committee" | ||||||||||||||||||||||||||||||||||||||
| icon="fa-light fa-plus" | ||||||||||||||||||||||||||||||||||||||
| severity="primary" | ||||||||||||||||||||||||||||||||||||||
| (onClick)="openCreateDialog()" | ||||||||||||||||||||||||||||||||||||||
| size="small" | ||||||||||||||||||||||||||||||||||||||
| data-testid="committee-new-cta"> | ||||||||||||||||||||||||||||||||||||||
| </lfx-button> | ||||||||||||||||||||||||||||||||||||||
| @if (project()?.writer) { | ||||||||||||||||||||||||||||||||||||||
| <lfx-button | ||||||||||||||||||||||||||||||||||||||
| label="New Committee" | ||||||||||||||||||||||||||||||||||||||
| icon="fa-light fa-plus" | ||||||||||||||||||||||||||||||||||||||
| severity="primary" | ||||||||||||||||||||||||||||||||||||||
| (onClick)="openCreateDialog()" | ||||||||||||||||||||||||||||||||||||||
| size="small" | ||||||||||||||||||||||||||||||||||||||
| data-testid="committee-new-cta"> | ||||||||||||||||||||||||||||||||||||||
| </lfx-button> | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+23
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Gate the empty-state “Add First Committee” CTA too. The bottom empty-state button (Lines 149–155) is still visible to non-writers; this is inconsistent with the new gating above. Apply: - <lfx-button
- label="Add First Committee"
- icon="fa-light fa-people-group"
- severity="secondary"
- (onClick)="openCreateDialog()"
- data-testid="committee-add-first"></lfx-button>
+ @if (project()?.writer) {
+ <lfx-button
+ label="Add First Committee"
+ icon="fa-light fa-people-group"
+ severity="secondary"
+ (onClick)="openCreateDialog()"
+ data-testid="committee-add-first"></lfx-button>
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| <!-- Statistics Cards --> | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7,7 +7,9 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div class="flex justify-between gap-4 mb-8"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <h3 class="text-lg font-medium text-gray-900">Committee Members</h3> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <!-- Add Member Button --> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <lfx-button label="Add Member" icon="fa-light fa-user-plus" size="small" severity="secondary" (onClick)="openAddMemberDialog()"> </lfx-button> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @if (committee()?.writer) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <lfx-button label="Add Member" icon="fa-light fa-user-plus" size="small" severity="secondary" (onClick)="openAddMemberDialog()"> </lfx-button> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <!-- Search and Filter Controls --> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -136,14 +138,27 @@ <h3 class="text-lg font-medium text-gray-900">Committee Members</h3> | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td class="text-center relative"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <lfx-menu #memberActionMenu [model]="memberActionMenuItems" [popup]="true" appendTo="body"> </lfx-menu> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <lfx-button | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| icon="fa-light fa-ellipsis-vertical" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [text]="true" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [rounded]="true" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| size="small" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| severity="secondary" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (onClick)="toggleMemberActionMenu($event, member, memberActionMenu)"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </lfx-button> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @if (committee()?.writer) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <lfx-button | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| icon="fa-light fa-ellipsis-vertical" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [text]="true" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [rounded]="true" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| size="small" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| severity="secondary" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (onClick)="toggleMemberActionMenu($event, member, memberActionMenu)"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </lfx-button> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } @else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <lfx-button | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| icon="fa-light fa-envelope" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [text]="true" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [rounded]="true" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| size="small" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| severity="secondary" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [href]="`mailto:${member.email}`" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| target="_blank" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pTooltip="Send Message"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </lfx-button> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+141
to
+161
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guard mailto when email is missing; add testids and aria-labels Avoids mailto:undefined, improves testability and a11y. - } @else {
- <lfx-button
- icon="fa-light fa-envelope"
- [text]="true"
- [rounded]="true"
- size="small"
- severity="secondary"
- [href]="`mailto:${member.email}`"
- target="_blank"
- pTooltip="Send Message">
- </lfx-button>
- }
+ } @else if (member.email) {
+ <lfx-button
+ icon="fa-light fa-envelope"
+ [text]="true"
+ [rounded]="true"
+ size="small"
+ severity="secondary"
+ [href]="`mailto:${member.email}`"
+ target="_blank"
+ pTooltip="Send Message"
+ [attr.data-testid]="'committee-members-message-' + member.uid"
+ [attr.aria-label]="'Send email to ' + (member.first_name || '') + ' ' + (member.last_name || '')">
+ </lfx-button>
+ } @else {
+ <lfx-button
+ icon="fa-light fa-envelope-slash"
+ [text]="true"
+ [rounded]="true"
+ size="small"
+ severity="secondary"
+ [disabled]="true"
+ pTooltip="No email available"
+ [attr.data-testid]="'committee-members-noemail-' + member.uid"
+ [attr.aria-label]="'No email available'">
+ </lfx-button>
+ }Also add testids/aria-labels to the ellipsis button: - <lfx-button
+ <lfx-button
icon="fa-light fa-ellipsis-vertical"
[text]="true"
[rounded]="true"
size="small"
severity="secondary"
- (onClick)="toggleMemberActionMenu($event, member, memberActionMenu)">
+ (onClick)="toggleMemberActionMenu($event, member, memberActionMenu)"
+ [attr.data-testid]="'committee-members-actions-' + member.uid"
+ [attr.aria-label]="'Open actions for ' + (member.first_name || '') + ' ' + (member.last_name || '')">📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </tr> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </ng-template> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -199,14 +199,16 @@ <h3 class="text-sm font-display text-gray-500">Upcoming Meetings</h3> | |||||||||||||||||||||||||||||||||||||||
| <i class="fa-light fa-calendar text-4xl text-gray-400 mb-4"></i> | ||||||||||||||||||||||||||||||||||||||||
| <h3 class="text-lg font-medium text-gray-900 mb-2">No Upcoming Meetings</h3> | ||||||||||||||||||||||||||||||||||||||||
| <p class="text-gray-600 mb-4 text-sm">There are no upcoming meetings scheduled.</p> | ||||||||||||||||||||||||||||||||||||||||
| <lfx-button | ||||||||||||||||||||||||||||||||||||||||
| label="Create Meeting" | ||||||||||||||||||||||||||||||||||||||||
| icon="fa-light fa-calendar-plus" | ||||||||||||||||||||||||||||||||||||||||
| severity="secondary" | ||||||||||||||||||||||||||||||||||||||||
| size="small" | ||||||||||||||||||||||||||||||||||||||||
| [routerLink]="['meetings/create']" | ||||||||||||||||||||||||||||||||||||||||
| [relativeTo]="activatedRoute"> | ||||||||||||||||||||||||||||||||||||||||
| </lfx-button> | ||||||||||||||||||||||||||||||||||||||||
| @if (project()?.writer) { | ||||||||||||||||||||||||||||||||||||||||
| <lfx-button | ||||||||||||||||||||||||||||||||||||||||
| label="Create Meeting" | ||||||||||||||||||||||||||||||||||||||||
| icon="fa-light fa-calendar-plus" | ||||||||||||||||||||||||||||||||||||||||
| severity="secondary" | ||||||||||||||||||||||||||||||||||||||||
| size="small" | ||||||||||||||||||||||||||||||||||||||||
| [routerLink]="['meetings/create']" | ||||||||||||||||||||||||||||||||||||||||
| [relativeTo]="activatedRoute"> | ||||||||||||||||||||||||||||||||||||||||
| </lfx-button> | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+202
to
+211
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Also gate the empty-state “Add Committee” CTA. Lines 261–262 remain unconditional. Align with writer gating to avoid exposing actions to read-only users. - <lfx-button label="Add Committee" icon="fa-light fa-people-group" severity="secondary" size="small" (onClick)="openCreateDialog()">
+ @if (project()?.writer) {
+ <lfx-button label="Add Committee" icon="fa-light fa-people-group" severity="secondary" size="small" (onClick)="openCreateDialog()">
+ </lfx-button>
+ }
- </lfx-button>📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.