-
-
Notifications
You must be signed in to change notification settings - Fork 993
feat: community layout & board page #4127
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
Merged
Merged
Changes from 42 commits
Commits
Show all changes
48 commits
Select commit
Hold shift + click to select a range
c00c218
feat: community layout & board page
aminoxix 55425bb
chore: update tools.json (#4117)
asyncapi-bot fc1bdda
docs(community): update latest maintainers list (#4118)
asyncapi-bot 4c8afd1
docs(community): update latest maintainers list (#4120)
asyncapi-bot a5edb9d
chore: update meetings.json and newsrooom_videos.json (#4121)
asyncapi-bot ea7aa48
chore: update meetings.json and newsrooom_videos.json (#4123)
asyncapi-bot 0ab497f
chore: update meetings.json and newsrooom_videos.json (#4124)
asyncapi-bot 31a378d
docs(community): update latest maintainers list (#4119)
asyncapi-bot 3b51264
fix: misaligned-nav-box (#4094)
itzraghavv c4aeee7
fix: redesign 'Latest News' section in Community Newsroom (#3982)
PankajKumardev 4f5fe34
fix: remove console logs exposing user data and critical website flow…
sagarkori143 871910f
fix: missing Hero/Banner on Case Study Pages (#4103)
noogler-eng b2b77c1
fix: updated few outdated information (#3723)
Adi-204 2879613
chore: update meetings.json and newsrooom_videos.json (#4125)
asyncapi-bot 4173294
chore: update tools.json (#4129)
asyncapi-bot b5e4c06
chore(blog): add singapore summary (#4056)
iambami 8b2aa60
ci: update of files from global .github repo (#4130)
asyncapi-bot 3dbc4ab
chore(blog): add marketing q1 report (#3911)
iambami d956b2b
docs(community): update latest tsc members list (#4135)
asyncapi-bot ee748e0
docs(generator): update latest generator documentation (#4136)
asyncapi-bot d0b770e
chore(blog): add google summer of 2025 first phase summary (#4131)
AceTheCreator 2050695
chore: update meetings.json and newsrooom_videos.json (#4137)
asyncapi-bot 857b17f
chore(blog): add may update (#4132)
thulieblack 8417bcc
fix: update eslintrc for all types of files (#4128)
akshatnema 99cc9b0
chore: update meetings.json and newsrooom_videos.json (#4139)
asyncapi-bot d098c74
chore: update meetings.json and newsrooom_videos.json (#4140)
asyncapi-bot b0490f0
chore: update meetings.json and newsrooom_videos.json (#4141)
asyncapi-bot 3756243
chore: update tools.json (#4142)
asyncapi-bot 77e4680
docs(community): update latest Board and TSC members list (#4144)
asyncapi-bot 80ff0c3
docs(community): update latest community documentation (#4146)
asyncapi-bot 4d2851b
docs(generator): update latest generator documentation (#4147)
asyncapi-bot fcce3f6
chore: update meetings.json and newsrooom_videos.json (#4149)
asyncapi-bot 25566f7
Merge remote-tracking branch 'origin' into feat/community-page
aminoxix 77fad43
fix: relevantMembersList type, TSC_BOARD_MEMBERS.yaml removed as JSON…
aminoxix e86178b
Merge pull request #20 from asyncapi/master
aminoxix 4100d17
Merge branch 'master' into feat/community-page
asyncapi-bot e75193b
feat: baord members navigation menu, scrollable flyout menu & fallbac…
aminoxix 8053b66
fix: redirected to dedicated ambassador page based on github username
aminoxix 381f0c7
Merge branch 'master' into feat/community-page
derberg 11bd0b4
Merge pull request #21 from asyncapi/master
aminoxix 46ed7ff
Merge branch 'master' into feat/community-page
aminoxix 2828eea
fix: AsyncAPI ambassador hyperlink styling
aminoxix c4cfbf8
Merge branch 'master' into feat/community-page
asyncapi-bot fa26bfc
feat: badge for chairperson
aminoxix 5f7274f
Merge branch 'master' into feat/community-page
aminoxix e6cbd83
Merge branch 'master' into feat/community-page
aminoxix d572f5a
fix: tsc board members json updated
aminoxix 004f928
Apply suggestions from code review
derberg File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,318 @@ | ||
| import { sortBy } from 'lodash'; | ||
| import React from 'react'; | ||
|
|
||
| import type { Ambassador, Tsc } from '@/types/pages/community/Community'; | ||
|
|
||
| import tscBoardList from '../../config/TSC_BOARD_MEMBERS.json'; | ||
| import IconGithub from '../icons/Github'; | ||
| import IconLinkedIn from '../icons/LinkedIn'; | ||
| import IconTwitter from '../icons/Twitter'; | ||
| import NewsletterSubscribe from '../NewsletterSubscribe'; | ||
| import TextLink from '../typography/TextLink'; | ||
| import GenericLayout from './GenericLayout'; | ||
|
|
||
| interface SocialLinkProps { | ||
| href: string; | ||
| social: string; | ||
| } | ||
|
|
||
| interface TSCUser { | ||
| user: Tsc | Ambassador; | ||
| } | ||
|
|
||
| /** | ||
| * @description This function adds additional information to the user object having Board (TSC or Ambassador) data. | ||
| * | ||
| * @param user The user object having Board (TSC or Ambassador) data. | ||
| * @returns The user object with additional information. | ||
| */ | ||
| function addAdditionalUserInfo(user: Tsc | Ambassador) { | ||
| const userData: Tsc | Ambassador = { | ||
| ...user | ||
| }; | ||
|
|
||
| // if username is not present, use the github username | ||
| if (!userData.name) { | ||
| userData.name = userData.github; | ||
| } | ||
|
|
||
| // add social links | ||
| if (userData.github) { | ||
| userData.github = `https://www.github.com/${userData.github}`; | ||
| } | ||
| if (userData.linkedin) { | ||
| userData.linkedin = `https://www.linkedin.com/in/${userData.linkedin}`; | ||
| } | ||
| if (userData.twitter) { | ||
| userData.twitter = `https://www.twitter.com/${userData.twitter}`; | ||
| } | ||
|
|
||
| // add avatar url | ||
| // github redirects to avatar url using `https://www.github.com/<username>.png` | ||
| userData.avatarUrl = `${userData.github}.png`; | ||
|
|
||
| // make repo links | ||
| if ('repos' in userData) { | ||
| userData.repos = userData.repos.map((repoName: string) => ({ | ||
| name: repoName, | ||
| url: `https://www.github.com/asyncapi/${repoName}` | ||
| })); | ||
| } | ||
|
|
||
| return userData; | ||
| } | ||
|
|
||
| /** | ||
| * @description This function returns the SVG component for Twitter. | ||
| * | ||
| * @returns The Twitter SVG component. | ||
| */ | ||
| function TwitterSVG() { | ||
| return ( | ||
| <div className='size-5'> | ||
| <IconTwitter className='hover:fill-black' /> | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * @description This function returns the SVG component for GitHub. | ||
| * | ||
| * @returns The GitHub SVG component. | ||
| */ | ||
| function GitHubSVG() { | ||
| return ( | ||
| <div className='size-5'> | ||
| <IconGithub className='hover:fill-black' /> | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * @description This function returns the SVG component for LinkedIn. | ||
| * | ||
| * @returns The LinkedIn SVG component. | ||
| */ | ||
| function LinkedInSVG() { | ||
| return ( | ||
| <div className='size-5'> | ||
| <IconLinkedIn className='hover:fill-linkedin' /> | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| const socials: { [key: string]: React.JSX.Element } = { | ||
| GitHub: <GitHubSVG />, | ||
| Twitter: <TwitterSVG />, | ||
| Linkedin: <LinkedInSVG /> | ||
| }; | ||
|
|
||
| /** | ||
| * @description This function returns the social link component. | ||
| * | ||
| * @param {SocialLinkProps} props - The props for the social link component. | ||
| * @param {string} props.href - The URL for the social link. | ||
| * @param {string} props.social - The social media platform. | ||
| */ | ||
| function SocialLink({ href, social }: SocialLinkProps) { | ||
| return ( | ||
| <li> | ||
| <a | ||
| data-testid='Social-Links' | ||
| href={href} | ||
| className='text-gray-600 hover:text-gray-500' | ||
| target='_blank' | ||
| rel='noreferrer noopener' | ||
| > | ||
| <span className='sr-only'>{social}</span> | ||
| {socials[social]} | ||
| </a> | ||
| </li> | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * @description This function returns the user work status component. | ||
| * | ||
| * @param {TSCUser} props - The props for the user work status component. | ||
| * @param {Tsc | Ambassador} props.user - The user object having Board (TSC or Ambassador) data. | ||
| */ | ||
| function UserWorkStatus({ user }: TSCUser) { | ||
| if ('availableForHire' in user && user.availableForHire) { | ||
| return ( | ||
| <div | ||
| data-testid='status-element' | ||
| className='text-md inline-flex items-center rounded-full bg-green-100 px-3 py-1 font-medium leading-5 text-green-800' | ||
| > | ||
| Available for hire | ||
| </div> | ||
| ); | ||
| } | ||
| if (user.company) { | ||
| return ( | ||
| <div | ||
| data-testid='status-element' | ||
| className='text-md inline-flex items-center rounded-full bg-orange-100 px-3 py-1 font-medium leading-5 text-orange-800' | ||
| > | ||
| {user.company} | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| return ( | ||
| <div | ||
| data-testid='status-element' | ||
| className='text-md inline-flex items-center rounded-full bg-blue-100 px-3 py-1 font-medium leading-5 text-blue-800' | ||
| > | ||
| Individual Member | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * @description This function returns the user info component. | ||
| * | ||
| * @param {TSCUser} props - The props for the user info component. | ||
| * @param {Tsc} props.user - The user object having Board (TSC or Ambassador) data. | ||
| */ | ||
| function UserInfo({ user }: TSCUser) { | ||
| const githubUsername = user.github.split('/').pop(); | ||
|
|
||
| return ( | ||
| <li | ||
| data-testid='UserInfo-list' | ||
| className='rounded-md border border-gray-200 p-4 text-center shadow-md' | ||
| key={user.github} | ||
| > | ||
| <div className='flex flex-row'> | ||
| <img | ||
| data-testid='UserInfo-avatar' | ||
| src={user.avatarUrl} | ||
| alt={user.name} | ||
| className='mx-auto size-20 rounded-full xl:size-28' | ||
| /> | ||
| <div className='flex-1'> | ||
| <div className='my-3 text-lg font-bold' data-testid='UserInfo-name'> | ||
| {user.name} | ||
| </div> | ||
| <UserWorkStatus user={user} /> | ||
| <ul role='list' className='my-5 flex justify-center space-x-5'> | ||
| <SocialLink href={user.github} social='GitHub' /> | ||
| {user.twitter ? <SocialLink href={user.twitter} social='Twitter' /> : null} | ||
| {user.linkedin ? <SocialLink href={user.linkedin} social='Linkedin' /> : null} | ||
| </ul> | ||
| </div> | ||
| </div> | ||
| {'repos' in user ? ( | ||
| <div className='flex flex-wrap items-center gap-1'> | ||
| Maintainer of: | ||
| {user.repos.map((repo: { name: string; url: string }) => ( | ||
| <a | ||
| data-testid='Repo-Links' | ||
| key={repo.name} | ||
| className='inline-flex items-center rounded-full bg-cyan-100 px-3 py-0.5 text-xs font-medium leading-5 text-cyan-800 hover:bg-cyan-300' | ||
| href={repo.url} | ||
| > | ||
| {repo.name} | ||
| </a> | ||
| ))} | ||
| </div> | ||
| ) : ( | ||
| // fallback to ambassador page | ||
| <TextLink | ||
| href={`/community/ambassadors/${githubUsername}`} | ||
| className='flex font-normal text-base text-blue-500 no-underline hover:text-sky-400' | ||
| > | ||
| AsyncAPI Ambassador | ||
| </TextLink> | ||
| )} | ||
| </li> | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * @description This function returns the question card component. | ||
| */ | ||
| function QuestionCard() { | ||
| return ( | ||
| <li className='rounded-md border border-gray-200 p-4 px-6 py-10 text-center shadow-md' data-testid='Question-card'> | ||
| <img | ||
| data-testid='Question-card-img' | ||
| src='/img/avatars/questionmark.webp' | ||
| alt='Question Mark' | ||
| className='mx-auto size-20 rounded-full xl:size-28' | ||
| /> | ||
| <div className='my-4'> | ||
| Want to become a member? Follow this | ||
| <TextLink | ||
| href='https://github.com/asyncapi/community/blob/master/TSC_MEMBERSHIP.md' | ||
| target='_blank' | ||
| className='font-normal text-base text-sky-600 no-underline hover:text-sky-400' | ||
| > | ||
| Link | ||
| </TextLink> | ||
| to know more! | ||
| </div> | ||
| </li> | ||
| ); | ||
| } | ||
|
|
||
| export enum Membership { | ||
| TSC = 'TSC', | ||
| BOARD = 'Board' | ||
| } | ||
|
|
||
| interface ICommunityLayout { | ||
| membership: Membership; | ||
| children: React.ReactNode; | ||
| } | ||
|
|
||
| /** | ||
| * @description This function returns the TSC or Board component. | ||
| * @param {Membership} props.membership - determines the community members belong to board or TSC (ambassadors & maintainers). | ||
| */ | ||
| export default function CommunityLayout({ children, membership }: ICommunityLayout) { | ||
| const description = `Meet the current AsyncAPI ${membership} members and learn how you can become one.`; | ||
| const image = `/img/social/community-${membership.toLowerCase()}.webp`; | ||
|
|
||
| const isTSCMembership = membership === Membership.TSC; | ||
| const tscBoardMembers = sortBy( | ||
| tscBoardList.map((user) => addAdditionalUserInfo(user)), | ||
| ['name'] | ||
| ).filter((user) => (isTSCMembership ? user.isTscMember : user.isBoardMember || user.isBoardChair)); | ||
aminoxix marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| return ( | ||
| <GenericLayout | ||
| title={isTSCMembership ? 'Technical Steering Committee' : 'Board Committee'} | ||
| description={description} | ||
| image={image} | ||
| wide | ||
| > | ||
| <div className='relative mx-auto px-4 py-12 sm:px-6 lg:px-8'> | ||
| {children} | ||
| {isTSCMembership && ( | ||
| <div className='mt-8'> | ||
| <NewsletterSubscribe | ||
| type='TSC Voting' | ||
| title='Get notified when TSC is voting' | ||
| subtitle="You'll receive an email whenever someone requests the TSC to vote." | ||
| /> | ||
| </div> | ||
| )} | ||
| <div className='mt-10'> | ||
| <div className='text-primary-800 mb-5 text-center'> | ||
| <h3 className='text-2xl font-semibold'>Current {membership} members</h3> | ||
| <span className='font-thin text-sm'>(in alphabetical order)</span> | ||
| </div> | ||
|
|
||
| <ul role='list' className='space-y-4 sm:grid sm:grid-cols-2 sm:gap-6 sm:space-y-0 lg:grid-cols-3 lg:gap-8'> | ||
| {tscBoardMembers.map((user) => ( | ||
| <UserInfo key={user.github} user={user} /> | ||
| ))} | ||
| <QuestionCard /> | ||
| </ul> | ||
| </div> | ||
| </div> | ||
| </GenericLayout> | ||
| ); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.