Skip to content

Commit d538442

Browse files
Merge pull request #855 from sudhanshutech/re/share
feat(catalog): restructure share action and add delete action
2 parents 588d510 + 9d97c0a commit d538442

File tree

4 files changed

+158
-105
lines changed

4 files changed

+158
-105
lines changed

src/custom/CatalogDetail/ActionButton.tsx

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import React from 'react';
22
import { CircularProgress } from '../../base';
3-
import { CopyIcon, EditIcon, KanvasIcon, PublishIcon } from '../../icons';
3+
import {
4+
CopyIcon,
5+
DeleteIcon,
6+
EditIcon,
7+
KanvasIcon,
8+
PublishIcon,
9+
ShareLineIcon
10+
} from '../../icons';
411
import Download from '../../icons/Download/Download';
512
import { charcoal, useTheme } from '../../theme';
613
import { Pattern } from '../CustomCatalog/CustomCard';
@@ -21,6 +28,10 @@ interface ActionButtonsProps {
2128
onOpenPlaygroundClick: (designId: string, name: string) => void;
2229
showInfoAction?: boolean;
2330
handleInfoClick?: () => void;
31+
showShareAction?: boolean;
32+
handleShare: () => void;
33+
showDeleteAction?: boolean;
34+
handleDelete: () => void;
2435
}
2536

2637
const ActionButtons: React.FC<ActionButtonsProps> = ({
@@ -35,7 +46,11 @@ const ActionButtons: React.FC<ActionButtonsProps> = ({
3546
showOpenPlaygroundAction,
3647
onOpenPlaygroundClick,
3748
showInfoAction,
38-
handleInfoClick
49+
handleInfoClick,
50+
showShareAction,
51+
handleShare,
52+
showDeleteAction,
53+
handleDelete
3954
}) => {
4055
const cleanedType = type.replace('my-', '').replace(/s$/, '');
4156
const theme = useTheme();
@@ -132,23 +147,51 @@ const ActionButtons: React.FC<ActionButtonsProps> = ({
132147
}}
133148
onClick={handleInfoClick}
134149
>
135-
<EditIcon width={24} height={24} fill={charcoal[10]} />
150+
<EditIcon width={24} height={24} fill={theme.palette.icon.default} />
136151
Edit
137152
</ActionButton>
138153
)}
139-
{showUnpublishAction && (
154+
{showShareAction && (
155+
<ActionButton
156+
sx={{
157+
borderRadius: '0.2rem',
158+
backgroundColor: 'transparent',
159+
border: `1px solid ${theme.palette.border.normal}`,
160+
gap: '10px',
161+
color: charcoal[10]
162+
}}
163+
onClick={handleShare}
164+
>
165+
<ShareLineIcon width="24" height="24" fill={theme.palette.icon.default} />
166+
Share
167+
</ActionButton>
168+
)}
169+
{showDeleteAction && (
140170
<UnpublishAction
141171
sx={{
142172
borderRadius: '0.2rem',
143173
gap: '10px'
144174
}}
145-
onClick={handleUnpublish}
175+
onClick={handleDelete}
146176
>
147-
<PublishIcon width={24} height={24} fill={charcoal[100]} />
148-
Unpublish
177+
<DeleteIcon width={24} height={24} fill={charcoal[100]} />
178+
Delete
149179
</UnpublishAction>
150180
)}
151181
</div>
182+
183+
{showUnpublishAction && (
184+
<UnpublishAction
185+
sx={{
186+
borderRadius: '0.2rem',
187+
gap: '10px'
188+
}}
189+
onClick={handleUnpublish}
190+
>
191+
<PublishIcon width={24} height={24} fill={charcoal[100]} />
192+
Unpublish
193+
</UnpublishAction>
194+
)}
152195
</StyledActionWrapper>
153196
);
154197
};

src/custom/CatalogDetail/LeftPanel.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ interface LeftPanelProps {
2525
onOpenPlaygroundClick: (designId: string, name: string) => void;
2626
showInfoAction?: boolean;
2727
handleInfoClick?: () => void;
28+
showShareAction?: boolean;
29+
handleShare: () => void;
30+
showDeleteAction?: boolean;
31+
handleDelete: () => void;
2832
}
2933

3034
const LeftPanel: React.FC<LeftPanelProps> = ({
@@ -44,7 +48,11 @@ const LeftPanel: React.FC<LeftPanelProps> = ({
4448
showOpenPlaygroundAction = true,
4549
onOpenPlaygroundClick,
4650
showInfoAction = false,
47-
handleInfoClick
51+
handleInfoClick,
52+
showShareAction = false,
53+
handleShare,
54+
showDeleteAction = false,
55+
handleDelete
4856
}) => {
4957
const theme = useTheme();
5058

@@ -89,6 +97,10 @@ const LeftPanel: React.FC<LeftPanelProps> = ({
8997
onOpenPlaygroundClick={onOpenPlaygroundClick}
9098
showInfoAction={showInfoAction}
9199
handleInfoClick={handleInfoClick}
100+
showShareAction={showShareAction}
101+
handleShare={handleShare}
102+
showDeleteAction={showDeleteAction}
103+
handleDelete={handleDelete}
92104
/>
93105
{showTechnologies && (
94106
<TechnologySection

src/custom/CatalogDetail/SocialSharePopper.tsx

Lines changed: 24 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
1-
import { Lock, Public } from '@mui/icons-material';
21
import { Box, IconButton, Menu, MenuItem } from '@mui/material';
32
import React, { useState } from 'react';
43
import { FacebookShareButton, LinkedinShareButton, TwitterShareButton } from 'react-share';
5-
import { Typography } from '../../base';
6-
import { ChainIcon, FacebookIcon, LinkedinIcon, ShareIcon, TwitterIcon } from '../../icons';
4+
5+
import {
6+
ChainIcon,
7+
FacebookIcon,
8+
LinkedinIcon,
9+
LockIcon,
10+
PublicIcon,
11+
ShareIcon,
12+
TwitterIcon
13+
} from '../../icons';
714
import { useTheme } from '../../theme';
815
import { Pattern } from '../CustomCatalog/CustomCard';
916
import { CustomTooltip } from '../CustomTooltip';
1017
import { ErrorBoundary } from '../ErrorBoundary';
18+
1119
import { VisibilityChipMenu } from '../VisibilityChipMenu';
1220
import { VIEW_VISIBILITY } from '../VisibilityChipMenu/VisibilityChipMenu';
13-
import { CopyShareIconWrapper, ShareButton, ShareButtonGroup, ShareSideButton } from './style';
21+
import { CopyShareIconWrapper } from './style';
1422

1523
interface SocialSharePopperProps {
1624
details: Pattern;
@@ -29,9 +37,7 @@ const SocialSharePopper: React.FC<SocialSharePopperProps> = ({
2937
cardId,
3038
title,
3139
getUrl,
32-
handleCopyUrl,
33-
showShareAction,
34-
handleShare
40+
handleCopyUrl
3541
}) => {
3642
const theme = useTheme();
3743
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
@@ -55,41 +61,19 @@ const SocialSharePopper: React.FC<SocialSharePopperProps> = ({
5561
onChange={() => {}}
5662
enabled={false}
5763
options={[
58-
[VIEW_VISIBILITY.PUBLIC, Public],
59-
[VIEW_VISIBILITY.PRIVATE, Lock]
64+
[VIEW_VISIBILITY.PUBLIC, PublicIcon],
65+
[VIEW_VISIBILITY.PRIVATE, LockIcon]
6066
]}
6167
/>
62-
{showShareAction ? (
63-
<ShareButtonGroup variant="contained">
64-
<CustomTooltip title="Change access and visibility">
65-
<ShareButton variant="contained" onClick={handleShare}>
66-
<Typography>Share</Typography>
67-
</ShareButton>
68-
</CustomTooltip>
69-
<CustomTooltip title="Copy link to design">
70-
<ShareSideButton
71-
variant="contained"
72-
size="small"
73-
onClick={() => handleCopyUrl(cleanedType, details?.name, details?.id)}
74-
>
75-
<ChainIcon height={'24'} width={'24'} fill={theme.palette.icon.inverse} />
76-
</ShareSideButton>
77-
</CustomTooltip>
78-
</ShareButtonGroup>
79-
) : (
80-
<>
81-
{details?.visibility !== 'private' && (
82-
<CustomTooltip title="Copy Link" placement="top" arrow>
83-
<IconButton
84-
sx={{ borderRadius: '0.1rem', padding: '0.5rem' }}
85-
onClick={() => handleCopyUrl(cleanedType, details?.name, details?.id)}
86-
>
87-
<ChainIcon height={'24'} width={'24'} fill={theme.palette.icon.secondary} />
88-
</IconButton>
89-
</CustomTooltip>
90-
)}
91-
</>
92-
)}
68+
69+
<CustomTooltip title="Copy Link" placement="top" arrow>
70+
<IconButton
71+
sx={{ borderRadius: '0.1rem', padding: '0.5rem' }}
72+
onClick={() => handleCopyUrl(cleanedType, details?.name, details?.id)}
73+
>
74+
<ChainIcon height={'24'} width={'24'} fill={theme.palette.icon.secondary} />
75+
</IconButton>
76+
</CustomTooltip>
9377

9478
{(details?.visibility === 'published' || details?.visibility === 'public') && (
9579
<>

src/custom/ShareModal/ShareModal.tsx

Lines changed: 71 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
import { ChainIcon, DeleteIcon, LockIcon, PublicIcon } from '../../icons';
1515
import { useTheme } from '../../theme';
1616
import { BLACK, WHITE } from '../../theme/colors';
17+
import { CustomTooltip } from '../CustomTooltip';
1718
import { Modal, ModalBody, ModalButtonPrimary, ModalButtonSecondary, ModalFooter } from '../Modal';
1819
import UserShareSearch from '../UserSearchField/UserSearchField';
1920
import {
@@ -97,13 +98,15 @@ const AccessList: React.FC<AccessListProps> = ({
9798
{ownerData.id === actorData.id ? (
9899
<div>Owner</div>
99100
) : (
100-
<IconButton
101-
edge="end"
102-
aria-label="delete"
103-
onClick={() => handleDelete(actorData.email)}
104-
>
105-
<DeleteIcon fill={theme.palette.background.neutral?.default} />
106-
</IconButton>
101+
<CustomTooltip title="Remove Access" placement="top" arrow>
102+
<IconButton
103+
edge="end"
104+
aria-label="delete"
105+
onClick={() => handleDelete(actorData.email)}
106+
>
107+
<DeleteIcon fill={theme.palette.background.neutral?.default} />
108+
</IconButton>
109+
</CustomTooltip>
107110
)}
108111
</ListItemSecondaryAction>
109112
</ListItem>
@@ -185,6 +188,9 @@ const ShareModal: React.FC<ShareModalProps> = ({
185188
const handleMenuClose = () => setMenu(false);
186189

187190
const isShareDisabled = () => {
191+
// Ensure at least one user other than the owner is selected
192+
const otherUsersSelected = shareUserData.some((user) => user.id !== ownerData.id);
193+
188194
const existingAccessIds = shareUserData.map((user) => user.id);
189195
const ownerDataId = ownerData?.id;
190196

@@ -195,10 +201,10 @@ const ShareModal: React.FC<ShareModalProps> = ({
195201
const hasMismatchedUsers = !shareUserData.every((user) => existingAccessIds.includes(user.id));
196202

197203
return (
198-
shareUserData.length === existingAccessIds.length &&
199-
!hasMismatchedUsers &&
200-
(selectedOption === selectedResource?.visibility ||
201-
shareUserData.length !== existingAccessIds.length)
204+
!otherUsersSelected || // Disable if no other users are selected
205+
(shareUserData.length === existingAccessIds.length &&
206+
!hasMismatchedUsers &&
207+
selectedOption === selectedResource?.visibility)
202208
);
203209
};
204210

@@ -238,52 +244,60 @@ const ShareModal: React.FC<ShareModalProps> = ({
238244
}
239245
fetchSuggestions={fetchSuggestions}
240246
/>
241-
<CustomListItemText>
242-
<Typography variant="h6">General Access</Typography>
243-
</CustomListItemText>
244-
<CustomDialogContentText>
245-
<FormControlWrapper size="small">
246-
<div style={{ display: 'flex', justifyContent: 'start', alignItems: 'center' }}>
247-
<VisibilityIconWrapper>
248-
{selectedOption === SHARE_MODE.PUBLIC ? (
249-
<PublicIcon
250-
width={24}
251-
height={24}
252-
stroke={theme.palette.mode === 'dark' ? WHITE : BLACK}
253-
/>
254-
) : (
255-
<LockIcon
256-
width={24}
257-
height={24}
258-
stroke={theme.palette.mode === 'dark' ? WHITE : BLACK}
259-
/>
260-
)}
261-
</VisibilityIconWrapper>
262-
<div style={{ display: 'flex', flexDirection: 'column' }}>
263-
<CustomSelect
264-
variant="outlined"
265-
defaultValue={selectedOption}
266-
labelId="share-menu-select"
267-
id="share-menu"
268-
open={openMenu}
269-
onClose={handleMenuClose}
270-
onOpen={() => setMenu(true)}
271-
onChange={handleOptionClick}
272-
disabled={isVisibilitySelectorDisabled}
273-
>
274-
{Object.values(SHARE_MODE).map((option) => (
275-
<MenuItem key={option} selected={option === selectedOption} value={option}>
276-
{option.charAt(0).toUpperCase() + option.slice(1)}
277-
</MenuItem>
278-
))}
279-
</CustomSelect>
280-
<Typography component="span" variant="body2">
281-
{selectedOption === SHARE_MODE.PRIVATE ? options.PRIVATE : options.PUBLIC}
282-
</Typography>
283-
</div>
284-
</div>
285-
</FormControlWrapper>
286-
</CustomDialogContentText>
247+
{selectedResource?.visibility !== 'published' && (
248+
<>
249+
<CustomListItemText>
250+
<Typography variant="h6">General Access</Typography>
251+
</CustomListItemText>
252+
<CustomDialogContentText>
253+
<FormControlWrapper size="small">
254+
<div style={{ display: 'flex', justifyContent: 'start', alignItems: 'center' }}>
255+
<VisibilityIconWrapper>
256+
{selectedOption === SHARE_MODE.PUBLIC ? (
257+
<PublicIcon
258+
width={24}
259+
height={24}
260+
stroke={theme.palette.mode === 'dark' ? WHITE : BLACK}
261+
/>
262+
) : (
263+
<LockIcon
264+
width={24}
265+
height={24}
266+
stroke={theme.palette.mode === 'dark' ? WHITE : BLACK}
267+
/>
268+
)}
269+
</VisibilityIconWrapper>
270+
<div style={{ display: 'flex', flexDirection: 'column' }}>
271+
<CustomSelect
272+
variant="outlined"
273+
defaultValue={selectedOption}
274+
labelId="share-menu-select"
275+
id="share-menu"
276+
open={openMenu}
277+
onClose={handleMenuClose}
278+
onOpen={() => setMenu(true)}
279+
onChange={handleOptionClick}
280+
disabled={isVisibilitySelectorDisabled}
281+
>
282+
{Object.values(SHARE_MODE).map((option) => (
283+
<MenuItem
284+
key={option}
285+
selected={option === selectedOption}
286+
value={option}
287+
>
288+
{option.charAt(0).toUpperCase() + option.slice(1)}
289+
</MenuItem>
290+
))}
291+
</CustomSelect>
292+
<Typography component="span" variant="body2">
293+
{selectedOption === SHARE_MODE.PRIVATE ? options.PRIVATE : options.PUBLIC}
294+
</Typography>
295+
</div>
296+
</div>
297+
</FormControlWrapper>
298+
</CustomDialogContentText>
299+
</>
300+
)}
287301
</ModalBody>
288302

289303
<ModalFooter

0 commit comments

Comments
 (0)