-
-
Notifications
You must be signed in to change notification settings - Fork 252
Fix homepage container flexibility #2100
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 10 commits
5e24a6d
caea551
7e7c88e
026ee9a
305d246
8a73963
8917f7c
3789e3d
5e0536e
f565947
37fa65b
4b93f3e
adb2e32
64ffd22
058cdd7
41d79c1
fdd40ea
3419a80
2e76459
891dd58
2cd43f6
d87feba
03f7dcc
b952945
ec0d606
23facd8
558aa6f
48f79f1
5892607
7352a18
df7aff0
c425484
6ee3cd5
dc5ed1d
690fe21
f4d49ea
10082d5
f17b2e7
e483c63
e625c12
8b5e522
1117ef3
2f37ee0
0bdde86
ba63156
c5e0993
b083a8a
4bbc988
b0627fe
a735bd5
2f6d0e7
3fcd9f9
dc248c0
9641262
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 | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -11,11 +11,12 @@ | |||||||||||||||||||||||||||||||||||||||
| "lint": "eslint . --config eslint.config.mjs --fix --max-warnings=0", | ||||||||||||||||||||||||||||||||||||||||
| "lint:check": "eslint . --config eslint.config.mjs --max-warnings=0", | ||||||||||||||||||||||||||||||||||||||||
| "start": "next start", | ||||||||||||||||||||||||||||||||||||||||
| "test:e2e": "npx playwright test", | ||||||||||||||||||||||||||||||||||||||||
| "test:unit": "tsc --noEmit && NODE_OPTIONS='--experimental-vm-modules --no-warnings=DEP0040' jest" | ||||||||||||||||||||||||||||||||||||||||
| "test": "pnpm test:unit", | ||||||||||||||||||||||||||||||||||||||||
| "test:unit": "tsc --noEmit && cross-env NODE_OPTIONS=--experimental-vm-modules --no-warnings=DEP0040 jest", | ||||||||||||||||||||||||||||||||||||||||
| "test:e2e": "playwright test", | ||||||||||||||||||||||||||||||||||||||||
| "test:all": "pnpm test:unit && pnpm test:e2e" | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+17
to
+20
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. cross-env is used in scripts but not declared — tests will fail.
Add "devDependencies": {
+ "cross-env": "^7.0.3",📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||
| "dependencies": { | ||||||||||||||||||||||||||||||||||||||||
| "@apollo/client": "^3.13.9", | ||||||||||||||||||||||||||||||||||||||||
| "@fortawesome/fontawesome-svg-core": "^6.7.2", | ||||||||||||||||||||||||||||||||||||||||
| "@fortawesome/free-brands-svg-icons": "^6.7.2", | ||||||||||||||||||||||||||||||||||||||||
| "@fortawesome/free-regular-svg-icons": "^6.7.2", | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -45,7 +46,6 @@ | |||||||||||||||||||||||||||||||||||||||
| "dompurify": "^3.2.6", | ||||||||||||||||||||||||||||||||||||||||
| "eslint-plugin-import": "^2.32.0", | ||||||||||||||||||||||||||||||||||||||||
| "framer-motion": "^12.23.12", | ||||||||||||||||||||||||||||||||||||||||
| "graphql": "^16.11.0", | ||||||||||||||||||||||||||||||||||||||||
| "leaflet": "^1.9.4", | ||||||||||||||||||||||||||||||||||||||||
| "leaflet.markercluster": "^1.5.3", | ||||||||||||||||||||||||||||||||||||||||
| "lodash": "^4.17.21", | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -58,9 +58,12 @@ | |||||||||||||||||||||||||||||||||||||||
| "react-apexcharts": "^1.7.0", | ||||||||||||||||||||||||||||||||||||||||
| "react-dom": "^19.1.1", | ||||||||||||||||||||||||||||||||||||||||
| "react-icons": "^5.5.0", | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| "react-router-dom": "^7.8.1", | ||||||||||||||||||||||||||||||||||||||||
| "tailwind-merge": "^3.3.1", | ||||||||||||||||||||||||||||||||||||||||
| "tailwindcss-animate": "^1.0.7" | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||
| "devDependencies": { | ||||||||||||||||||||||||||||||||||||||||
| "@axe-core/react": "^4.10.2", | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -70,7 +73,11 @@ | |||||||||||||||||||||||||||||||||||||||
| "@swc/core": "^1.13.3", | ||||||||||||||||||||||||||||||||||||||||
| "@swc/jest": "^0.2.39", | ||||||||||||||||||||||||||||||||||||||||
| "@tailwindcss/postcss": "^4.1.12", | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
79
to
80
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. 💡 Verification agent 🧩 Analysis chainPick a single Jest transformer. Both @swc/jest and ts-jest are present; using both can conflict. Prefer @swc/jest for speed, or keep ts-jest — but not both in config. Run to see what your config uses: If only one is referenced, remove the unused package. Also applies to: 117-117 🏁 Script executed: #!/bin/bash
rg -nP -C2 '(jest\.config|setupFiles|setupFilesAfterEnv|jest":\s*{)'
rg -nP -C3 '"transform"\s*:\s*{[^}]*}'
rg -nP -C2 '(ts-jest|@swc/jest)'Length of output: 5414 Remove unused ts-jest dependency transform in frontend/jest.config.ts only references @swc/jest, so ts-jest in package.json (line 117) isn’t used and should be removed. 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| "@testing-library/jest-dom": "^6.7.0", | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| "@testing-library/react": "^16.3.0", | ||||||||||||||||||||||||||||||||||||||||
| "@types/jest": "^29.5.14", | ||||||||||||||||||||||||||||||||||||||||
| "@types/leaflet": "^1.9.20", | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -83,6 +90,7 @@ | |||||||||||||||||||||||||||||||||||||||
| "@typescript-eslint/eslint-plugin": "^8.40.0", | ||||||||||||||||||||||||||||||||||||||||
| "@typescript-eslint/parser": "^8.40.0", | ||||||||||||||||||||||||||||||||||||||||
| "autoprefixer": "^10.4.21", | ||||||||||||||||||||||||||||||||||||||||
| "cross-env": "^10.0.0", | ||||||||||||||||||||||||||||||||||||||||
| "eslint": "^9.33.0", | ||||||||||||||||||||||||||||||||||||||||
| "eslint-config-next": "^15.4.7", | ||||||||||||||||||||||||||||||||||||||||
| "eslint-config-prettier": "^10.1.8", | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -103,7 +111,8 @@ | |||||||||||||||||||||||||||||||||||||||
| "prettier": "^3.6.2", | ||||||||||||||||||||||||||||||||||||||||
| "prettier-plugin-tailwindcss": "^0.6.14", | ||||||||||||||||||||||||||||||||||||||||
| "require-in-the-middle": "^7.5.2", | ||||||||||||||||||||||||||||||||||||||||
| "tailwindcss": "^3.4.17", | ||||||||||||||||||||||||||||||||||||||||
| "tailwindcss": "^4.1.12", | ||||||||||||||||||||||||||||||||||||||||
| "tailwindcss-animate": "^1.0.7", | ||||||||||||||||||||||||||||||||||||||||
| "ts-jest": "^29.4.1", | ||||||||||||||||||||||||||||||||||||||||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||
| "ts-node": "^10.9.2", | ||||||||||||||||||||||||||||||||||||||||
| "typescript": "~5.8.3", | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| ignoredBuiltDependencies: | ||
| - '@heroui/shared-utils' | ||
| - '@sentry/cli' | ||
| - core-js | ||
| - unrs-resolver | ||
| onlyBuiltDependencies: | ||
| - '@swc/core' | ||
| - '@tailwindcss/oxide' | ||
| - sharp | ||
OUMIMANDAL marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| module.exports = { | ||
| plugins: { | ||
| "@tailwindcss/postcss": {}, | ||
| autoprefixer: {}, | ||
| tailwindcss: {}, | ||
| }, | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,3 @@ | ||
| import { Metadata } from 'next' | ||
| import React from 'react' | ||
| import { getStaticMetadata } from 'utils/metaconfig' | ||
|
|
||
| export const metadata: Metadata = getStaticMetadata('about', '/about') | ||
|
|
||
| export default function AboutLayout({ children }: { children: React.ReactNode }) { | ||
| return children | ||
| } | ||
| return children; | ||
| } |
|
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. What is going on here?! 👀 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,285 +1,11 @@ | ||
| 'use client' | ||
| import { useQuery } from '@apollo/client' | ||
| import { | ||
| faCircleCheck, | ||
| faClock, | ||
| faUserGear, | ||
| faMapSigns, | ||
| faScroll, | ||
| faUsers, | ||
| faTools, | ||
| faArrowUpRightFromSquare, | ||
| } from '@fortawesome/free-solid-svg-icons' | ||
| import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | ||
| import { Tooltip } from '@heroui/tooltip' | ||
| import upperFirst from 'lodash/upperFirst' | ||
| import Image from 'next/image' | ||
| import Link from 'next/link' | ||
| import { useRouter } from 'next/navigation' | ||
| import { useEffect, useState } from 'react' | ||
| import FontAwesomeIconWrapper from 'wrappers/FontAwesomeIconWrapper' | ||
| import { ErrorDisplay, handleAppError } from 'app/global-error' | ||
| import { GET_PROJECT_METADATA, GET_TOP_CONTRIBUTORS } from 'server/queries/projectQueries' | ||
| import { GET_LEADER_DATA } from 'server/queries/userQueries' | ||
| import type { Contributor } from 'types/contributor' | ||
| import type { Project } from 'types/project' | ||
| import type { User } from 'types/user' | ||
| import { aboutText, technologies } from 'utils/aboutData' | ||
| import AnchorTitle from 'components/AnchorTitle' | ||
| import AnimatedCounter from 'components/AnimatedCounter' | ||
| import LoadingSpinner from 'components/LoadingSpinner' | ||
| import Markdown from 'components/MarkdownWrapper' | ||
| import SecondaryCard from 'components/SecondaryCard' | ||
| import TopContributorsList from 'components/TopContributorsList' | ||
| import UserCard from 'components/UserCard' | ||
|
|
||
| const leaders = { | ||
| arkid15r: 'CCSP, CISSP, CSSLP', | ||
| kasya: 'CC', | ||
| mamicidal: 'CISSP', | ||
| } | ||
| const projectKey = 'nest' | ||
|
|
||
| const About = () => { | ||
| const { data: projectMetadataResponse, error: projectMetadataRequestError } = useQuery( | ||
| GET_PROJECT_METADATA, | ||
| { | ||
| variables: { key: projectKey }, | ||
| } | ||
| ) | ||
|
|
||
| const { data: topContributorsResponse, error: topContributorsRequestError } = useQuery( | ||
| GET_TOP_CONTRIBUTORS, | ||
| { | ||
| variables: { | ||
| excludedUsernames: Object.keys(leaders), | ||
| hasFullName: true, | ||
| key: projectKey, | ||
| limit: 24, | ||
| }, | ||
| } | ||
| ) | ||
|
|
||
| const [projectMetadata, setProjectMetadata] = useState<Project | null>(null) | ||
| const [topContributors, setTopContributors] = useState<Contributor[]>([]) | ||
|
|
||
| useEffect(() => { | ||
| if (projectMetadataResponse?.project) { | ||
| setProjectMetadata(projectMetadataResponse.project) | ||
| } | ||
|
|
||
| if (projectMetadataRequestError) { | ||
| handleAppError(projectMetadataRequestError) | ||
| } | ||
| }, [projectMetadataResponse, projectMetadataRequestError]) | ||
|
|
||
| useEffect(() => { | ||
| if (topContributorsResponse?.topContributors) { | ||
| setTopContributors(topContributorsResponse.topContributors) | ||
| } | ||
|
|
||
| if (topContributorsRequestError) { | ||
| handleAppError(topContributorsRequestError) | ||
| } | ||
| }, [topContributorsResponse, topContributorsRequestError]) | ||
|
|
||
| const isLoading = | ||
| !projectMetadataResponse || | ||
| !topContributorsResponse || | ||
| (projectMetadataRequestError && !projectMetadata) || | ||
| (topContributorsRequestError && !topContributors) | ||
|
|
||
| if (isLoading) { | ||
| return <LoadingSpinner /> | ||
| } | ||
|
|
||
| if (!projectMetadata || !topContributors) { | ||
| return ( | ||
| <ErrorDisplay | ||
| statusCode={404} | ||
| title="Data not found" | ||
| message="Sorry, the page you're looking for doesn't exist" | ||
| /> | ||
| ) | ||
| } | ||
|
|
||
| export default function AboutPage() { | ||
| return ( | ||
| <div className="min-h-screen p-8 text-gray-600 dark:bg-[#212529] dark:text-gray-300"> | ||
| <div className="mx-auto max-w-6xl"> | ||
| <h1 className="mb-6 mt-4 text-4xl font-bold">About</h1> | ||
| <SecondaryCard icon={faScroll} title={<AnchorTitle title="History" />}> | ||
| {aboutText.map((text) => ( | ||
| <div key={text} className="mb-4"> | ||
| <div key={text}> | ||
| <Markdown content={text} /> | ||
| </div> | ||
| </div> | ||
| ))} | ||
| </SecondaryCard> | ||
|
|
||
| <SecondaryCard icon={faArrowUpRightFromSquare} title={<AnchorTitle title="Leaders" />}> | ||
| <div className="flex w-full flex-col items-center justify-around overflow-hidden md:flex-row"> | ||
| {Object.keys(leaders).map((username) => ( | ||
| <div key={username}> | ||
| <LeaderData username={username} /> | ||
| </div> | ||
| ))} | ||
| </div> | ||
| </SecondaryCard> | ||
|
|
||
| {topContributors && ( | ||
| <TopContributorsList | ||
| contributors={topContributors} | ||
| icon={faUsers} | ||
| maxInitialDisplay={12} | ||
| /> | ||
| )} | ||
|
|
||
| <SecondaryCard icon={faTools} title={<AnchorTitle title="Technologies & Tools" />}> | ||
| <div className="w-full"> | ||
| <div className="grid w-full grid-cols-1 justify-center sm:grid-cols-2 lg:grid-cols-4 lg:pl-8"> | ||
| {technologies.map((tech) => ( | ||
| <div key={tech.section} className="mb-2"> | ||
| <h3 className="mb-3 font-semibold text-blue-400">{tech.section}</h3> | ||
| <ul className="space-y-3"> | ||
| {Object.entries(tech.tools).map(([name, details]) => ( | ||
| <li key={name} className="flex flex-row items-center gap-2"> | ||
| <Image | ||
| alt={`${name} icon`} | ||
| className="inline-block align-middle grayscale" | ||
| height={24} | ||
| src={details.icon} | ||
| width={24} | ||
| /> | ||
| <Link | ||
| href={details.url} | ||
| className="text-gray-600 hover:underline dark:text-gray-300" | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| > | ||
| {upperFirst(name)} | ||
| </Link> | ||
| </li> | ||
| ))} | ||
| </ul> | ||
| </div> | ||
| ))} | ||
| </div> | ||
| </div> | ||
| </SecondaryCard> | ||
|
|
||
| {projectMetadata.recentMilestones.length > 0 && ( | ||
| <SecondaryCard icon={faMapSigns} title={<AnchorTitle title="Roadmap" />}> | ||
| <div className="grid gap-4"> | ||
| {[...projectMetadata.recentMilestones] | ||
| .filter((milestone) => milestone.state !== 'closed') | ||
| .sort((a, b) => (a.title > b.title ? 1 : -1)) | ||
| .map((milestone, index) => ( | ||
| <div | ||
| key={milestone.url || milestone.title || index} | ||
| className="flex items-center gap-4 overflow-hidden rounded-lg bg-gray-200 p-6 dark:bg-gray-700" | ||
| > | ||
| <div className="flex-1"> | ||
| <Link | ||
| href={milestone.url} | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="inline-block" | ||
| > | ||
| <h3 className="mb-2 text-xl font-semibold text-blue-400"> | ||
| {milestone.title} | ||
| <Tooltip | ||
| closeDelay={100} | ||
| content={ | ||
| milestone.progress === 100 | ||
| ? 'Completed' | ||
| : milestone.progress > 0 | ||
| ? 'In Progress' | ||
| : 'Not Started' | ||
| } | ||
| id={`tooltip-state-${index}`} | ||
| delay={100} | ||
| placement="top" | ||
| showArrow | ||
| > | ||
| <span className="ml-4 inline-block text-gray-400"> | ||
| <FontAwesomeIcon | ||
| icon={ | ||
| milestone.progress === 100 | ||
| ? faCircleCheck | ||
| : milestone.progress > 0 | ||
| ? faUserGear | ||
| : faClock | ||
| } | ||
| /> | ||
| </span> | ||
| </Tooltip> | ||
| </h3> | ||
| </Link> | ||
| <p className="text-gray-600 dark:text-gray-300">{milestone.body}</p> | ||
| </div> | ||
| </div> | ||
| ))} | ||
| </div> | ||
| </SecondaryCard> | ||
| )} | ||
|
|
||
| <div className="grid gap-6 md:grid-cols-4"> | ||
| {[ | ||
| { label: 'Forks', value: projectMetadata.forksCount }, | ||
| { label: 'Stars', value: projectMetadata.starsCount }, | ||
| { label: 'Contributors', value: projectMetadata.contributorsCount }, | ||
| { label: 'Open Issues', value: projectMetadata.issuesCount }, | ||
| ].map((stat, index) => ( | ||
| <div key={index}> | ||
| <SecondaryCard className="text-center"> | ||
| <div className="mb-2 text-3xl font-bold text-blue-400"> | ||
| <AnimatedCounter end={Math.floor(stat.value / 10) * 10} duration={2} />+ | ||
| </div> | ||
| <div className="text-gray-600 dark:text-gray-300">{stat.label}</div> | ||
| </SecondaryCard> | ||
| </div> | ||
| ))} | ||
| </div> | ||
| </div> | ||
| <div className="p-8 font-sans"> | ||
| <h1 className="text-3xl font-bold mb-4">About OWASP Nest</h1> | ||
| <p> | ||
| OWASP Nest is a platform to discover, engage, and contribute to OWASP | ||
| projects and initiatives. It serves as a central hub for the community. | ||
| </p> | ||
| </div> | ||
| ) | ||
| } | ||
|
|
||
| const LeaderData = ({ username }: { username: string }) => { | ||
| const { data, loading, error } = useQuery(GET_LEADER_DATA, { | ||
| variables: { key: username }, | ||
| }) | ||
| const router = useRouter() | ||
|
|
||
| if (loading) return <p>Loading {username}...</p> | ||
| if (error) return <p>Error loading {username}'s data</p> | ||
|
|
||
| const user = data?.user | ||
|
|
||
| if (!user) { | ||
| return <p>No data available for {username}</p> | ||
| } | ||
|
|
||
| const handleButtonClick = (user: User) => { | ||
| router.push(`/members/${user.login}`) | ||
| } | ||
|
|
||
| return ( | ||
| <UserCard | ||
| avatar={user.avatarUrl} | ||
| button={{ | ||
| icon: <FontAwesomeIconWrapper icon="fa-solid fa-right-to-bracket" />, | ||
| label: 'View Profile', | ||
| onclick: () => handleButtonClick(user), | ||
| }} | ||
| className="h-64 w-40 bg-inherit" | ||
| company={user.company} | ||
| description={leaders[user.login]} | ||
| location={user.location} | ||
| name={user.name || username} | ||
| /> | ||
| ) | ||
| } | ||
|
|
||
| export default About | ||
| ); | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.