• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

alkem-io / client-web / #9048

11 Oct 2024 01:42PM UTC coverage: 5.943%. First build
#9048

Pull #7022

travis-ci

Pull Request #7022: [v0.74.0] Roles API + Unauthenticated Explore page

202 of 10241 branches covered (1.97%)

Branch coverage included in aggregate %.

63 of 431 new or added lines in 60 files covered. (14.62%)

1468 of 17861 relevant lines covered (8.22%)

0.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/domain/community/user/ContributorsView.tsx
1
import {
2
  OrganizationContributorFragment,
3
  RoleSetContributorType,
4
  UserContributorFragment,
5
} from '@/core/apollo/generated/graphql-schema';
6
import ScrollableCardsLayoutContainer from '@/core/ui/card/cardsLayout/ScrollableCardsLayoutContainer';
7
import PageContentBlock from '@/core/ui/content/PageContentBlock';
8
import PageContentBlockHeader from '@/core/ui/content/PageContentBlockHeader';
9
import { useColumns } from '@/core/ui/grid/GridContext';
10
import GridItem from '@/core/ui/grid/GridItem';
11
import GridProvider from '@/core/ui/grid/GridProvider';
12
import { Identifiable } from '@/core/utils/Identifiable';
13
import ImageBackdrop from '@/domain/shared/components/Backdrops/ImageBackdrop';
14
import useLazyLoading from '@/domain/shared/pagination/useLazyLoading';
15
import { Box, GridLegacy } from '@mui/material';
16
import { times } from 'lodash';
17
import { ComponentType, ReactNode, Ref } from 'react';
18
import { useTranslation } from 'react-i18next';
19
import ContributorCardSquare, {
20
  ContributorCardSkeleton,
21
  ContributorCardSquareProps,
22
} from '../contributor/ContributorCardSquare/ContributorCardSquare';
23
import { VirtualContributorModelBase } from '../virtualContributor/model/VirtualContributorModelBase';
24
import { PaginatedResult, VirtualContributors } from './ContributorsPage';
25

26
const grayedOutUsersImgSrc = '/contributors/users-grayed.png';
×
NEW
27
export const ITEMS_PER_PAGE = 32;
×
28

29
const userToContributorCard = (user: UserContributorFragment): ContributorCardSquareProps => {
×
30
  return {
×
31
    id: user.id,
32
    displayName: user.userProfile.displayName,
33
    avatar: user.userProfile.visual?.uri ?? '',
×
34
    url: user.userProfile.url,
35
    tooltip: {
36
      tags: (user.userProfile?.tagsets || []).flatMap(y => y.tags),
×
37
      city: user.userProfile?.location?.city || '',
×
38
      country: user.userProfile?.location?.country || '',
×
39
    },
40
    isContactable: user.isContactable,
41
    contributorType: RoleSetContributorType.User,
42
  };
43
};
44

45
const organizationToContributorCard = (org: OrganizationContributorFragment): ContributorCardSquareProps => {
×
46
  return {
×
47
    id: org.id,
48
    displayName: org.orgProfile.displayName,
49
    avatar: org.orgProfile.visual?.uri ?? '',
×
50
    url: org.orgProfile.url,
51
    isContactable: true,
52
    contributorType: RoleSetContributorType.Organization,
53
  };
54
};
55

56
const vcToContributorCard = (vc: VirtualContributorModelBase): ContributorCardSquareProps => {
57
  return {
58
    id: vc.id,
59
    displayName: vc.profile.displayName,
60
    avatar: vc.profile.avatar?.uri ?? '',
61
    url: vc.profile.url ?? '',
62
    tooltip: {
63
      tags: (vc.profile?.tagsets ?? []).flatMap(y => y.tags),
64
      city: vc.profile?.location?.city ?? '',
65
      country: vc.profile?.location?.country ?? '',
66
    },
67
    isContactable: false,
68
    contributorType: RoleSetContributorType.Virtual,
69
  };
70
};
×
71

72
export interface ContributorsViewProps {
73
  showUsers: boolean;
74
  usersPaginated: PaginatedResult<UserContributorFragment> | undefined; // only for registered users
75
  organizationsPaginated: PaginatedResult<OrganizationContributorFragment> | undefined;
76
  virtualContributors: VirtualContributors | undefined;
×
77
}
78

