Skip to content
Snippets Groups Projects
Unverified Commit d378dc3a authored by github-automation-metabase's avatar github-automation-metabase Committed by GitHub
Browse files

fix(sdk): Fix interactive dashboard scroll in fullscreen mode (#49366) (#49427)


* Fix scroll for EditableDashboard in fullscreen mode

* Fix scroll for InteractiveDashboard in fullscreen mode

* Display fullscreen control to dashboards by default

* Fix issue with public shared questions empty footer

Co-authored-by: default avatarDenis Berezin <denis.berezin@metabase.com>
parent 6c4e2204
Branches
Tags
No related merge requests found
......@@ -35,6 +35,18 @@ You can embed a dashboard using the one of the dashboard components:
_\* Not available for `StaticDashboard`._
By default, dashboard components take full page height (100vh). You can override this with custom styles passed via `style` or `className` props.
```tsx
<EditableDashboard
style={{
height: 800,
minHeight: "auto",
}}
dashboardId={dashboardId}
/>
```
## Example embedded dashboard with `InteractiveDashboard` component
```typescript
......
......@@ -55,9 +55,7 @@ describeSDK("scenarios > embedding-sdk > static-dashboard", () => {
cy.intercept("POST", "/api/dashboard/*/dashcard/*/card/*/query").as(
"dashcardQuery",
);
});
it("should show dashboard content", () => {
cy.get("@dashboardId").then(dashboardId => {
visitFullAppEmbeddingUrl({
url: EMBEDDING_SDK_STORY_HOST,
......@@ -78,15 +76,23 @@ describeSDK("scenarios > embedding-sdk > static-dashboard", () => {
expect(response?.statusCode).to.equal(200);
});
cy.get("#metabase-sdk-root")
.should("be.visible")
.within(() => {
cy.findByText("Embedding Sdk Test Dashboard").should("be.visible"); // dashboard title
cy.get("#metabase-sdk-root").should("be.visible");
});
cy.findByText("Text text card").should("be.visible"); // text card content
it("should show dashboard content", () => {
cy.get("#metabase-sdk-root").within(() => {
cy.findByText("Embedding Sdk Test Dashboard").should("be.visible"); // dashboard title
cy.wait("@dashcardQuery");
cy.findByText("Test question card").should("be.visible"); // question card content
});
cy.findByText("Text text card").should("be.visible"); // text card content
cy.wait("@dashcardQuery");
cy.findByText("Test question card").should("be.visible"); // question card content
});
});
it("should show fullscreen mode control by default", () => {
cy.get("#metabase-sdk-root").within(() => {
cy.icon("expand").should("be.visible"); // enter full screen control
});
});
});
......@@ -9,4 +9,5 @@ export const StyledPublicComponentWrapper = styled(PublicComponentWrapper)`
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
overflow: auto;
`;
import styled from "@emotion/styled";
import { PublicComponentWrapper } from "embedding-sdk/components/private/PublicComponentWrapper";
export const StyledPublicComponentWrapper = styled(PublicComponentWrapper)`
min-height: 100vh;
background: var(--mb-color-bg-dashboard);
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
overflow: auto;
`;
import type { CSSProperties } from "react";
import _ from "underscore";
import type { SdkPluginsConfig } from "embedding-sdk";
......@@ -5,8 +6,8 @@ import { InteractiveAdHocQuestion } from "embedding-sdk/components/private/Inter
import {
SdkError,
SdkLoader,
withPublicComponentWrapper,
} from "embedding-sdk/components/private/PublicComponentWrapper";
import { StyledPublicComponentWrapper } from "embedding-sdk/components/public/InteractiveDashboard/InteractiveDashboard.styled";
import { useCommonDashboardParams } from "embedding-sdk/components/public/InteractiveDashboard/use-common-dashboard-params";
import {
type SdkDashboardDisplayProps,
......@@ -18,7 +19,6 @@ import { useEmbedFont } from "metabase/dashboard/hooks/use-embed-font";
import { useValidatedEntityId } from "metabase/lib/entity-id/hooks/use-validated-entity-id";
import { PublicOrEmbeddedDashboard } from "metabase/public/containers/PublicOrEmbeddedDashboard/PublicOrEmbeddedDashboard";
import type { PublicOrEmbeddedDashboardEventHandlersProps } from "metabase/public/containers/PublicOrEmbeddedDashboard/types";
import { Box } from "metabase/ui";
import { InteractiveDashboardProvider } from "./context";
......@@ -26,6 +26,7 @@ export type InteractiveDashboardProps = {
questionHeight?: number;
plugins?: SdkPluginsConfig;
className?: string;
style?: CSSProperties;
} & SdkDashboardDisplayProps &
PublicOrEmbeddedDashboardEventHandlersProps;
......@@ -41,6 +42,7 @@ const InteractiveDashboardInner = ({
onLoad,
onLoadWithoutCards,
className,
style,
}: InteractiveDashboardProps) => {
const {
displayOptions,
......@@ -71,7 +73,7 @@ const InteractiveDashboardInner = ({
const { font } = useEmbedFont();
return (
<Box w="100%" h="100%" ref={ref} className={className}>
<StyledPublicComponentWrapper className={className} style={style} ref={ref}>
{adhocQuestionUrl ? (
<InteractiveAdHocQuestion
questionPath={adhocQuestionUrl}
......@@ -111,26 +113,26 @@ const InteractiveDashboardInner = ({
/>
</InteractiveDashboardProvider>
)}
</Box>
</StyledPublicComponentWrapper>
);
};
export const InteractiveDashboard =
withPublicComponentWrapper<InteractiveDashboardProps>(
({ dashboardId, ...rest }) => {
const { id, isLoading } = useValidatedEntityId({
type: "dashboard",
id: dashboardId,
});
export const InteractiveDashboard = ({
dashboardId,
...rest
}: InteractiveDashboardProps) => {
const { id, isLoading } = useValidatedEntityId({
type: "dashboard",
id: dashboardId,
});
if (isLoading) {
return <SdkLoader />;
}
if (isLoading) {
return <SdkLoader />;
}
if (!id) {
return <SdkError message="ID not found" />;
}
if (!id) {
return <SdkError message="ID not found" />;
}
return <InteractiveDashboardInner dashboardId={id} {...rest} />;
},
);
return <InteractiveDashboardInner dashboardId={id} {...rest} />;
};
......@@ -127,7 +127,7 @@ export const EmbedFrame = ({
.filter(Boolean)
.join(",");
const showFooter = hasEmbedBranding || (downloadsEnabled && actionButtons);
const showFooter = hasEmbedBranding || downloadsEnabled || actionButtons;
const finalName = titled ? name : null;
......
......@@ -58,15 +58,16 @@ export function PublicOrEmbeddedQuestionView({
downloadsEnabled,
}: PublicOrEmbeddedQuestionViewProps) {
const question = new Question(card, metadata);
const actionButtons = result && downloadsEnabled && (
<QueryDownloadWidget
className={cx(CS.m1, CS.textMediumHover)}
question={question}
result={result}
uuid={uuid}
token={token}
/>
);
const actionButtons =
result && downloadsEnabled ? (
<QueryDownloadWidget
className={cx(CS.m1, CS.textMediumHover)}
question={question}
result={result}
uuid={uuid}
token={token}
/>
) : null;
return (
<EmbedFrame
......@@ -85,6 +86,7 @@ export function PublicOrEmbeddedQuestionView({
hide_parameters={hide_parameters}
theme={theme}
titled={titled}
downloadsEnabled={downloadsEnabled}
>
<LoadingAndErrorWrapper
className={CS.flexFull}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment