diff --git a/backend/apps/github/api/internal/queries/user.py b/backend/apps/github/api/internal/queries/user.py
index d99df0de43..cf39bd1cc3 100644
--- a/backend/apps/github/api/internal/queries/user.py
+++ b/backend/apps/github/api/internal/queries/user.py
@@ -2,6 +2,7 @@
import strawberry
import strawberry_django
+from django.db.models import Case, IntegerField, Value, When
from apps.github.api.internal.nodes.repository import RepositoryNode
from apps.github.api.internal.nodes.user import UserNode
@@ -52,3 +53,25 @@ def user(
"""
return User.objects.filter(has_public_member_page=True, login=login).first()
+
+ @strawberry_django.field
+ def users(self, logins: list[str]) -> list[UserNode]:
+ """Resolve users by their logins.
+
+ Args:
+ logins (list[str]): List of user logins.
+
+ Returns:
+ list[User]: List of user objects.
+
+ """
+ if not logins:
+ return []
+ qs = User.objects.filter(login__in=logins, has_public_member_page=True)
+ if logins:
+ order = Case(
+ *[When(login=login, then=Value(pos)) for pos, login in enumerate(logins)],
+ output_field=IntegerField(),
+ )
+ qs = qs.order_by(order)
+ return qs
diff --git a/backend/tests/apps/github/api/internal/queries/user_test.py b/backend/tests/apps/github/api/internal/queries/user_test.py
index 4b430d030b..5896862d9e 100644
--- a/backend/tests/apps/github/api/internal/queries/user_test.py
+++ b/backend/tests/apps/github/api/internal/queries/user_test.py
@@ -79,3 +79,55 @@ def test_top_contributed_repositories(self):
mock_queryset.filter.return_value.order_by.assert_called_once_with(
"-contributions_count"
)
+
+ def test_resolve_users_with_logins(self, mock_user):
+ """Test resolving multiple users by their logins."""
+ with patch("apps.github.models.user.User.objects.filter") as mock_filter:
+ mock_queryset = mock_filter.return_value
+ mock_queryset.order_by.return_value = [mock_user]
+
+ result = UserQuery().users(logins=["user1", "user2"])
+
+ assert result == [mock_user]
+ mock_filter.assert_called_once_with(
+ login__in=["user1", "user2"], has_public_member_page=True
+ )
+ mock_queryset.order_by.assert_called_once()
+
+ def test_resolve_users_empty_list(self):
+ """Test resolving users with an empty logins list."""
+ with patch("apps.github.models.user.User.objects.filter") as mock_filter:
+ mock_queryset = mock_filter.return_value
+ mock_queryset.order_by.return_value = []
+
+ result = UserQuery().users(logins=[])
+
+ assert result == []
+
+ def test_resolve_users_filters_by_public_member_page_and_login_in(self):
+ """Test that users query filters by both has_public_member_page and login__in."""
+ with patch("apps.github.models.user.User.objects.filter") as mock_filter:
+ mock_queryset = mock_filter.return_value
+ mock_queryset.order_by.return_value = []
+
+ UserQuery().users(logins=["user1", "user2", "user3"])
+
+ mock_filter.assert_called_once_with(
+ login__in=["user1", "user2", "user3"], has_public_member_page=True
+ )
+
+ def test_resolve_users_preserves_order(self, mock_user):
+ """Test that users are returned in the order of input logins."""
+ mock_user1 = Mock(spec=User, login="user1")
+ mock_user2 = Mock(spec=User, login="user2")
+
+ with patch("apps.github.models.user.User.objects.filter") as mock_filter:
+ mock_queryset = mock_filter.return_value
+ mock_queryset.order_by.return_value = [mock_user1, mock_user2]
+
+ logins = ["user1", "user2"]
+ result = UserQuery().users(logins=logins)
+
+ assert result == [mock_user1, mock_user2]
+ mock_filter.assert_called_once_with(login__in=logins, has_public_member_page=True)
+ mock_queryset.order_by.assert_called_once()
diff --git a/docker-compose/local/compose.yaml b/docker-compose/local/compose.yaml
index d1d8121c18..dcfccedec6 100644
--- a/docker-compose/local/compose.yaml
+++ b/docker-compose/local/compose.yaml
@@ -31,7 +31,7 @@ services:
- 8000:8000
volumes:
- ../../backend:/home/owasp
- - backend-venv:/home/owasp/.venv
+ - backend-venv_3592:/home/owasp/.venv
cache:
command: >
@@ -50,7 +50,7 @@ services:
networks:
- nest-network
volumes:
- - cache-data:/data
+ - cache-data_3592:/data
db:
container_name: nest-db
@@ -67,7 +67,7 @@ services:
networks:
- nest-network
volumes:
- - db-data:/var/lib/postgresql/data
+ - db-data_3592:/var/lib/postgresql/data
docs:
container_name: nest-docs
@@ -84,7 +84,7 @@ services:
- 8001:8001
volumes:
- ../../docs:/home/owasp/docs
- - docs-venv:/home/owasp/.venv
+ - docs-venv_3592:/home/owasp/.venv
frontend:
container_name: nest-frontend
@@ -106,8 +106,8 @@ services:
- 3000:3000
volumes:
- ../../frontend:/home/owasp
- - frontend-next:/home/owasp/.next
- - frontend-node-modules:/home/owasp/node_modules
+ - frontend-next_3592:/home/owasp/.next
+ - frontend-node-modules_3592:/home/owasp/node_modules
worker:
container_name: nest-worker
@@ -136,15 +136,15 @@ services:
- nest-network
volumes:
- ../../backend:/home/owasp
- - backend-venv:/home/owasp/.venv
+ - backend-venv_3592:/home/owasp/.venv
networks:
nest-network:
volumes:
- backend-venv:
- cache-data:
- db-data:
- docs-venv:
- frontend-next:
- frontend-node-modules:
+ backend-venv_3592:
+ cache-data_3592:
+ db-data_3592:
+ docs-venv_3592:
+ frontend-next_3592:
+ frontend-node-modules_3592:
diff --git a/frontend/__tests__/e2e/pages/About.spec.ts b/frontend/__tests__/e2e/pages/About.spec.ts
index 56dd64ddfc..1e1762e5ea 100644
--- a/frontend/__tests__/e2e/pages/About.spec.ts
+++ b/frontend/__tests__/e2e/pages/About.spec.ts
@@ -8,17 +8,17 @@ test.describe('About Page', () => {
const request = route.request()
const postData = request.postDataJSON()
- if (postData.query?.includes('user')) {
- const username = postData.variables.key
- const userData = mockAboutData.users[username]
- await route.fulfill({ status: 200, json: { data: { user: userData } } })
- } else if (postData.query?.includes('topContributors')) {
+ if (postData.operationName === 'GetAboutPageData') {
await route.fulfill({
status: 200,
- json: { data: { topContributors: mockAboutData.topContributors } },
+ json: {
+ data: {
+ project: mockAboutData.project,
+ topContributors: mockAboutData.topContributors,
+ users: mockAboutData.users,
+ },
+ },
})
- } else {
- await route.fulfill({ status: 200, json: { data: { project: mockAboutData.project } } })
}
})
diff --git a/frontend/__tests__/mockData/mockAboutData.ts b/frontend/__tests__/mockData/mockAboutData.ts
index 47c329613d..a50b87aa31 100644
--- a/frontend/__tests__/mockData/mockAboutData.ts
+++ b/frontend/__tests__/mockData/mockAboutData.ts
@@ -42,21 +42,21 @@ export const mockAboutData = {
login: `contributor${i + 1}`,
name: `Contributor ${i + 1}`,
})),
- users: {
- arkid15r: {
+ users: [
+ {
avatarUrl: 'https://avatars.githubusercontent.com/u/2201626?v=4',
login: 'arkid15r',
name: 'Arkadii Yakovets',
},
- kasya: {
+ {
avatarUrl: 'https://avatars.githubusercontent.com/u/5873153?v=4',
login: 'kasya',
name: 'Kate Golovanova',
},
- mamicidal: {
+ {
avatarUrl: 'https://avatars.githubusercontent.com/u/112129498?v=4',
login: 'mamicidal',
name: 'Starr Brown',
},
- },
+ ],
}
diff --git a/frontend/__tests__/unit/pages/About.test.tsx b/frontend/__tests__/unit/pages/About.test.tsx
index 9af466b734..980068feb4 100644
--- a/frontend/__tests__/unit/pages/About.test.tsx
+++ b/frontend/__tests__/unit/pages/About.test.tsx
@@ -6,12 +6,6 @@ import { useRouter } from 'next/navigation'
import React, { act } from 'react'
import { render } from 'wrappers/testUtil'
import About from 'app/about/page'
-import {
- GetProjectMetadataDocument,
- GetTopContributorsDocument,
-} from 'types/__generated__/projectQueries.generated'
-import { GetLeaderDataDocument } from 'types/__generated__/userQueries.generated'
-
jest.mock('@apollo/client/react', () => ({
...jest.requireActual('@apollo/client/react'),
useQuery: jest.fn(),
@@ -201,43 +195,13 @@ jest.mock('components/ShowMoreButton', () => ({
},
}))
-const mockUserData = (username) => ({
- data: { user: mockAboutData.users[username] },
- loading: false,
- error: null,
-})
-
-const mockProjectData = {
- data: { project: mockAboutData.project },
- loading: false,
- error: null,
-}
-
-const mockTopContributorsData = {
- data: { topContributors: mockAboutData.topContributors },
- loading: false,
- error: null,
-}
-
describe('About Component', () => {
let mockRouter: { push: jest.Mock }
beforeEach(() => {
- ;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
- const key = options?.variables?.key
-
- if (query === GetProjectMetadataDocument) {
- if (key === 'nest') {
- return mockProjectData
- }
- } else if (query === GetTopContributorsDocument) {
- if (key === 'nest') {
- return mockTopContributorsData
- }
- } else if (query === GetLeaderDataDocument) {
- return mockUserData(key)
- }
-
- return { loading: true }
+ ;(useQuery as unknown as jest.Mock).mockReturnValue({
+ data: mockAboutData,
+ loading: false,
+ error: null,
})
mockRouter = { push: jest.fn() }
;(useRouter as jest.Mock).mockReturnValue(mockRouter)
@@ -451,13 +415,10 @@ describe('About Component', () => {
})
test('handles null project in data response gracefully', async () => {
- ;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
- if (options?.variables?.key === 'nest') {
- return { data: { project: null }, loading: false, error: null }
- } else if (['arkid15r', 'kasya', 'mamicidal'].includes(options?.variables?.key)) {
- return mockUserData(options?.variables?.key)
- }
- return { loading: true }
+ ;(useQuery as unknown as jest.Mock).mockReturnValue({
+ data: { ...mockAboutData, project: null },
+ loading: false,
+ error: null,
})
await act(async () => {
@@ -488,30 +449,22 @@ describe('About Component', () => {
test('handles partial user data in leader response', async () => {
const partialUserData = {
+ avatarUrl: 'https://avatars.githubusercontent.com/u/2201626?v=4',
+ company: 'OWASP',
+ // name is missing
+ login: 'arkid15r',
+ url: '/members/arkid15r',
+ }
+
+ ;(useQuery as unknown as jest.Mock).mockReturnValue({
data: {
- user: {
- avatarUrl: 'https://avatars.githubusercontent.com/u/2201626?v=4',
- company: 'OWASP',
- // name is missing
- login: 'arkid15r',
- url: '/members/arkid15r',
- },
+ ...mockAboutData,
+ users: mockAboutData.users.map((user) =>
+ user.login === 'arkid15r' ? partialUserData : user
+ ),
},
loading: false,
error: null,
- }
-
- ;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
- if (query === GetProjectMetadataDocument && options?.variables?.key === 'nest') {
- return mockProjectData
- } else if (query === GetTopContributorsDocument && options?.variables?.key === 'nest') {
- return mockTopContributorsData
- } else if (options?.variables?.key === 'arkid15r') {
- return partialUserData
- } else if (options?.variables?.key === 'kasya' || options?.variables?.key === 'mamicidal') {
- return mockUserData(options?.variables?.key)
- }
- return { loading: true }
})
await act(async () => {
@@ -571,35 +524,9 @@ describe('About Component', () => {
})
})
- test('triggers toaster error when GraphQL request fails for project', async () => {
+ test('triggers toaster error when GraphQL request fails', async () => {
;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
- if (query === GetProjectMetadataDocument && options?.variables?.key === 'nest') {
- return { loading: false, data: null, error: new Error('GraphQL error') }
- }
- return {
- loading: false,
- data: { user: { avatarUrl: '', company: '', name: 'Dummy', location: '' } },
- error: null,
- }
- })
- await act(async () => {
- render()
- })
- await waitFor(() => {
- expect(addToast).toHaveBeenCalledWith({
- color: 'danger',
- description: 'GraphQL error',
- shouldShowTimeoutProgress: true,
- timeout: 5000,
- title: 'Server Error',
- variant: 'solid',
- })
- })
- })
-
- test('triggers toaster error when GraphQL request fails for topContributors', async () => {
- ;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
- if (query === GetTopContributorsDocument && options?.variables?.key === 'nest') {
+ if (options?.variables?.key === 'nest') {
return { loading: false, data: null, error: new Error('GraphQL error') }
}
return {
@@ -684,37 +611,4 @@ describe('About Component', () => {
expect(screen.getByText('Timeline Event 2')).toBeInTheDocument()
expect(screen.queryByText('Timeline Event 1')).not.toBeInTheDocument()
})
-
- test('triggers toaster error when GraphQL request fails for a leader', async () => {
- ;(useQuery as unknown as jest.Mock).mockImplementation((query, options) => {
- if (query === GetLeaderDataDocument && options?.variables?.key === 'arkid15r') {
- return { loading: false, data: null, error: new Error('GraphQL error for leader') }
- }
- if (query === GetProjectMetadataDocument) {
- return mockProjectData
- }
- if (query === GetTopContributorsDocument) {
- return mockTopContributorsData
- }
- if (query === GetLeaderDataDocument) {
- return mockUserData(options?.variables?.key)
- }
- return { loading: true }
- })
-
- await act(async () => {
- render()
- })
-
- await waitFor(() => {
- expect(addToast).toHaveBeenCalledWith({
- color: 'danger',
- description: 'GraphQL error for leader',
- shouldShowTimeoutProgress: true,
- timeout: 5000,
- title: 'Server Error',
- variant: 'solid',
- })
- })
- })
})
diff --git a/frontend/src/app/about/page.tsx b/frontend/src/app/about/page.tsx
index f447e70caa..0f686b414e 100644
--- a/frontend/src/app/about/page.tsx
+++ b/frontend/src/app/about/page.tsx
@@ -11,11 +11,7 @@ import { FaCircleCheck, FaClock, FaScroll, FaBullseye, FaUser, FaUsersGear } fro
import { HiUserGroup } from 'react-icons/hi'
import { IconWrapper } from 'wrappers/IconWrapper'
import { ErrorDisplay, handleAppError } from 'app/global-error'
-import {
- GetProjectMetadataDocument,
- GetTopContributorsDocument,
-} from 'types/__generated__/projectQueries.generated'
-import { GetLeaderDataDocument } from 'types/__generated__/userQueries.generated'
+import { GetAboutPageDataDocument } from 'types/__generated__/aboutQueries.generated'
import {
technologies,
missionContent,
@@ -66,50 +62,35 @@ const getMilestoneIcon = (progress: number) => {
const About = () => {
const {
- data: projectMetadataResponse,
- loading: projectMetadataLoading,
- error: projectMetadataRequestError,
- } = useQuery(GetProjectMetadataDocument, {
- variables: { key: projectKey },
- })
-
- const {
- data: topContributorsResponse,
- loading: topContributorsLoading,
- error: topContributorsRequestError,
- } = useQuery(GetTopContributorsDocument, {
+ data: aboutPageDataResponse,
+ loading: aboutPageDataLoading,
+ error: aboutPageDataRequestError,
+ } = useQuery(GetAboutPageDataDocument, {
variables: {
- excludedUsernames: Object.keys(leaders),
- hasFullName: true,
key: projectKey,
+ leaderLogins: Object.keys(leaders),
+ hasFullName: true,
limit: 24,
},
})
- const { leadersData, isLoading: leadersLoading } = useLeadersData()
-
- // Derive data directly from response to prevent race conditions.
- const projectMetadata = projectMetadataResponse?.project
- const topContributors = topContributorsResponse?.topContributors
-
+ const projectMetadata = aboutPageDataResponse?.project
+ const topContributors = aboutPageDataResponse?.topContributors
+ const leadersData = (aboutPageDataResponse?.users ?? []).filter(Boolean).map((leader) => ({
+ description: leaders[leader.login],
+ memberName: leader.name || leader.login,
+ member: leader,
+ }))
const [showAllRoadmap, setShowAllRoadmap] = useState(false)
const [showAllTimeline, setShowAllTimeline] = useState(false)
useEffect(() => {
- if (projectMetadataRequestError) {
- handleAppError(projectMetadataRequestError)
- }
- }, [projectMetadataRequestError])
-
- useEffect(() => {
- if (topContributorsRequestError) {
- handleAppError(topContributorsRequestError)
+ if (aboutPageDataRequestError) {
+ handleAppError(aboutPageDataRequestError)
}
- }, [topContributorsRequestError])
-
- const isLoading = leadersLoading || projectMetadataLoading || topContributorsLoading
+ }, [aboutPageDataRequestError])
- if (isLoading) {
+ if (aboutPageDataLoading) {
return
}
@@ -319,46 +300,4 @@ const About = () => {
)
}
-const useLeadersData = () => {
- const {
- data: leader1Data,
- loading: loading1,
- error: error1,
- } = useQuery(GetLeaderDataDocument, {
- variables: { key: 'arkid15r' },
- })
- const {
- data: leader2Data,
- loading: loading2,
- error: error2,
- } = useQuery(GetLeaderDataDocument, {
- variables: { key: 'kasya' },
- })
- const {
- data: leader3Data,
- loading: loading3,
- error: error3,
- } = useQuery(GetLeaderDataDocument, {
- variables: { key: 'mamicidal' },
- })
-
- const isLoading = loading1 || loading2 || loading3
-
- useEffect(() => {
- if (error1) handleAppError(error1)
- if (error2) handleAppError(error2)
- if (error3) handleAppError(error3)
- }, [error1, error2, error3])
-
- const leadersData = [leader1Data?.user, leader2Data?.user, leader3Data?.user]
- .filter(Boolean)
- .map((user) => ({
- description: leaders[user.login],
- memberName: user.name || user.login,
- member: user,
- }))
-
- return { leadersData, isLoading }
-}
-
export default About
diff --git a/frontend/src/server/queries/aboutQueries.ts b/frontend/src/server/queries/aboutQueries.ts
new file mode 100644
index 0000000000..2cc312cf09
--- /dev/null
+++ b/frontend/src/server/queries/aboutQueries.ts
@@ -0,0 +1,55 @@
+import { gql } from '@apollo/client'
+
+export const GET_ABOUT_PAGE_DATA = gql`
+ query GetAboutPageData(
+ $key: String!
+ $leaderLogins: [String!]!
+ $hasFullName: Boolean = false
+ $limit: Int = 20
+ ) {
+ project(key: $key) {
+ id
+ contributorsCount
+ forksCount
+ issuesCount
+ name
+ starsCount
+ summary
+ recentMilestones(limit: 25) {
+ id
+ title
+ url
+ body
+ progress
+ state
+ }
+ }
+
+ topContributors(
+ excludedUsernames: $leaderLogins
+ hasFullName: $hasFullName
+ limit: $limit
+ project: $key
+ ) {
+ id
+ avatarUrl
+ login
+ name
+ }
+
+ users(logins: $leaderLogins) {
+ id
+ avatarUrl
+ login
+ name
+ badgeCount
+ badges {
+ cssClass
+ description
+ id
+ name
+ weight
+ }
+ }
+ }
+`
diff --git a/frontend/src/types/__generated__/aboutQueries.generated.ts b/frontend/src/types/__generated__/aboutQueries.generated.ts
new file mode 100644
index 0000000000..1944d604ff
--- /dev/null
+++ b/frontend/src/types/__generated__/aboutQueries.generated.ts
@@ -0,0 +1,15 @@
+import * as Types from './graphql';
+
+import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
+export type GetAboutPageDataQueryVariables = Types.Exact<{
+ key: Types.Scalars['String']['input'];
+ leaderLogins: Array | Types.Scalars['String']['input'];
+ hasFullName?: Types.InputMaybe;
+ limit?: Types.InputMaybe;
+}>;
+
+
+export type GetAboutPageDataQuery = { project: { __typename: 'ProjectNode', id: string, contributorsCount: number, forksCount: number, issuesCount: number, name: string, starsCount: number, summary: string, recentMilestones: Array<{ __typename: 'MilestoneNode', id: string, title: string, url: string, body: string, progress: number, state: string }> } | null, topContributors: Array<{ __typename: 'RepositoryContributorNode', id: string, avatarUrl: string, login: string, name: string }>, users: Array<{ __typename: 'UserNode', id: string, avatarUrl: string, login: string, name: string, badgeCount: number, badges: Array<{ __typename: 'BadgeNode', cssClass: string, description: string, id: string, name: string, weight: number }> }> };
+
+
+export const GetAboutPageDataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetAboutPageData"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"key"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"leaderLogins"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"hasFullName"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}},"defaultValue":{"kind":"BooleanValue","value":false}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"limit"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}},"defaultValue":{"kind":"IntValue","value":"20"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"key"},"value":{"kind":"Variable","name":{"kind":"Name","value":"key"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"contributorsCount"}},{"kind":"Field","name":{"kind":"Name","value":"forksCount"}},{"kind":"Field","name":{"kind":"Name","value":"issuesCount"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"starsCount"}},{"kind":"Field","name":{"kind":"Name","value":"summary"}},{"kind":"Field","name":{"kind":"Name","value":"recentMilestones"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"25"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"url"}},{"kind":"Field","name":{"kind":"Name","value":"body"}},{"kind":"Field","name":{"kind":"Name","value":"progress"}},{"kind":"Field","name":{"kind":"Name","value":"state"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"topContributors"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"excludedUsernames"},"value":{"kind":"Variable","name":{"kind":"Name","value":"leaderLogins"}}},{"kind":"Argument","name":{"kind":"Name","value":"hasFullName"},"value":{"kind":"Variable","name":{"kind":"Name","value":"hasFullName"}}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"limit"}}},{"kind":"Argument","name":{"kind":"Name","value":"project"},"value":{"kind":"Variable","name":{"kind":"Name","value":"key"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}},{"kind":"Field","name":{"kind":"Name","value":"login"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"users"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"logins"},"value":{"kind":"Variable","name":{"kind":"Name","value":"leaderLogins"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}},{"kind":"Field","name":{"kind":"Name","value":"login"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"badgeCount"}},{"kind":"Field","name":{"kind":"Name","value":"badges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"cssClass"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"weight"}}]}}]}}]}}]} as unknown as DocumentNode;
\ No newline at end of file
diff --git a/frontend/src/types/__generated__/graphql.ts b/frontend/src/types/__generated__/graphql.ts
index c1eb07d419..88a03df559 100644
--- a/frontend/src/types/__generated__/graphql.ts
+++ b/frontend/src/types/__generated__/graphql.ts
@@ -725,6 +725,7 @@ export type Query = {
topContributors: Array;
upcomingEvents: Array;
user?: Maybe;
+ users: Array;
};
@@ -939,6 +940,11 @@ export type QueryUserArgs = {
login: Scalars['String']['input'];
};
+
+export type QueryUsersArgs = {
+ logins: Array;
+};
+
export type ReleaseNode = Node & {
__typename?: 'ReleaseNode';
author?: Maybe;