From 6a792e8adb9ad9aa26e4b406965cc28e0370d3c2 Mon Sep 17 00:00:00 2001 From: Sudhanshu Dasgupta Date: Tue, 17 Dec 2024 13:15:08 +0530 Subject: [PATCH 1/3] fix(share): revamp share action and modal Signed-off-by: Sudhanshu Dasgupta --- src/custom/CatalogDetail/ActionButton.tsx | 37 ++++++++++++---- src/custom/CatalogDetail/LeftPanel.tsx | 8 +++- .../CatalogDetail/SocialSharePopper.tsx | 35 +++++----------- src/custom/ShareModal/ShareModal.tsx | 42 +++++++++++++------ 4 files changed, 75 insertions(+), 47 deletions(-) diff --git a/src/custom/CatalogDetail/ActionButton.tsx b/src/custom/CatalogDetail/ActionButton.tsx index ee6cb48ce..72dd6f149 100644 --- a/src/custom/CatalogDetail/ActionButton.tsx +++ b/src/custom/CatalogDetail/ActionButton.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { CircularProgress } from '../../base'; -import { CopyIcon, EditIcon, KanvasIcon, PublishIcon } from '../../icons'; +import { CopyIcon, EditIcon, KanvasIcon, PublishIcon, ShareIcon } from '../../icons'; import Download from '../../icons/Download/Download'; import { charcoal, useTheme } from '../../theme'; import { Pattern } from '../CustomCatalog/CustomCard'; @@ -21,6 +21,8 @@ interface ActionButtonsProps { onOpenPlaygroundClick: (designId: string, name: string) => void; showInfoAction?: boolean; handleInfoClick?: () => void; + showShareAction?: boolean; + handleShare: () => void; } const ActionButtons: React.FC = ({ @@ -35,7 +37,9 @@ const ActionButtons: React.FC = ({ showOpenPlaygroundAction, onOpenPlaygroundClick, showInfoAction, - handleInfoClick + handleInfoClick, + showShareAction, + handleShare }) => { const cleanedType = type.replace('my-', '').replace(/s$/, ''); const theme = useTheme(); @@ -136,19 +140,34 @@ const ActionButtons: React.FC = ({ Edit )} - {showUnpublishAction && ( - - - Unpublish - + + Share + )} + {showUnpublishAction && ( + + + Unpublish + + )} ); }; diff --git a/src/custom/CatalogDetail/LeftPanel.tsx b/src/custom/CatalogDetail/LeftPanel.tsx index 82d7fe995..fa7beeedd 100644 --- a/src/custom/CatalogDetail/LeftPanel.tsx +++ b/src/custom/CatalogDetail/LeftPanel.tsx @@ -25,6 +25,8 @@ interface LeftPanelProps { onOpenPlaygroundClick: (designId: string, name: string) => void; showInfoAction?: boolean; handleInfoClick?: () => void; + showShareAction?: boolean; + handleShare: () => void; } const LeftPanel: React.FC = ({ @@ -44,7 +46,9 @@ const LeftPanel: React.FC = ({ showOpenPlaygroundAction = true, onOpenPlaygroundClick, showInfoAction = false, - handleInfoClick + handleInfoClick, + showShareAction = false, + handleShare }) => { const theme = useTheme(); @@ -89,6 +93,8 @@ const LeftPanel: React.FC = ({ onOpenPlaygroundClick={onOpenPlaygroundClick} showInfoAction={showInfoAction} handleInfoClick={handleInfoClick} + showShareAction={showShareAction} + handleShare={handleShare} /> {showTechnologies && ( = ({ cardId, title, getUrl, - handleCopyUrl, - showShareAction, - handleShare + handleCopyUrl }) => { const theme = useTheme(); const [anchorEl, setAnchorEl] = useState(null); @@ -54,27 +52,14 @@ const SocialSharePopper: React.FC = ({ {details?.visibility} - {showShareAction ? ( - - - - Share - - - ) : ( - <> - {details?.visibility !== 'private' && ( - - handleCopyUrl(cleanedType, details?.name, details?.id)} - > - - - - )} - - )} + + handleCopyUrl(cleanedType, details?.name, details?.id)} + > + + + {(details?.visibility === 'published' || details?.visibility === 'public') && ( <> diff --git a/src/custom/ShareModal/ShareModal.tsx b/src/custom/ShareModal/ShareModal.tsx index fd8213d94..76ca1c125 100644 --- a/src/custom/ShareModal/ShareModal.tsx +++ b/src/custom/ShareModal/ShareModal.tsx @@ -14,6 +14,7 @@ import { import { ChainIcon, DeleteIcon, LockIcon, PublicIcon } from '../../icons'; import { useTheme } from '../../theme'; import { BLACK, WHITE } from '../../theme/colors'; +import { CustomTooltip } from '../CustomTooltip'; import { Modal, ModalBody, ModalButtonPrimary, ModalButtonSecondary, ModalFooter } from '../Modal'; import UserShareSearch from '../UserSearchField/UserSearchField'; import { @@ -97,13 +98,15 @@ const AccessList: React.FC = ({ {ownerData.id === actorData.id ? (
Owner
) : ( - handleDelete(actorData.email)} - > - - + + handleDelete(actorData.email)} + > + + + )} @@ -185,6 +188,9 @@ const ShareModal: React.FC = ({ const handleMenuClose = () => setMenu(false); const isShareDisabled = () => { + // Ensure at least one user other than the owner is selected + const otherUsersSelected = shareUserData.some((user) => user.id !== ownerData.id); + const existingAccessIds = shareUserData.map((user) => user.id); const ownerDataId = ownerData?.id; @@ -195,10 +201,10 @@ const ShareModal: React.FC = ({ const hasMismatchedUsers = !shareUserData.every((user) => existingAccessIds.includes(user.id)); return ( - shareUserData.length === existingAccessIds.length && - !hasMismatchedUsers && - (selectedOption === selectedResource?.visibility || - shareUserData.length !== existingAccessIds.length) + !otherUsersSelected || // Disable if no other users are selected + (shareUserData.length === existingAccessIds.length && + !hasMismatchedUsers && + selectedOption === selectedResource?.visibility) ); }; @@ -216,6 +222,18 @@ const ShareModal: React.FC = ({ } }, [selectedResource]); + useEffect(() => { + if (selectedResource?.visibility === 'published') { + setOption(SHARE_MODE.PRIVATE); // Force set to private if published + } else { + setOption(selectedResource?.visibility); + } + }, [selectedResource]); + + // Filter options dynamically to exclude PUBLIC when visibility is published + const filteredOptions = + selectedResource?.visibility === 'published' ? [SHARE_MODE.PRIVATE] : Object.values(SHARE_MODE); + return (
= ({ onChange={handleOptionClick} disabled={isVisibilitySelectorDisabled} > - {Object.values(SHARE_MODE).map((option) => ( + {filteredOptions.map((option) => ( {option.charAt(0).toUpperCase() + option.slice(1)} From d67c4316b6bb1175117b2228f8e5913fc133dbef Mon Sep 17 00:00:00 2001 From: Sudhanshu Dasgupta Date: Tue, 17 Dec 2024 17:13:38 +0530 Subject: [PATCH 2/3] fix(icon): use other share icon Signed-off-by: Sudhanshu Dasgupta --- src/custom/CatalogDetail/ActionButton.tsx | 4 +- src/custom/ShareModal/ShareModal.tsx | 112 +++++++++++----------- 2 files changed, 56 insertions(+), 60 deletions(-) diff --git a/src/custom/CatalogDetail/ActionButton.tsx b/src/custom/CatalogDetail/ActionButton.tsx index 72dd6f149..ac2ef1bb6 100644 --- a/src/custom/CatalogDetail/ActionButton.tsx +++ b/src/custom/CatalogDetail/ActionButton.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { CircularProgress } from '../../base'; -import { CopyIcon, EditIcon, KanvasIcon, PublishIcon, ShareIcon } from '../../icons'; +import { CopyIcon, EditIcon, KanvasIcon, PublishIcon, ShareLineIcon } from '../../icons'; import Download from '../../icons/Download/Download'; import { charcoal, useTheme } from '../../theme'; import { Pattern } from '../CustomCatalog/CustomCard'; @@ -151,7 +151,7 @@ const ActionButtons: React.FC = ({ }} onClick={handleShare} > - + Share )} diff --git a/src/custom/ShareModal/ShareModal.tsx b/src/custom/ShareModal/ShareModal.tsx index 76ca1c125..6150249cd 100644 --- a/src/custom/ShareModal/ShareModal.tsx +++ b/src/custom/ShareModal/ShareModal.tsx @@ -222,18 +222,6 @@ const ShareModal: React.FC = ({ } }, [selectedResource]); - useEffect(() => { - if (selectedResource?.visibility === 'published') { - setOption(SHARE_MODE.PRIVATE); // Force set to private if published - } else { - setOption(selectedResource?.visibility); - } - }, [selectedResource]); - - // Filter options dynamically to exclude PUBLIC when visibility is published - const filteredOptions = - selectedResource?.visibility === 'published' ? [SHARE_MODE.PRIVATE] : Object.values(SHARE_MODE); - return (
= ({ } fetchSuggestions={fetchSuggestions} /> - - General Access - - - -
- - {selectedOption === SHARE_MODE.PUBLIC ? ( - - ) : ( - - )} - -
- setMenu(true)} - onChange={handleOptionClick} - disabled={isVisibilitySelectorDisabled} - > - {filteredOptions.map((option) => ( - - {option.charAt(0).toUpperCase() + option.slice(1)} - - ))} - - - {selectedOption === SHARE_MODE.PRIVATE ? options.PRIVATE : options.PUBLIC} - -
-
-
-
+ {selectedResource?.visibility !== 'published' && ( + <> + + General Access + + + +
+ + {selectedOption === SHARE_MODE.PUBLIC ? ( + + ) : ( + + )} + +
+ setMenu(true)} + onChange={handleOptionClick} + disabled={isVisibilitySelectorDisabled} + > + {Object.values(SHARE_MODE).map((option) => ( + + {option.charAt(0).toUpperCase() + option.slice(1)} + + ))} + + + {selectedOption === SHARE_MODE.PRIVATE ? options.PRIVATE : options.PUBLIC} + +
+
+
+
+ + )} Date: Tue, 17 Dec 2024 17:46:57 +0530 Subject: [PATCH 3/3] feat(delete): add delelte action Signed-off-by: Sudhanshu Dasgupta --- src/custom/CatalogDetail/ActionButton.tsx | 28 +++++++++++++++++++++-- src/custom/CatalogDetail/LeftPanel.tsx | 8 ++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/custom/CatalogDetail/ActionButton.tsx b/src/custom/CatalogDetail/ActionButton.tsx index 3be499b93..d1fa71490 100644 --- a/src/custom/CatalogDetail/ActionButton.tsx +++ b/src/custom/CatalogDetail/ActionButton.tsx @@ -1,6 +1,13 @@ import React from 'react'; import { CircularProgress } from '../../base'; -import { CopyIcon, EditIcon, KanvasIcon, PublishIcon, ShareLineIcon } from '../../icons'; +import { + CopyIcon, + DeleteIcon, + EditIcon, + KanvasIcon, + PublishIcon, + ShareLineIcon +} from '../../icons'; import Download from '../../icons/Download/Download'; import { charcoal, useTheme } from '../../theme'; import { Pattern } from '../CustomCatalog/CustomCard'; @@ -23,6 +30,8 @@ interface ActionButtonsProps { handleInfoClick?: () => void; showShareAction?: boolean; handleShare: () => void; + showDeleteAction?: boolean; + handleDelete: () => void; } const ActionButtons: React.FC = ({ @@ -39,7 +48,9 @@ const ActionButtons: React.FC = ({ showInfoAction, handleInfoClick, showShareAction, - handleShare + handleShare, + showDeleteAction, + handleDelete }) => { const cleanedType = type.replace('my-', '').replace(/s$/, ''); const theme = useTheme(); @@ -155,7 +166,20 @@ const ActionButtons: React.FC = ({ Share )} + {showDeleteAction && ( + + + Delete + + )}
+ {showUnpublishAction && ( void; showShareAction?: boolean; handleShare: () => void; + showDeleteAction?: boolean; + handleDelete: () => void; } const LeftPanel: React.FC = ({ @@ -48,7 +50,9 @@ const LeftPanel: React.FC = ({ showInfoAction = false, handleInfoClick, showShareAction = false, - handleShare + handleShare, + showDeleteAction = false, + handleDelete }) => { const theme = useTheme(); @@ -95,6 +99,8 @@ const LeftPanel: React.FC = ({ handleInfoClick={handleInfoClick} showShareAction={showShareAction} handleShare={handleShare} + showDeleteAction={showDeleteAction} + handleDelete={handleDelete} /> {showTechnologies && (