Skip to content
Snippets Groups Projects
Unverified Commit 056b6a39 authored by Oisin Coveney's avatar Oisin Coveney Committed by GitHub
Browse files

Convert QueryBuilder action buttons to Mantine (#46631)

parent abacb880
No related branches found
No related tags found
No related merge requests found
Showing
with 173 additions and 95 deletions
import { type Ref, forwardRef, type HTMLAttributes } from "react";
import {
ActionIcon,
Center,
Icon,
Tooltip,
type ActionIconProps,
type IconName,
} from "metabase/ui";
export type ViewFooterButtonProps = {
icon: IconName;
tooltipLabel?: string | null;
} & ActionIconProps &
HTMLAttributes<HTMLButtonElement>;
export const ViewFooterButton = forwardRef(function _ViewFooterButton(
{ icon, tooltipLabel, ...actionIconProps }: ViewFooterButtonProps,
ref: Ref<HTMLButtonElement>,
) {
return (
<Tooltip label={tooltipLabel}>
<Center>
<ActionIcon ref={ref} variant="viewFooter" {...actionIconProps}>
<Icon size={18} name={icon} />
</ActionIcon>
</Center>
</Tooltip>
);
});
export * from "./ViewFooterButton";
......@@ -11,6 +11,7 @@ import {
} from "metabase/dashboard/components/PublicLinkPopover";
import { useSelector } from "metabase/lib/redux";
import { ResourceEmbedButton } from "metabase/public/components/ResourceEmbedButton";
import { ViewFooterSharingButton } from "metabase/query_builder/components/view/ViewFooterSharingButton";
import { getSetting } from "metabase/selectors/settings";
import { Menu, Title, Text, Stack, Center, Icon } from "metabase/ui";
......@@ -31,9 +32,12 @@ export const AdminEmbedMenu = ({
getSetting(state, "enable-embedding"),
);
const target = (
<ResourceEmbedButton hasBackground={resourceType === "dashboard"} />
);
const target =
resourceType === "dashboard" ? (
<ResourceEmbedButton hasBackground={true} />
) : (
<ViewFooterSharingButton />
);
if (menuMode === "public-link-popover") {
return resourceType === "dashboard" ? (
......
......@@ -8,6 +8,7 @@ import {
} from "metabase/dashboard/components/PublicLinkPopover";
import { useSelector } from "metabase/lib/redux";
import { ResourceEmbedButton } from "metabase/public/components/ResourceEmbedButton";
import { ViewFooterSharingButton } from "metabase/query_builder/components/view/ViewFooterSharingButton";
import { getSetting } from "metabase/selectors/settings";
export const NonAdminEmbedMenu = ({
......@@ -27,14 +28,21 @@ export const NonAdminEmbedMenu = ({
const isDisabled = !isPublicSharingEnabled || !hasPublicLink;
const target = (
<ResourceEmbedButton
hasBackground={resourceType === "dashboard"}
onClick={() => setIsOpen(!isOpen)}
disabled={isDisabled}
tooltip={isDisabled ? tooltipLabel : null}
/>
);
const target =
resourceType === "dashboard" ? (
<ResourceEmbedButton
hasBackground={true}
onClick={() => setIsOpen(!isOpen)}
disabled={isDisabled}
tooltip={isDisabled ? tooltipLabel : null}
/>
) : (
<ViewFooterSharingButton
onClick={() => setIsOpen(!isOpen)}
disabled={isDisabled}
tooltipLabel={isDisabled ? tooltipLabel : null}
/>
);
return resourceType === "dashboard" ? (
<DashboardPublicLinkPopover
......
import { useState } from "react";
import { t } from "ttag";
import { ViewFooterButton } from "metabase/components/ViewFooterButton";
import { PLUGIN_FEATURE_LEVEL_PERMISSIONS } from "metabase/plugins";
import { Flex, Popover, Tooltip } from "metabase/ui";
import { Flex, Popover } from "metabase/ui";
import type Question from "metabase-lib/v1/Question";
import type {
DashboardId,
......@@ -14,8 +15,6 @@ import type {
import { QueryDownloadPopover } from "../QueryDownloadPopover";
import { useDownloadData } from "../QueryDownloadPopover/use-download-data";
import { DownloadIcon } from "./QueryDownloadWidget.styled";
interface QueryDownloadWidgetProps {
className?: string;
question: Question;
......@@ -53,14 +52,12 @@ const QueryDownloadWidget = ({
<Popover opened={isPopoverOpen} onClose={() => setIsPopoverOpen(false)}>
<Popover.Target>
<Flex className={className}>
<Tooltip label={t`Download full results`}>
<DownloadIcon
onClick={() => setIsPopoverOpen(!isPopoverOpen)}
name="download"
size={20}
data-testid="download-button"
/>
</Tooltip>
<ViewFooterButton
icon="download"
data-testid="download-button"
tooltipLabel={t`Download full results`}
onClick={() => setIsPopoverOpen(!isPopoverOpen)}
/>
</Flex>
</Popover.Target>
<Popover.Dropdown p="0.75rem">
......
......@@ -4,13 +4,12 @@ import { createRef, Component } from "react";
import { t } from "ttag";
import Popover from "metabase/components/Popover";
import { ViewFooterButton } from "metabase/components/ViewFooterButton";
import CS from "metabase/css/core/index.css";
import { Icon } from "metabase/ui";
import { AlertListPopoverContent } from "../AlertListPopoverContent";
import { AlertIcon } from "./QuestionAlertWidget.styled";
export default class QuestionAlertWidget extends Component {
state = {
isOpen: false,
......@@ -69,12 +68,11 @@ export default class QuestionAlertWidget extends Component {
);
} else {
return (
<AlertIcon
name="bell"
tooltip={t`Get alerts`}
size={20}
className={className}
<ViewFooterButton
icon="bell"
tooltipLabel={t`Get alerts`}
onClick={onCreateAlert}
className={className}
/>
);
}
......
import { t } from "ttag";
import { TimelineIcon } from "./QuestionTimelineWidget.styled";
import { ViewFooterButton } from "metabase/components/ViewFooterButton";
export interface QuestionTimelineWidgetProps {
className?: string;
......@@ -16,11 +16,11 @@ const QuestionTimelineWidget = ({
onCloseTimelines,
}: QuestionTimelineWidgetProps): JSX.Element => {
return (
<TimelineIcon
className={className}
name="calendar"
tooltip={t`Events`}
<ViewFooterButton
icon="calendar"
tooltipLabel={t`Events`}
onClick={isShowingTimelineSidebar ? onCloseTimelines : onOpenTimelines}
className={className}
/>
);
};
......
......@@ -5,9 +5,10 @@ import { t } from "ttag";
import ButtonBar from "metabase/components/ButtonBar";
import CS from "metabase/css/core/index.css";
import { EmbedMenu } from "metabase/dashboard/components/EmbedMenu";
import { ResourceEmbedButton } from "metabase/public/components/ResourceEmbedButton";
import QueryDownloadWidget from "metabase/query_builder/components/QueryDownloadWidget";
import { ViewFooterSharingButton } from "metabase/query_builder/components/view/ViewFooterSharingButton";
import { MODAL_TYPES } from "metabase/query_builder/constants";
import { Group } from "metabase/ui";
import * as Lib from "metabase-lib";
import { ExecutionTime } from "./ExecutionTime";
......@@ -112,68 +113,64 @@ const ViewFooter = ({
ExecutionTime.shouldRender({ result }) && (
<ExecutionTime key="execution_time" time={result.running_time} />
),
QuestionLastUpdated.shouldRender({ result }) && (
<QuestionLastUpdated
key="last-updated"
className={cx(CS.hide, CS.smShow)}
result={result}
/>
),
QueryDownloadWidget.shouldRender({ result }) && (
<QueryDownloadWidget
key="download"
className={cx(CS.hide, CS.smShow)}
question={question}
result={result}
visualizationSettings={visualizationSettings}
dashcardId={question.card().dashcardId}
dashboardId={question.card().dashboardId}
/>
),
QuestionAlertWidget.shouldRender({
question,
visualizationSettings,
}) && (
<QuestionAlertWidget
key="alerts"
className={cx(CS.hide, CS.smShow)}
canManageSubscriptions={canManageSubscriptions}
question={question}
questionAlerts={questionAlerts}
onCreateAlert={() =>
question.isSaved()
? onOpenModal("create-alert")
: onOpenModal("save-question-before-alert")
}
/>
),
type === "question" &&
!question.isArchived() &&
(question.isSaved() ? (
<EmbedMenu
key="embed"
resource={question}
resourceType="question"
hasPublicLink={!!question.publicUUID()}
onModalOpen={() => onOpenModal(MODAL_TYPES.EMBED)}
<Group key="button-group" spacing="sm" noWrap>
{QuestionLastUpdated.shouldRender({ result }) && (
<QuestionLastUpdated
className={cx(CS.hide, CS.smShow)}
result={result}
/>
)}
{QueryDownloadWidget.shouldRender({ result }) && (
<QueryDownloadWidget
className={cx(CS.hide, CS.smShow)}
question={question}
result={result}
visualizationSettings={visualizationSettings}
dashcardId={question.card().dashcardId}
dashboardId={question.card().dashboardId}
/>
) : (
<ResourceEmbedButton
hasBackground={false}
onClick={() =>
onOpenModal(MODAL_TYPES.SAVE_QUESTION_BEFORE_EMBED)
)}
{QuestionAlertWidget.shouldRender({
question,
visualizationSettings,
}) && (
<QuestionAlertWidget
className={cx(CS.hide, CS.smShow)}
canManageSubscriptions={canManageSubscriptions}
question={question}
questionAlerts={questionAlerts}
onCreateAlert={() =>
question.isSaved()
? onOpenModal(MODAL_TYPES.CREATE_ALERT)
: onOpenModal(MODAL_TYPES.SAVE_QUESTION_BEFORE_ALERT)
}
/>
)),
QuestionTimelineWidget.shouldRender({ isTimeseries }) && (
<QuestionTimelineWidget
key="timelines"
className={cx(CS.hide, CS.smShow)}
isShowingTimelineSidebar={isShowingTimelineSidebar}
onOpenTimelines={onOpenTimelines}
onCloseTimelines={onCloseTimelines}
/>
),
)}
{type === "question" &&
!question.isArchived() &&
(question.isSaved() ? (
<EmbedMenu
resource={question}
resourceType="question"
hasPublicLink={!!question.publicUUID()}
onModalOpen={() => onOpenModal(MODAL_TYPES.EMBED)}
/>
) : (
<ViewFooterSharingButton
onClick={() =>
onOpenModal(MODAL_TYPES.SAVE_QUESTION_BEFORE_EMBED)
}
/>
))}
{QuestionTimelineWidget.shouldRender({ isTimeseries }) && (
<QuestionTimelineWidget
className={cx(CS.hide, CS.smShow)}
isShowingTimelineSidebar={isShowingTimelineSidebar}
onOpenTimelines={onOpenTimelines}
onCloseTimelines={onCloseTimelines}
/>
)}
</Group>,
]}
/>
</ViewFooterRoot>
......
import { t } from "ttag";
import {
ViewFooterButton,
type ViewFooterButtonProps,
} from "metabase/components/ViewFooterButton";
import { useSelector } from "metabase/lib/redux";
import { getSetting } from "metabase/selectors/settings";
export const ViewFooterSharingButton = (
viewFooterButtonProps: Omit<ViewFooterButtonProps, "icon" | "data-testid">,
) => {
const isPublicSharingEnabled = useSelector(state =>
getSetting(state, "enable-public-sharing"),
);
const tooltipLabel =
viewFooterButtonProps.tooltipLabel ??
(isPublicSharingEnabled ? t`Sharing` : t`Embedding`);
return (
<ViewFooterButton
icon="share"
data-testid="resource-embed-button"
tooltipLabel={tooltipLabel}
{...viewFooterButtonProps}
/>
);
};
......@@ -23,6 +23,7 @@ import {
} from "metabase/query_builder/components/view/ViewHeader/components";
import { canExploreResults } from "metabase/query_builder/components/view/ViewHeader/utils";
import type { QueryModalType } from "metabase/query_builder/constants";
import { MODAL_TYPES } from "metabase/query_builder/constants";
import { Tooltip } from "metabase/ui";
import * as Lib from "metabase-lib";
import type Question from "metabase-lib/v1/Question";
......@@ -235,7 +236,7 @@ export function ViewTitleHeaderRightSide({
onClick={event => {
event.preventDefault();
if (!isSaveDisabled) {
onOpenModal("save");
onOpenModal(MODAL_TYPES.SAVE);
}
}}
>
......
......@@ -44,6 +44,18 @@ export const getActionIconOverrides =
},
},
}),
viewFooter: theme => ({
root: {
color: theme.fn.themeColor("text-medium"),
"&:hover": {
color: theme.fn.themeColor("brand"),
},
"&:disabled, &[data-disabled]": {
color: theme.fn.themeColor("text-light"),
backgroundColor: "transparent",
},
},
}),
},
},
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment