Skip to content
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

refactor: Landscape membership list #1262

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f288a4f
chore: Upgrade shared version
josebui Oct 11, 2023
d5f25ac
refactor: Use membership list for home page and landscapeService
josebui Oct 11, 2023
54f38b4
refactor: (WIP) Landscape view membership list
josebui Oct 11, 2023
e9a66e4
chore: Updated shared version
josebui Oct 27, 2023
699c983
fix: Fixed Landscape View, Landscape List, Shared data link to Landscape
josebui Oct 30, 2023
1d19913
fix: Get home landscapes by user email
josebui Oct 31, 2023
297310a
fix: Linter fixes
josebui Oct 31, 2023
ab5ad69
refactor: (WIP) Landscape membership list
josebui Oct 31, 2023
c7a3e43
refactor: Landscape members list
josebui Oct 31, 2023
26b1cfb
fix: Removed default landscape group filter
josebui Nov 1, 2023
787e544
fix: Use collaboration context for shared data components
josebui Nov 1, 2023
db1cc89
chore: Updated shared version
josebui Nov 1, 2023
692b0a5
fix: Fixed tests
josebui Nov 1, 2023
b61b8e9
chore: Updated shared version
josebui Nov 1, 2023
c7ae8c5
fix: Added base url for collaboration context in group view
josebui Nov 1, 2023
5fb5cde
fix: Moved string to collaboration
josebui Nov 1, 2023
8779e79
fix: Get manage members permission in landscape view
josebui Nov 1, 2023
7af1640
fix: Linter fix
josebui Nov 1, 2023
715580a
Update src/landscape/landscapeSlice.js
josebui Nov 7, 2023
c5718b0
Update src/collaboration/components/MemberJoin.js
josebui Nov 7, 2023
c12141c
Update src/collaboration/components/MembershipJoinLeaveButton.js
josebui Nov 7, 2023
b09c6cf
Update src/collaboration/components/MembershipPendingWarning.js
josebui Nov 7, 2023
9a21373
Update src/collaboration/components/MembershipJoinLeaveButton.js
josebui Nov 7, 2023
8166715
Update src/collaboration/collaborationContext.js
josebui Nov 7, 2023
301b693
Update src/collaboration/components/MembershipCard.js
josebui Nov 7, 2023
d5ae619
Update src/collaboration/components/MembershipCard.js
josebui Nov 7, 2023
53f9fd3
Update src/collaboration/components/MembershipCount.js
josebui Nov 7, 2023
4868b85
fix: Small fixes from PR comments
josebui Nov 7, 2023
7411532
fix: Added label to role select
josebui Nov 7, 2023
525e89e
fix: Linter fix
josebui Nov 7, 2023
472a8f7
chore: Updated shared version
josebui Nov 10, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"slate-hyperscript": "^0.100.0",
"slate-react": "^0.101.0",
"source-map-explorer": "^2.5.3",
"terraso-client-shared": "github:techmatters/terraso-client-shared#7c31557",
"terraso-client-shared": "github:techmatters/terraso-client-shared#3d61ee79d26cdf3651f9a6ef32edcef04e399699",
"use-debounce": "^9.0.4",
"uuid": "^9.0.1",
"web-vitals": "^3.5.0",
Expand Down
3 changes: 3 additions & 0 deletions src/collaboration/collaborationConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@
*/
export const MEMBERSHIP_STATUS_APPROVED = 'APPROVED';
export const MEMBERSHIP_STATUS_PENDING = 'PENDING';

export const MEMBERSHIP_TYPE_CLOSED = 'CLOSED';
export const MEMBERSHIP_TYPE_OPEN = 'OPEN';
68 changes: 68 additions & 0 deletions src/collaboration/collaborationContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright © 2023 Technology Matters
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
import React, { useContext, useMemo } from 'react';
import _ from 'lodash/fp';
import { useTranslation } from 'react-i18next';

const CollaborationContext = React.createContext();

export const CollaborationContextProvider = props => {
const { t } = useTranslation();
const { entityType } = props;

const entityTypeLocalized = useMemo(
() => t('collaboration.entity_type', { context: entityType }),
[entityType, t]
);

const providerValue = useMemo(
() => ({
entityType,
entityTypeLocalized,
..._.pick(
[
'owner',
'baseOwnerUrl',
'accountMembership',
'membershipsInfo',
'onMemberJoin',
'onMemberRemove',
'onMemberRoleChange',
'MemberLeaveButton',
'MemberRemoveButton',
'MemberJoinButton',
'MemberRequestJoinButton',
'MemberRequestCancelButton',
'updateOwner',
],
props
),
}),
[entityType, entityTypeLocalized, props]
);

return (
<CollaborationContext.Provider value={providerValue}>
{props.children}
</CollaborationContext.Provider>
);
};

export const useCollaborationContext = () => {
const context = useContext(CollaborationContext);
return context;
};
45 changes: 45 additions & 0 deletions src/collaboration/components/MemberJoin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright © 2023 Technology Matters
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
import React from 'react';
import _ from 'lodash/fp';
import { useTranslation } from 'react-i18next';
import { LoadingButton } from '@mui/lab';

import { useCollaborationContext } from 'collaboration/collaborationContext';

const MemberJoin = props => {
const { t } = useTranslation();
const { owner } = useCollaborationContext();
const { ariaLabel, onJoin, buttonProps, loading } = props;

return (
<LoadingButton
variant="outlined"
aria-label={t(ariaLabel, {
name: _.get('name', owner),
})}
onClick={onJoin}
loading={loading}
sx={{ flexGrow: 1 }}
{...buttonProps}
>
{t(props.label)}
</LoadingButton>
);
};

export default MemberJoin;
194 changes: 194 additions & 0 deletions src/collaboration/components/MembershipCard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
/*
* Copyright © 2023 Technology Matters
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
import React from 'react';
import _ from 'lodash/fp';
import { Trans, useTranslation } from 'react-i18next';
import { useSelector } from 'terrasoApi/store';
import {
AvatarGroup,
Box,
Button,
Card,
CardActions,
CardContent,
CardHeader,
CircularProgress,
Link,
Typography,
} from '@mui/material';

import {
MEMBERSHIP_STATUS_PENDING,
MEMBERSHIP_TYPE_CLOSED,
} from 'collaboration/collaborationConstants';
import { useCollaborationContext } from 'collaboration/collaborationContext';
import ExternalLink from 'common/components/ExternalLink';
import AccountAvatar from 'account/components/AccountAvatar';

import MembershipJoinLeaveButton from './MembershipJoinLeaveButton';
import MembershipPendingWarning from './MembershipPendingWarning';

const Loader = () => {
const { t } = useTranslation();
return (
<CardContent>
<Box sx={{ display: 'flex', justifyContent: 'center' }}>
<CircularProgress aria-label={t('common.loader_label')} />
</Box>
</CardContent>
);
};

const Content = props => {
const { t } = useTranslation();
const { owner, membershipsInfo, accountMembership } =
useCollaborationContext();
const { user, fetching, onViewMembers } = props;

const membersSample = _.getOr([], 'membershipsSample', membershipsInfo);
const totalCount = _.getOr(0, 'totalCount', membershipsInfo);

if (fetching) {
return <Loader />;
}

const pendingRequest =
accountMembership?.membershipStatus === MEMBERSHIP_STATUS_PENDING;
const closedGroup =
membershipsInfo?.membershipType === MEMBERSHIP_TYPE_CLOSED;

if (pendingRequest) {
return (
<CardContent>
<Trans i18nKey="group.membership_card_pending_description">
<Typography variant="body1">
prefix
<b>bold</b>
</Typography>
</Trans>
</CardContent>
);
}

if (!accountMembership && closedGroup) {
return (
<CardContent>
<Trans
i18nKey="group.membership_card_closed_description"
values={{ name: owner.name }}
>
<Typography variant="body1" sx={{ mb: 2 }}>
description
</Typography>
<Typography variant="body1">
prefix
<ExternalLink href={t('group.membership_card_closed_help_url')}>
link
</ExternalLink>
</Typography>
</Trans>
</CardContent>
);
}

return (
<CardContent>
<Typography variant="body2" color="text.secondary">
{t('group.membership_card_description', {
count: totalCount,
name: owner.name,
})}
</Typography>
<AvatarGroup
component="ul"
aria-labelledby="membership-card-title"
total={totalCount}
sx={{
flexDirection: 'row',
marginTop: 2,
marginBottom: 2,
paddingLeft: 0,
}}
>
{membersSample.map((member, index) => (
<AccountAvatar key={index} user={member} component="li" />
))}
</AvatarGroup>
{user && (
<Link sx={{ cursor: 'pointer' }} onClick={onViewMembers}>
{t('group.membership_view_all')}
</Link>
)}
</CardContent>
);
};

const MembershipCard = props => {
const { t } = useTranslation();
const { membershipsInfo } = useCollaborationContext();
const { onViewMembers, InfoComponent, fetching, allowedToManageMembers } =
props;
const { data: user } = useSelector(_.get('account.currentUser'));

return (
<Card
component="section"
aria-labelledby="membership-card-title"
style={{
width: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
}}
>
<CardHeader
disableTypography
title={
<Typography variant="h2" id="membership-card-title" sx={{ pt: 0 }}>
{t('group.membership_card_title')}
</Typography>
}
/>
<Content user={user} fetching={fetching} onViewMembers={onViewMembers} />
{fetching || !user ? null : (
<CardActions sx={{ display: 'block', paddingBottom: '24px' }}>
{allowedToManageMembers ? (
<Button variant="outlined" onClick={onViewMembers}>
{t('group.membership_card_manage_members')}
</Button>
) : (
<>
<MembershipJoinLeaveButton />
{InfoComponent && <InfoComponent />}
</>
)}
</CardActions>
)}
{allowedToManageMembers && membershipsInfo.pendingCount > 0 && (
<CardContent>
<MembershipPendingWarning
link
count={membershipsInfo.pendingCount}
onPendingClick={onViewMembers}
/>
</CardContent>
)}
</Card>
);
};

export default MembershipCard;
27 changes: 27 additions & 0 deletions src/collaboration/components/MembershipCount.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright © 2023 Technology Matters
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
import React from 'react';
import _ from 'lodash/fp';
import { Typography } from '@mui/material';

const MembershipListCount = props => {
const { membershipsInfo } = props;
const count = _.getOr(0, 'totalCount', membershipsInfo);
return <Typography variant="body1">{count}</Typography>;
};

export default MembershipListCount;
Loading
Loading