From c0ef832c8cd117f83680e0ff01774b6c4261d70d Mon Sep 17 00:00:00 2001 From: Alexander Polyankin <alexander.polyankin@metabase.com> Date: Wed, 15 Jun 2022 11:51:07 +0300 Subject: [PATCH] Show disabled menu item to show visualization (#23339) --- .../components/ActionMenu/ActionMenu.tsx | 13 ++++++------ .../PinnedItemOverview/PinnedItemOverview.tsx | 4 ++-- .../PinnedQuestionCard/PinnedQuestionCard.tsx | 4 ++-- frontend/src/metabase/collections/utils.ts | 6 ++---- .../src/metabase/components/EntityItem.jsx | 11 ++++++---- .../src/metabase/components/EntityMenu.jsx | 1 + .../metabase/components/EntityMenuItem.jsx | 21 ++++++++++++++----- .../components/EntityMenuItem.styled.jsx | 10 ++++----- 8 files changed, 41 insertions(+), 29 deletions(-) diff --git a/frontend/src/metabase/collections/components/ActionMenu/ActionMenu.tsx b/frontend/src/metabase/collections/components/ActionMenu/ActionMenu.tsx index ecfcf20b301..49f37a2cc13 100644 --- a/frontend/src/metabase/collections/components/ActionMenu/ActionMenu.tsx +++ b/frontend/src/metabase/collections/components/ActionMenu/ActionMenu.tsx @@ -5,6 +5,7 @@ import { ANALYTICS_CONTEXT } from "metabase/collections/constants"; import { hasRequiredParameters, isItemPinned, + isPreviewShown, isPreviewEnabled, Item, } from "metabase/collections/utils"; @@ -50,11 +51,8 @@ function ActionMenu({ deleteBookmark, }: ActionMenuProps) { const isBookmarked = bookmarks && getIsBookmarked(item, bookmarks); - const canTogglePreview = - isItemPinned(item) && - hasRequiredParameters(item) && - collection.can_write && - item.setCollectionPreview; + const isPreviewOptionShown = + isItemPinned(item) && collection.can_write && item.setCollectionPreview; const handlePin = useCallback(() => { item.setPinned(!isItemPinned(item)); @@ -89,7 +87,8 @@ function ActionMenu({ className={className} item={item} isBookmarked={isBookmarked} - isPreviewEnabled={isPreviewEnabled(item)} + isPreviewShown={isPreviewShown(item)} + isPreviewAvailable={hasRequiredParameters(item)} onPin={collection.can_write ? handlePin : null} onMove={collection.can_write && item.setCollection ? handleMove : null} onCopy={item.copy ? handleCopy : null} @@ -97,7 +96,7 @@ function ActionMenu({ collection.can_write && item.setArchived ? handleArchive : null } onToggleBookmark={handleToggleBookmark} - onTogglePreview={canTogglePreview ? handleTogglePreview : null} + onTogglePreview={isPreviewOptionShown ? handleTogglePreview : null} analyticsContext={ANALYTICS_CONTEXT} /> </EventSandbox> diff --git a/frontend/src/metabase/collections/components/PinnedItemOverview/PinnedItemOverview.tsx b/frontend/src/metabase/collections/components/PinnedItemOverview/PinnedItemOverview.tsx index 3a00aa81667..f2e4d48960d 100644 --- a/frontend/src/metabase/collections/components/PinnedItemOverview/PinnedItemOverview.tsx +++ b/frontend/src/metabase/collections/components/PinnedItemOverview/PinnedItemOverview.tsx @@ -11,7 +11,7 @@ import PinnedItemSortDropTarget from "metabase/collections/components/PinnedItem import { Item, isRootCollection, - isPreviewable, + isPreviewShown, } from "metabase/collections/utils"; import PinDropZone from "metabase/collections/components/PinDropZone"; import ItemDragSource from "metabase/containers/dnd/ItemDragSource"; @@ -50,7 +50,7 @@ function PinnedItemOverview({ dashboard: dashboardItems = [], dataset: dataModelItems = [], } = _.groupBy(sortedItems, "model"); - const cardGroups = _.partition(cardItems, isPreviewable); + const cardGroups = _.partition(cardItems, isPreviewShown); return items.length === 0 ? ( <Container> diff --git a/frontend/src/metabase/collections/components/PinnedQuestionCard/PinnedQuestionCard.tsx b/frontend/src/metabase/collections/components/PinnedQuestionCard/PinnedQuestionCard.tsx index 5035af01e3a..339b05aecac 100644 --- a/frontend/src/metabase/collections/components/PinnedQuestionCard/PinnedQuestionCard.tsx +++ b/frontend/src/metabase/collections/components/PinnedQuestionCard/PinnedQuestionCard.tsx @@ -2,7 +2,7 @@ import React from "react"; import { t } from "ttag"; import { hasRequiredParameters, - isPreviewable, + isPreviewShown, Item, } from "metabase/collections/utils"; import Visualization from "metabase/visualizations/components/Visualization"; @@ -37,7 +37,7 @@ const PinnedQuestionCard = ({ onCreateBookmark, onDeleteBookmark, }: PinnedQuestionCardProps): JSX.Element => { - const isPreview = isPreviewable(item); + const isPreview = isPreviewShown(item); return ( <CardRoot to={item.getUrl()} isPreview={isPreview}> diff --git a/frontend/src/metabase/collections/utils.ts b/frontend/src/metabase/collections/utils.ts index 714379f251a..1207debd685 100644 --- a/frontend/src/metabase/collections/utils.ts +++ b/frontend/src/metabase/collections/utils.ts @@ -1,7 +1,5 @@ import { t } from "ttag"; -import _ from "underscore"; - -import { Collection, CollectionId } from "metabase-types/api"; +import { Collection } from "metabase-types/api"; export type Item = { id: number; @@ -82,7 +80,7 @@ export function isItemPinned(item: Item) { return item.collection_position != null; } -export function isPreviewable(item: Item) { +export function isPreviewShown(item: Item) { return isPreviewEnabled(item) && hasRequiredParameters(item); } diff --git a/frontend/src/metabase/components/EntityItem.jsx b/frontend/src/metabase/components/EntityItem.jsx index 8aa232733d5..23cb676342e 100644 --- a/frontend/src/metabase/components/EntityItem.jsx +++ b/frontend/src/metabase/components/EntityItem.jsx @@ -85,7 +85,8 @@ function EntityItemName({ name, variant }) { function EntityItemMenu({ item, isBookmarked, - isPreviewEnabled, + isPreviewShown, + isPreviewAvailable, onPin, onMove, onCopy, @@ -108,12 +109,13 @@ function EntityItemMenu({ event: `${analyticsContext};Entity Item;Pin Item;${item.model}`, }, onTogglePreview && { - title: isPreviewEnabled + title: isPreviewShown ? t`Don’t show visualization` : t`Show visualization`, - icon: isPreviewEnabled ? "eye_crossed_out" : "eye", + icon: isPreviewShown ? "eye_crossed_out" : "eye", action: onTogglePreview, event: `${analyticsContext};Entity Item;Preview Item;${item.model}`, + disabled: !isPreviewAvailable, }, onMove && { title: t`Move`, @@ -144,7 +146,8 @@ function EntityItemMenu({ item.model, isPinned, isBookmarked, - isPreviewEnabled, + isPreviewShown, + isPreviewAvailable, showPinnedAction, onPin, onMove, diff --git a/frontend/src/metabase/components/EntityMenu.jsx b/frontend/src/metabase/components/EntityMenu.jsx index c1cfd4fbac6..bbcc8092a71 100644 --- a/frontend/src/metabase/components/EntityMenu.jsx +++ b/frontend/src/metabase/components/EntityMenu.jsx @@ -140,6 +140,7 @@ class EntityMenu extends Component { } event={item.event && item.event} link={item.link} + disabled={item.disabled} onClose={() => { this.toggleMenu(); item?.onClose?.(); diff --git a/frontend/src/metabase/components/EntityMenuItem.jsx b/frontend/src/metabase/components/EntityMenuItem.jsx index d6836e11bbf..fcbef50c70b 100644 --- a/frontend/src/metabase/components/EntityMenuItem.jsx +++ b/frontend/src/metabase/components/EntityMenuItem.jsx @@ -5,11 +5,19 @@ import { Link } from "react-router"; import Icon from "metabase/components/Icon"; import { Item, StyledExternalLink } from "./EntityMenuItem.styled"; -const LinkMenuItem = ({ children, link, onClose, event, externalLink }) => +const LinkMenuItem = ({ + children, + link, + onClose, + event, + externalLink, + disabled, +}) => externalLink ? ( <StyledExternalLink href={link} target="_blank" + disabled={disabled} onClick={onClose} data-metabase-event={event} > @@ -18,6 +26,7 @@ const LinkMenuItem = ({ children, link, onClose, event, externalLink }) => ) : ( <Link to={link} + disabled={disabled} onClick={onClose} data-metabase-event={event} className="block" @@ -26,8 +35,8 @@ const LinkMenuItem = ({ children, link, onClose, event, externalLink }) => </Link> ); -const ActionMenuItem = ({ children, action, event }) => ( - <div onClick={action} data-metabase-event={event}> +const ActionMenuItem = ({ children, action, event, disabled }) => ( + <div onClick={!disabled ? action : undefined} data-metabase-event={event}> {children} </div> ); @@ -40,6 +49,7 @@ const EntityMenuItem = ({ onClose, event, externalLink, + disabled, }) => { if (link && action) { console.warn( @@ -49,7 +59,7 @@ const EntityMenuItem = ({ } const content = ( - <Item> + <Item disabled={disabled}> {icon && <Icon name={icon} mr={1} />} <span className="text-bold">{title}</span> </Item> @@ -60,6 +70,7 @@ const EntityMenuItem = ({ <LinkMenuItem link={link} externalLink={externalLink} + disabled={disabled} onClose={onClose} event={event} > @@ -69,7 +80,7 @@ const EntityMenuItem = ({ } if (action) { return ( - <ActionMenuItem action={action} event={event}> + <ActionMenuItem action={action} event={event} disabled={disabled}> {content} </ActionMenuItem> ); diff --git a/frontend/src/metabase/components/EntityMenuItem.styled.jsx b/frontend/src/metabase/components/EntityMenuItem.styled.jsx index 33ca602e79a..040074816ce 100644 --- a/frontend/src/metabase/components/EntityMenuItem.styled.jsx +++ b/frontend/src/metabase/components/EntityMenuItem.styled.jsx @@ -5,21 +5,21 @@ import { color } from "metabase/lib/colors"; export const Item = styled.div` display: flex; -align-items: center; - cursor: pointer; - color: ${color("text-medium")}; + align-items: center; + cursor: ${props => (props.disabled ? "not-allowed" : "pointer")}; + color: ${props => color(props.disabled ? "text-light" : "text-medium")}; padding: 0.85em 1.45em; text-decoration: none; transition: all 300ms linear; :hover { - color: ${color("brand")}; + color: ${props => !props.disabled && color("brand")}; } > .Icon { color: ${color("text-light")}; margin-right: 0.65em; } :hover > .Icon { - color: ${color("brand")}; + color: ${props => !props.disabled && color("brand")}; transition: all 300ms linear; }, /* icon specific tweaks -- GitLab