Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,8 @@ export class CommitteeManageComponent {
sso_group_name: committee.sso_group_name,
website: committee.website,
joinable: false,
member_visibility: committee.member_visibility || 'hidden',
show_meeting_attendees: committee.show_meeting_attendees || false,
});
}

Expand All @@ -402,6 +404,8 @@ export class CommitteeManageComponent {
sso_group_enabled: new FormControl(false),
sso_group_name: new FormControl(''),
joinable: new FormControl(false),
member_visibility: new FormControl('hidden'),
show_meeting_attendees: new FormControl(false),
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,34 @@ <h4 class="text-sm font-semibold mb-1">{{ committeeLabel }} Features</h4>
</ng-template>
</lfx-message>

<!-- Member Visibility Setting -->
<div class="space-y-2">
<h3 class="text-base font-medium text-slate-900">Member Visibility</h3>
<div class="bg-white border border-slate-200 p-4 rounded-lg">
<div class="flex flex-col gap-3">
<div class="flex items-center gap-3">
<div class="p-2 rounded-lg bg-blue-50 text-blue-500">
<i class="fa-light fa-user-lock text-sm"></i>
</div>
<div class="flex-1">
<label for="member-visibility" class="text-sm font-semibold text-slate-900">Member Profile Visibility</label>
<p class="text-xs text-slate-600">Control what member information is visible within the {{ committeeLabel.toLowerCase() }}</p>
</div>
</div>
<lfx-select
[form]="form()"
control="member_visibility"
[options]="memberVisibilityOptions"
placeholder="Select visibility level"
styleClass="w-full"
size="small"
id="member-visibility"
data-testid="member-visibility-select">
</lfx-select>
</div>
</div>
</div>

<!-- Committee Settings Features -->
<div class="space-y-4">
<h3 class="text-base font-medium text-slate-900">{{ committeeLabel }} Features</h3>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
import { Component, input } from '@angular/core';
import { FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MessageComponent } from '@components/message/message.component';
import { SelectComponent } from '@components/select/select.component';
import { ToggleComponent } from '@components/toggle/toggle.component';
import { COMMITTEE_LABEL, COMMITTEE_SETTINGS_FEATURES } from '@lfx-one/shared/constants';
import { COMMITTEE_LABEL, COMMITTEE_SETTINGS_FEATURES, MEMBER_VISIBILITY_OPTIONS } from '@lfx-one/shared/constants';

@Component({
selector: 'lfx-committee-settings',
imports: [ReactiveFormsModule, MessageComponent, ToggleComponent],
imports: [ReactiveFormsModule, MessageComponent, SelectComponent, ToggleComponent],
templateUrl: './committee-settings.component.html',
})
export class CommitteeSettingsComponent {
Expand All @@ -19,4 +20,5 @@ export class CommitteeSettingsComponent {
// Constants from shared package
public readonly features = COMMITTEE_SETTINGS_FEATURES;
public readonly committeeLabel = COMMITTEE_LABEL.singular;
public readonly memberVisibilityOptions = MEMBER_VISIBILITY_OPTIONS;
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ <h3 class="text-lg font-semibold text-gray-900">{{ fullName() | titlecase }}</h3
</div>
}

@if (member().linkedin_profile) {
<div class="flex items-center gap-2">
<i class="fa-brands fa-linkedin text-gray-400 w-4"></i>
<a [href]="member().linkedin_profile" rel="noopener noreferrer" target="_blank" class="text-sm text-primary hover:text-primary-600 hover:underline">
LinkedIn Profile
</a>
</div>
}

@if (member().organization) {
<div class="flex items-center gap-2">
<i class="fa-light fa-building text-gray-400 w-4"></i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@
<lfx-input-text size="small" [form]="form()" control="job_title" id="job-title" placeholder="Enter job title" styleClass="w-full"></lfx-input-text>
</div>

<!-- LinkedIn Profile -->
<div>
<label for="linkedin-profile" class="block text-sm font-medium text-gray-700 mb-1"> LinkedIn Profile </label>
<lfx-input-text
size="small"
[form]="form()"
control="linkedin_profile"
id="linkedin-profile"
placeholder="Enter LinkedIn profile URL"
styleClass="w-full"
data-testid="member-form-linkedin-profile"></lfx-input-text>
</div>

<!-- Organization Search -->
<div>
<label for="organization-search" class="block text-sm font-medium text-gray-700 mb-1"> Organization </label>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export class MemberFormComponent {
last_name: formValue.last_name || null,
email: formValue.email,
job_title: formValue.job_title || null,
linkedin_profile: formValue.linkedin_profile || null,
appointed_by: formValue.appointed_by || null,
role: formValue.role
? {
Expand Down Expand Up @@ -166,6 +167,7 @@ export class MemberFormComponent {
last_name: member.last_name,
email: member.email,
job_title: member.job_title,
linkedin_profile: member.linkedin_profile,
organization: member.organization?.name,
organization_url: member.organization?.website,
role: member.role?.name,
Expand All @@ -185,6 +187,7 @@ export class MemberFormComponent {
last_name: new FormControl('', [Validators.required]),
email: new FormControl('', [Validators.required, Validators.email]),
job_title: new FormControl(''),
linkedin_profile: new FormControl('', [Validators.pattern(/^https?:\/\/.+\..+/)]),
organization: new FormControl(''),
organization_url: new FormControl(''),
role: new FormControl(''),
Expand Down
16 changes: 16 additions & 0 deletions packages/shared/src/constants/committees.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -421,4 +421,20 @@ export const COMMITTEE_SETTINGS_FEATURES = [
description: 'Sync membership with Single Sign-On provider',
color: lfxColors.red[500],
},
{
key: 'show_meeting_attendees',
icon: 'fa-light fa-users-rectangle',
title: 'Show Meeting Attendees',
description: 'Display who attended or is attending committee meetings',
color: lfxColors.blue[500],
},
];

/**
* Member visibility options for committee settings
* @description Controls the visibility level of member profiles within a committee
*/
export const MEMBER_VISIBILITY_OPTIONS = [
{ label: 'Hidden', value: 'hidden' },
{ label: 'Basic Profile', value: 'basic_profile' },
];
13 changes: 13 additions & 0 deletions packages/shared/src/enums/committee.enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright The Linux Foundation and each contributor to LFX.
// SPDX-License-Identifier: MIT

/**
* Committee member visibility settings
* @description Controls the visibility level of member profiles within a committee
*/
export enum CommitteeMemberVisibility {
/** Member profiles are hidden from other members */
HIDDEN = 'hidden',
/** Basic member profile information is visible to other members */
BASIC_PROFILE = 'basic_profile',
}
1 change: 1 addition & 0 deletions packages/shared/src/enums/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

export * from './error.enum';
export * from './meeting.enum';
export * from './committee.enum';
export * from './committee-member.enum';
export * from './nats.enum';
export * from './snowflake.enum';
14 changes: 14 additions & 0 deletions packages/shared/src/interfaces/committee.interface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright The Linux Foundation and each contributor to LFX.
// SPDX-License-Identifier: MIT

import { CommitteeMemberVisibility } from '../enums/committee.enum';

/**
* Committee entity with complete details
* @description Represents a committee/working group within a project with full metadata
Expand Down Expand Up @@ -53,6 +55,10 @@ export interface Committee {
business_email_required?: boolean;
/** Whether audit logging is enabled (from settings) */
is_audit_enabled?: boolean;
/** Member profile visibility setting */
member_visibility?: CommitteeMemberVisibility;
/** Whether to show meeting attendees by default */
show_meeting_attendees?: boolean;
}

/**
Expand Down Expand Up @@ -88,6 +94,10 @@ export interface CommitteeCreateData {
project_uid?: string;
/** Whether committee is open for self-joining */
joinable?: boolean;
/** Member profile visibility setting */
member_visibility?: CommitteeMemberVisibility;
/** Whether to show meeting attendees by default */
show_meeting_attendees?: boolean;
}

/**
Expand All @@ -105,4 +115,8 @@ export interface CommitteeSettingsData {
business_email_required?: boolean;
/** Update audit logging setting */
is_audit_enabled?: boolean;
/** Update member profile visibility setting */
member_visibility?: CommitteeMemberVisibility;
/** Update show meeting attendees setting */
show_meeting_attendees?: boolean;
}
4 changes: 4 additions & 0 deletions packages/shared/src/interfaces/member.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export interface CommitteeMember {
last_name: string;
/** Member's job title */
job_title?: string;
/** Member's LinkedIn profile URL */
linkedin_profile?: string;
/** Who appointed this member to their role */
appointed_by?: CommitteeMemberAppointedBy;
/** Member status */
Expand Down Expand Up @@ -78,6 +80,8 @@ export interface CreateCommitteeMemberRequest {
last_name?: string | null;
/** Member's job title */
job_title?: string | null;
/** Member's LinkedIn profile URL */
linkedin_profile?: string | null;
/** Member's role within the committee */
role?: {
/** Role name */
Expand Down
Loading