-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathcommittees.constants.ts
More file actions
609 lines (556 loc) · 23.8 KB
/
Copy pathcommittees.constants.ts
File metadata and controls
609 lines (556 loc) · 23.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
// Copyright The Linux Foundation and each contributor to LFX.
// SPDX-License-Identifier: MIT
import { CommitteeMemberAppointedBy, CommitteeMemberRole, CommitteeMemberVotingStatus } from '../enums/committee-member.enum';
import { BehavioralClassDisplayConfig, CommitteeTab, GroupBehavioralClass, JoinMode } from '../interfaces/committee.interface';
import { lfxColors } from './colors.constants';
// Re-export helper functions from utils for backward compatibility
export {
getGroupBehavioralClass,
isGoverningBoard,
isOversightCommittee,
isWorkingGroup,
isSpecialInterestGroup,
isAmbassadorProgram,
isOtherClass,
isGovernanceClass,
isCollaborationClass,
} from '../utils/committee.utils';
/**
* Valid tab keys for committee view navigation
*/
export const COMMITTEE_VALID_TABS: CommitteeTab[] = ['overview', 'members', 'votes', 'meetings', 'surveys', 'documents', 'settings'];
/**
* Configurable labels for committees displayed throughout the UI
* @description This constant allows the user-facing labels to be changed (e.g., to "Group/Groups")
* while keeping all code and file names as "committees"
* @readonly
* @example
* // Use in templates to display the label
* <h1>{{COMMITTEE_LABEL.plural}}</h1> // Displays "Groups"
* <span>{{COMMITTEE_LABEL.singular}} Name</span> // Displays "Group Name"
*/
export const COMMITTEE_LABEL = {
singular: 'Group',
plural: 'Groups',
} as const;
/**
* Committee category info for card-based selection
* @description Defines icons, descriptions, and colors for each committee category
*/
export interface CommitteeCategoryInfo {
icon: string;
description: string;
examples: string;
color: string;
}
/**
* Committee category configurations with visual styling
* @description Maps category values to their display info (follows meeting type pattern)
*/
export const COMMITTEE_CATEGORY_CONFIGS: Record<string, CommitteeCategoryInfo> = {
Ambassador: {
icon: 'fa-light fa-bullhorn',
description: 'Community advocates who promote and represent the project',
examples: 'Developer advocates, community evangelists, regional representatives',
color: lfxColors.violet[500],
},
Board: {
icon: 'fa-light fa-user-crown',
description: 'Governance body for strategic decisions and project direction',
examples: 'Board of directors, governing board, advisory board',
color: lfxColors.red[500],
},
'Code of Conduct': {
icon: 'fa-light fa-shield-check',
description: 'Ensures community standards and handles conduct issues',
examples: 'CoC committee, conduct review board, community standards team',
color: lfxColors.red[500],
},
Committers: {
icon: 'fa-light fa-code-commit',
description: 'Contributors with commit access to project repositories',
examples: 'Core committers, project committers, module maintainers',
color: lfxColors.blue[500],
},
'Expert Group': {
icon: 'fa-light fa-lightbulb',
description: 'Specialized group focused on specific technical domains',
examples: 'Security experts, performance specialists, API designers',
color: lfxColors.amber[500],
},
'Finance Committee': {
icon: 'fa-light fa-coins',
description: 'Oversees budget, funding, and financial decisions',
examples: 'Budget committee, finance review board, funding allocation',
color: lfxColors.emerald[500],
},
'Government Advisory Council': {
icon: 'fa-light fa-landmark',
description: 'Advises on government relations and public sector engagement',
examples: 'Public sector advisory, government liaison, policy advisors',
color: lfxColors.violet[500],
},
'Legal Committee': {
icon: 'fa-light fa-scale-balanced',
description: 'Handles licensing, compliance, and legal matters',
examples: 'License review, IP committee, legal advisory',
color: lfxColors.amber[500],
},
Maintainers: {
icon: 'fa-light fa-gear',
description: 'Core team responsible for project maintenance and releases',
examples: 'Project maintainers, release managers, core team',
color: lfxColors.blue[500],
},
'Marketing Committee/Sub Committee': {
icon: 'fa-light fa-chart-line-up',
description: 'Drives marketing initiatives and community growth',
examples: 'Marketing team, growth committee, outreach group',
color: lfxColors.emerald[500],
},
'Marketing Mailing List': {
icon: 'fa-light fa-envelope',
description: 'Communication channel for marketing discussions',
examples: 'Marketing announcements, campaign coordination',
color: lfxColors.emerald[500],
},
'Marketing Oversight Committee/Marketing Advisory Committee': {
icon: 'fa-light fa-chart-pie',
description: 'Strategic oversight for marketing activities',
examples: 'Marketing strategy, brand guidelines, campaign approval',
color: lfxColors.emerald[500],
},
'Product Security': {
icon: 'fa-light fa-shield-halved',
description: 'Handles security vulnerabilities and advisories',
examples: 'Security response team, vulnerability disclosure, CVE handling',
color: lfxColors.red[500],
},
'Special Interest Group': {
icon: 'fa-light fa-users-viewfinder',
description: 'Focused group for specific topics or use cases',
examples: 'Cloud SIG, Edge SIG, Documentation SIG',
color: lfxColors.blue[500],
},
'Technical Advisory Committee': {
icon: 'fa-light fa-diagram-project',
description: 'Advises on technical direction and architecture',
examples: 'TAC committee, architecture review, technical guidance',
color: lfxColors.violet[500],
},
'Technical Mailing List': {
icon: 'fa-light fa-at',
description: 'Communication channel for technical discussions',
examples: 'Dev discussions, RFC reviews, technical Q&A',
color: lfxColors.violet[500],
},
'Technical Oversight Committee': {
icon: 'fa-light fa-sitemap',
description: 'Oversees technical governance and standards',
examples: 'TOC committee, project incubation, technical standards',
color: lfxColors.violet[500],
},
'Technical Steering Committee': {
icon: 'fa-light fa-compass',
description: 'Steers technical roadmap and priorities',
examples: 'TSC committee, roadmap planning, release decisions',
color: lfxColors.violet[500],
},
'Working Group': {
icon: 'fa-light fa-users-gear',
description: 'Collaborative group working on specific initiatives',
examples: 'Documentation WG, Testing WG, CI/CD WG',
color: lfxColors.amber[500],
},
Other: {
icon: 'fa-light fa-folder-open',
description: 'Other committee types not covered by standard categories',
examples: 'Custom committees, ad-hoc groups, temporary teams',
color: lfxColors.gray[500],
},
};
/**
* Available committee category types for classification
* @description Standard categories used across the LFX platform for organizing committees
* @readonly
*/
export const COMMITTEE_CATEGORIES = [
{ label: 'Ambassador', value: 'Ambassador' },
{ label: 'Board', value: 'Board' },
{ label: 'Code of Conduct', value: 'Code of Conduct' },
{ label: 'Committers', value: 'Committers' },
{ label: 'Expert Group', value: 'Expert Group' },
{ label: 'Finance Committee', value: 'Finance Committee' },
{ label: 'Government Advisory Council', value: 'Government Advisory Council' },
{ label: 'Legal Committee', value: 'Legal Committee' },
{ label: 'Maintainers', value: 'Maintainers' },
{ label: 'Marketing Committee/Sub Committee', value: 'Marketing Committee/Sub Committee' },
{ label: 'Marketing Mailing List', value: 'Marketing Mailing List' },
{ label: 'Marketing Oversight Committee/Marketing Advisory Committee', value: 'Marketing Oversight Committee/Marketing Advisory Committee' },
{ label: 'Product Security', value: 'Product Security' },
{ label: 'Special Interest Group', value: 'Special Interest Group' },
{ label: 'Technical Advisory Committee', value: 'Technical Advisory Committee' },
{ label: 'Technical Mailing List', value: 'Technical Mailing List' },
{ label: 'Technical Oversight Committee', value: 'Technical Oversight Committee' },
{ label: 'Technical Steering Committee', value: 'Technical Steering Committee' },
{ label: 'Working Group', value: 'Working Group' },
{ label: 'Other', value: 'Other' },
];
/**
* Filtered committee categories for specific UI contexts
* @description Subset of categories for restricted selection (e.g., forms, dashboards)
*/
export const FILTERED_COMMITTEE_CATEGORIES = [
{ label: 'Special Interest Group', value: 'Special Interest Group' },
{ label: 'Technical Advisory Committee', value: 'Technical Advisory Committee' },
{ label: 'Technical Oversight Committee', value: 'Technical Oversight Committee' },
{ label: 'Technical Steering Committee', value: 'Technical Steering Committee' },
{ label: 'Working Group', value: 'Working Group' },
{ label: 'Other', value: 'Other' },
];
/**
* Available member roles within committees
* @description Standard roles that members can have within committees and working groups
* @readonly
* @example
* // Use for role assignment
* const chairRole = MEMBER_ROLES.find(role => role.value === CommitteeMemberRole.CHAIR);
*/
export const MEMBER_ROLES = [
{ label: 'Chair', value: CommitteeMemberRole.CHAIR },
{ label: 'Developer Seat', value: CommitteeMemberRole.DEVELOPER_SEAT },
{ label: 'Director', value: CommitteeMemberRole.DIRECTOR },
{ label: 'Lead', value: CommitteeMemberRole.LEAD },
{ label: 'LF Staff', value: CommitteeMemberRole.LF_STAFF },
{ label: 'Secretary', value: CommitteeMemberRole.SECRETARY },
{ label: 'TAC/TOC Representative', value: CommitteeMemberRole.TAC_TOC_REPRESENTATIVE },
{ label: 'Treasurer', value: CommitteeMemberRole.TREASURER },
{ label: 'Vice Chair', value: CommitteeMemberRole.VICE_CHAIR },
{ label: 'None', value: CommitteeMemberRole.NONE },
];
/**
* Available voting status types for committee members
* @description Defines the voting rights and status of committee members
* @readonly
* @example
* // Check if member has voting rights
* const canVote = [CommitteeMemberVotingStatus.VOTING_REP, CommitteeMemberVotingStatus.ALTERNATE_VOTING_REP].includes(member.voting?.status);
*/
export const VOTING_STATUSES = [
{ label: 'Alternate Voting Rep', value: CommitteeMemberVotingStatus.ALTERNATE_VOTING_REP },
{ label: 'Emeritus', value: CommitteeMemberVotingStatus.EMERITUS },
{ label: 'Observer', value: CommitteeMemberVotingStatus.OBSERVER },
{ label: 'Voting Rep', value: CommitteeMemberVotingStatus.VOTING_REP },
{ label: 'None', value: CommitteeMemberVotingStatus.NONE },
];
/**
* Voting status options for meeting committee filters.
* Excludes None — it is not a selectable value in meeting forms but remains
* a valid member status. None is treated as Observer for filtering purposes.
*/
export const MEETING_VOTING_STATUSES = VOTING_STATUSES.filter(({ value }) => value !== CommitteeMemberVotingStatus.NONE);
/**
* Available appointment sources for committee members
* @description Defines how a member was appointed to the committee
* @readonly
*/
export const APPOINTED_BY_OPTIONS = [
{ label: 'Community', value: CommitteeMemberAppointedBy.COMMUNITY },
{ label: 'Membership Entitlement', value: CommitteeMemberAppointedBy.MEMBERSHIP_ENTITLEMENT },
{ label: 'Vote of Academic Member Class', value: CommitteeMemberAppointedBy.VOTE_OF_ACADEMIC_MEMBER_CLASS },
{ label: 'Vote of End User Committee', value: CommitteeMemberAppointedBy.VOTE_OF_END_USER_COMMITTEE },
{ label: 'Vote of End User Member Class', value: CommitteeMemberAppointedBy.VOTE_OF_END_USER_MEMBER_CLASS },
{ label: 'Vote of General Member Class', value: CommitteeMemberAppointedBy.VOTE_OF_GENERAL_MEMBER_CLASS },
{ label: 'Vote of Gold Member Class', value: CommitteeMemberAppointedBy.VOTE_OF_GOLD_MEMBER_CLASS },
{ label: 'Vote of Governing Board', value: CommitteeMemberAppointedBy.VOTE_OF_GOVERNING_BOARD },
{ label: 'Vote of Lab Member Class', value: CommitteeMemberAppointedBy.VOTE_OF_LAB_MEMBER_CLASS },
{ label: 'Vote of Marketing Committee', value: CommitteeMemberAppointedBy.VOTE_OF_MARKETING_COMMITTEE },
{ label: 'Vote of Silver Member Class', value: CommitteeMemberAppointedBy.VOTE_OF_SILVER_MEMBER_CLASS },
{ label: 'Vote of Strategic Membership Class', value: CommitteeMemberAppointedBy.VOTE_OF_STRATEGIC_MEMBERSHIP_CLASS },
{ label: 'Vote of TAC Committee', value: CommitteeMemberAppointedBy.VOTE_OF_TAC_COMMITTEE },
{ label: 'Vote of TOC Committee', value: CommitteeMemberAppointedBy.VOTE_OF_TOC_COMMITTEE },
{ label: 'Vote of TSC Committee', value: CommitteeMemberAppointedBy.VOTE_OF_TSC_COMMITTEE },
{ label: 'None', value: CommitteeMemberAppointedBy.NONE },
];
/**
* Internal committee type color mappings for exact match fallback
* @private - Use getCommitteeTypeColor() function instead
* @description Uses LFX semantic color tokens from the design system
*/
const COMMITTEE_TYPE_COLORS = {
// Board and governance
Board: 'bg-violet-100 text-violet-800',
'Government Advisory Council': 'bg-violet-100 text-violet-800',
// Legal and compliance
'Legal Committee': 'bg-red-100 text-red-800',
'Code of Conduct': 'bg-red-100 text-red-800',
'Product Security': 'bg-red-100 text-red-800',
// Special interest groups
'Special Interest Group': 'bg-blue-100 text-blue-800',
'Expert Group': 'bg-blue-100 text-blue-800',
// Working groups
'Working Group': 'bg-amber-100 text-amber-800',
// Technical committees
'Technical Steering Committee': 'bg-emerald-100 text-emerald-800',
'Technical Advisory Committee': 'bg-blue-100 text-blue-700',
'Technical Oversight Committee': 'bg-blue-100 text-blue-700',
'Technical Mailing List': 'bg-blue-100 text-blue-700',
// Technical roles
Maintainers: 'bg-blue-100 text-blue-800',
Committers: 'bg-blue-100 text-blue-800',
// Marketing and outreach
'Marketing Oversight Committee/Marketing Advisory Committee': 'bg-violet-100 text-violet-700',
'Marketing Committee/Sub Committee': 'bg-violet-100 text-violet-700',
'Marketing Mailing List': 'bg-violet-100 text-violet-700',
Ambassador: 'bg-violet-100 text-violet-700',
// Finance
'Finance Committee': 'bg-emerald-100 text-emerald-800',
// Other/miscellaneous
Other: 'bg-gray-100 text-gray-800',
} as const;
/**
* Internal default color scheme for unknown committee types
* @private
*/
const DEFAULT_COMMITTEE_TYPE_COLOR = 'bg-gray-100 text-gray-800';
/**
* Get color classes for a committee category badge
* Returns background and text color classes based on category name
* Uses partial string matching to categorize committee types
*/
export function getCommitteeTypeColor(category: string | undefined): string {
if (!category) return DEFAULT_COMMITTEE_TYPE_COLOR;
const lowerCategory = category.toLowerCase();
// Board and governance
if (lowerCategory.includes('board')) return 'bg-violet-100 text-violet-800';
if (lowerCategory.includes('government')) return 'bg-violet-100 text-violet-800';
// Legal and compliance
if (lowerCategory.includes('legal')) return 'bg-red-100 text-red-800';
if (lowerCategory.includes('code of conduct')) return 'bg-red-100 text-red-800';
if (lowerCategory.includes('product security')) return 'bg-red-100 text-red-800';
// Special interest groups
if (lowerCategory.includes('special interest')) return 'bg-blue-100 text-blue-800';
if (lowerCategory.includes('expert')) return 'bg-blue-100 text-blue-800';
// Working groups
if (lowerCategory.includes('working group')) return 'bg-amber-100 text-amber-800';
// Technical committees
if (lowerCategory.includes('technical steering')) return 'bg-emerald-100 text-emerald-800';
if (lowerCategory.includes('technical advisory')) return 'bg-blue-100 text-blue-700';
if (lowerCategory.includes('technical oversight')) return 'bg-blue-100 text-blue-700';
if (lowerCategory.includes('technical mailing')) return 'bg-blue-100 text-blue-700';
// Technical roles
if (lowerCategory.includes('maintainer')) return 'bg-blue-100 text-blue-800';
if (lowerCategory.includes('committer')) return 'bg-blue-100 text-blue-800';
// Marketing and outreach
if (lowerCategory.includes('marketing oversight')) return 'bg-violet-100 text-violet-700';
if (lowerCategory.includes('marketing committee')) return 'bg-violet-100 text-violet-700';
if (lowerCategory.includes('marketing mailing')) return 'bg-violet-100 text-violet-700';
if (lowerCategory.includes('ambassador')) return 'bg-violet-100 text-violet-700';
// Finance
if (lowerCategory.includes('finance')) return 'bg-emerald-100 text-emerald-800';
// Other/miscellaneous
if (lowerCategory.includes('other')) return 'bg-gray-100 text-gray-800';
// Fallback to exact match or default
return COMMITTEE_TYPE_COLORS[category as keyof typeof COMMITTEE_TYPE_COLORS] || DEFAULT_COMMITTEE_TYPE_COLOR;
}
// ============================================================================
// Committee Form Configuration Constants
// ============================================================================
/**
* Step titles for the committee creation/edit stepper
* @description Array of human-readable titles for each step in the committee form
*/
export const COMMITTEE_STEP_TITLES = [`${COMMITTEE_LABEL.singular} Type`, 'Basic Information', `${COMMITTEE_LABEL.singular} Settings`, 'Add Members'];
/**
* Total number of steps in the committee form
* @description Must match the length of COMMITTEE_STEP_TITLES array
* @example 4 steps: Category → Basic Info → Settings → Add Members
*/
export const COMMITTEE_TOTAL_STEPS = COMMITTEE_STEP_TITLES.length;
/**
* Committee form step indices
* @description One-based step numbers for form navigation and validation
* @readonly
*/
export const COMMITTEE_FORM_STEPS = {
/** Step 1: Select committee category/type */
CATEGORY: 1,
/** Step 2: Basic information (name, parent, description, website) */
BASIC_INFO: 2,
/** Step 3: Configure settings (toggles for various features) */
SETTINGS: 3,
/** Step 4: Add members to the committee */
ADD_MEMBERS: 4,
};
/**
* Committee settings features for Step 2 form
* @description Feature toggles for committee settings (follows MEETING_FEATURES pattern)
*/
export const COMMITTEE_SETTINGS_FEATURES = [
{
key: 'business_email_required',
icon: 'fa-light fa-shield',
title: 'Business Email Required',
description: 'Require members to have a business email address',
color: lfxColors.blue[500],
},
{
key: 'enable_voting',
icon: 'fa-light fa-check-to-slot',
title: 'Enable Voting',
description: `Allow members to vote on ${COMMITTEE_LABEL.singular.toLowerCase()} matters`,
recommended: true,
color: lfxColors.violet[500],
},
{
key: 'is_audit_enabled',
icon: 'fa-light fa-file-check',
title: 'Enable Audit',
description: `Track and log all ${COMMITTEE_LABEL.singular.toLowerCase()} activity for compliance`,
color: lfxColors.emerald[500],
},
{
key: 'public',
icon: 'fa-light fa-eye',
title: `Make ${COMMITTEE_LABEL.singular} Public`,
description: `Make ${COMMITTEE_LABEL.singular.toLowerCase()} visible to all users`,
recommended: true,
color: lfxColors.violet[500],
},
{
key: 'sso_group_enabled',
icon: 'fa-light fa-key',
title: 'Enable SSO Group',
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],
},
];
/**
* Permission level options for committee member ACL dropdowns.
* Shared across add-member-dialog and member-form components.
*/
export const COMMITTEE_PERMISSION_OPTIONS = [
{ label: 'Member', value: 'member' },
{ label: 'Reviewer', value: 'review' },
{ label: 'Manage', value: 'manage' },
] as const;
/** Add-member dialog: invite-by-email vs direct roster add (writers only). */
export const ADD_MEMBER_ACTION_OPTIONS = [
{ label: 'Add directly', value: 'add_directly' },
{ label: 'Send invite', value: 'invite' },
] as const;
/**
* 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' },
];
/**
* Human-readable labels for JoinMode enum values.
* Used by JoinModeLabelPipe for template display.
*/
export const JOIN_MODE_LABELS: Record<JoinMode, string> = {
open: 'Open',
invite_only: 'Invite Only',
application: 'Apply to Join',
closed: 'Closed',
};
/**
* Join-mode options for the Group settings form (Step 3).
* Maps to the JoinMode type in committee.interface.ts.
*/
export const JOIN_MODE_OPTIONS = [
{ label: 'Open — anyone can join', value: 'open' },
{ label: 'Invite Only — members send invites', value: 'invite_only' },
{ label: 'Apply & Review — admin approves', value: 'application' },
{ label: 'Closed — admin adds members', value: 'closed' },
];
// ============================================================================
// Group-Type Behavioral Classification (6-Type Taxonomy v1.1)
// ============================================================================
/**
* Maps PCC committee categories (20 raw types) to the 6 behavioral classes.
* This is the single source of truth for classification.
*
* v2.0 taxonomy: membership-class removed → ambassador-program added.
* Marketing types moved to special-interest-group (community/outreach).
*/
export const CATEGORY_BEHAVIORAL_CLASS: Record<string, GroupBehavioralClass> = {
// ── governing-board ──
Board: 'governing-board',
'Government Advisory Council': 'governing-board',
// ── oversight-committee (governance + technical hybrid) ──
TSC: 'oversight-committee',
'Technical Steering Committee': 'oversight-committee',
'Technical Advisory Committee': 'oversight-committee',
'Technical Oversight Committee': 'oversight-committee',
'Legal Committee': 'oversight-committee',
'Finance Committee': 'oversight-committee',
'Code of Conduct': 'oversight-committee',
'Product Security': 'oversight-committee',
// ── working-group (task-oriented collaboration) ──
'Working Group': 'working-group',
'Expert Group': 'working-group',
Committers: 'working-group',
Maintainers: 'working-group',
// ── special-interest-group (community / discussion / marketing outreach) ──
'Special Interest Group': 'special-interest-group',
'Technical Mailing List': 'special-interest-group',
'Marketing Committee/Sub Committee': 'special-interest-group',
'Marketing Mailing List': 'special-interest-group',
'Marketing Oversight Committee/Marketing Advisory Committee': 'special-interest-group',
// ── ambassador-program (evangelism / referral / outreach campaigns) ──
Ambassador: 'ambassador-program',
// ── other (catch-all) ──
Other: 'other',
Committee: 'other',
};
export const BEHAVIORAL_CLASS_CONFIG: Record<GroupBehavioralClass, BehavioralClassDisplayConfig> = {
'governing-board': {
label: 'Boards',
icon: 'fa-light fa-gavel',
color: 'text-violet-700',
bgColor: 'bg-violet-50',
},
'oversight-committee': {
label: 'Oversight',
icon: 'fa-light fa-shield-check',
color: 'text-emerald-700',
bgColor: 'bg-emerald-50',
},
'working-group': {
label: 'Working Groups',
icon: 'fa-light fa-users-gear',
color: 'text-amber-700',
bgColor: 'bg-amber-50',
},
'special-interest-group': {
label: 'SIGs',
icon: 'fa-light fa-comments',
color: 'text-blue-700',
bgColor: 'bg-blue-50',
},
'ambassador-program': {
label: 'Ambassadors',
icon: 'fa-light fa-megaphone',
color: 'text-rose-700',
bgColor: 'bg-rose-50',
},
other: {
label: 'Other',
icon: 'fa-light fa-layer-group',
color: 'text-gray-700',
bgColor: 'bg-gray-50',
},
};
/** Max concurrent create-invite requests when fanning out a bulk committee invite. */
export const COMMITTEE_INVITE_CONCURRENCY = 5;