×
79
interface ContributorsListProps<Item extends Identifiable> {
80
  items: Item[] | undefined;
×
81
  loading?: boolean;
82
  hasMoreRef?: Ref<HTMLDivElement>;
×
83
  cardComponent: ComponentType<Item>;
84
  loader: ReactNode;
85
}
86

87
const ContributorsList = <Item extends Identifiable>({
88
  cardComponent: Card,
89
  items,
×
90
  loading,
91
  loader,
×
92
}: ContributorsListProps<Item>) => {
93
  const columns = useColumns();
94

95
  return (
96
    <GridProvider columns={16} force={columns === 12}>
97
      <ScrollableCardsLayoutContainer cards={false} maxHeight={theme => theme.spacing(26)}>
98
        {items?.map(item => (
99
          <GridItem columns={2} key={item.id}>
100
            <Box>
101
              <Card {...item} />
102
            </Box>
×
103
          </GridItem>
104
        ))}
105
        {loader}
106
        {loading &&
107
          times(ITEMS_PER_PAGE, i => (
×
108
            <GridItem columns={2} key={`__loading_${i}`}>
109
              <Box>
×
110
                <ContributorCardSkeleton />
×
111
              </Box>
×
112
            </GridItem>
×
113
          ))}
114
      </ScrollableCardsLayoutContainer>
115
    </GridProvider>
×
116
  );
×
117
};
×
118

×
119
const ContributorsView = ({
120
  showUsers,
121
  usersPaginated: users,
×
122
  organizationsPaginated: orgs,
123
  virtualContributors: vcs,
124
}: ContributorsViewProps) => {
125
  const { t } = useTranslation();
×
126

127
  const usersLoader = useLazyLoading(Box, {
128
    hasMore: users?.hasMore || false,
129
    loading: users?.loading || false,
130
    fetchMore: () => (users?.fetchMore ? users?.fetchMore() : Promise.resolve()),
131
  });
132

133
  const orgsLoader = useLazyLoading(Box, {
×
134
    hasMore: orgs?.hasMore || false,
135
    loading: orgs?.loading || false,
136
    fetchMore: () => (orgs?.fetchMore ? orgs?.fetchMore() : Promise.resolve()),
137
  });
138

139
  return (
×
140
    <>
141
      <PageContentBlock columns={12}>
142
        <PageContentBlockHeader title={t('pages.contributors.users.title')} />
143
        {showUsers && (
144
          <ContributorsList
145
            items={users?.items?.map(userToContributorCard)}
146
            cardComponent={ContributorCardSquare}
147
            loading={users?.loading}
148
            loader={usersLoader}
149
          />
150
        )}
151
        {!showUsers && (
152
          <GridLegacy item>
153
            <ImageBackdrop
154
              src={grayedOutUsersImgSrc}
155
              backdropMessage="login"
156
              blockName="all-contributing-users"
157
              messageSx={theme => ({
158
                [theme.breakpoints.up('sm')]: {
159
                  fontWeight: 'bold',
160
                },
161
              })}
162
            />
163
          </GridLegacy>
164
        )}
165
      </PageContentBlock>
166
      <PageContentBlock columns={12}>
167
        <PageContentBlockHeader title={t('pages.contributors.virtualContributors.title')} />
168
        <ContributorsList
169
          items={vcs?.items?.map(vcToContributorCard)}
170
          cardComponent={ContributorCardSquare}
171
          loading={vcs?.loading}
172
          loader={undefined}
173
        />
174
      </PageContentBlock>
175
      <PageContentBlock columns={12}>
176
        <PageContentBlockHeader title={t('pages.contributors.organizations.title')} />
177
        <ContributorsList
178
          items={orgs?.items?.map(organizationToContributorCard)}
179
          cardComponent={ContributorCardSquare}
180
          loading={orgs?.loading}
181
          loader={orgsLoader}
182
        />
183
      </PageContentBlock>
184
    </>
185
  );
186
};
187

188
export default ContributorsView;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc