From b7cac72c3cd97f57aeac225c2645a32078756bcf Mon Sep 17 00:00:00 2001 From: Alexander Polyankin <alexander.polyankin@metabase.com> Date: Tue, 4 Jan 2022 23:50:13 +0300 Subject: [PATCH] Add storybook for database statuses (#19537) --- .storybook/preview.js | 2 ++ .../api/database.ts} | 13 +++++--- frontend/src/metabase-types/api/user.ts | 8 +++++ .../TextInput/TextInput.stories.jsx | 14 -------- .../DatabaseStatus/DatabaseStatus.tsx | 3 +- .../DatabaseStatus.unit.spec.tsx | 23 ++++--------- .../DatabaseStatusLarge.stories.tsx | 32 +++++++++++++++++++ .../DatabaseStatusLarge.tsx | 18 ++++++++--- .../DatabaseStatusLarge.unit.spec.tsx | 30 +++++++---------- .../DatabaseStatusSmall.stories.tsx | 29 +++++++++++++++++ .../DatabaseStatusSmall.styled.tsx | 2 +- .../DatabaseStatusSmall.tsx | 2 +- .../DatabaseStatusSmall.unit.spec.tsx | 22 ++++--------- .../DatabaseStatus/DatabaseStatus.tsx | 2 +- 14 files changed, 123 insertions(+), 77 deletions(-) rename frontend/src/{metabase/status/types.ts => metabase-types/api/database.ts} (52%) create mode 100644 frontend/src/metabase-types/api/user.ts delete mode 100644 frontend/src/metabase/components/TextInput/TextInput.stories.jsx create mode 100644 frontend/src/metabase/status/components/DatabaseStatusLarge/DatabaseStatusLarge.stories.tsx create mode 100644 frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.stories.tsx diff --git a/.storybook/preview.js b/.storybook/preview.js index f089c7f9d53..ec28b3af9ed 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -1,3 +1,5 @@ +import "metabase/css/index.css"; + export const parameters = { actions: { argTypesRegex: "^on[A-Z].*" }, controls: { diff --git a/frontend/src/metabase/status/types.ts b/frontend/src/metabase-types/api/database.ts similarity index 52% rename from frontend/src/metabase/status/types.ts rename to frontend/src/metabase-types/api/database.ts index a08bd6e2f4a..f88eb0f4917 100644 --- a/frontend/src/metabase/status/types.ts +++ b/frontend/src/metabase-types/api/database.ts @@ -1,9 +1,5 @@ export type InitialSyncStatus = "incomplete" | "complete" | "aborted"; -export interface User { - id: number; -} - export interface Database { id: number; name: string; @@ -11,3 +7,12 @@ export interface Database { creator_id?: number; initial_sync_status: InitialSyncStatus; } + +export const createDatabase = (opts?: Partial<Database>): Database => ({ + id: 1, + name: "Database", + is_sample: false, + creator_id: undefined, + initial_sync_status: "complete", + ...opts, +}); diff --git a/frontend/src/metabase-types/api/user.ts b/frontend/src/metabase-types/api/user.ts new file mode 100644 index 00000000000..3041f062a1a --- /dev/null +++ b/frontend/src/metabase-types/api/user.ts @@ -0,0 +1,8 @@ +export interface User { + id: number; +} + +export const createUser = (opts?: Partial<User>): User => ({ + id: 1, + ...opts, +}); diff --git a/frontend/src/metabase/components/TextInput/TextInput.stories.jsx b/frontend/src/metabase/components/TextInput/TextInput.stories.jsx deleted file mode 100644 index c2aa2a525aa..00000000000 --- a/frontend/src/metabase/components/TextInput/TextInput.stories.jsx +++ /dev/null @@ -1,14 +0,0 @@ -import React, { useState } from "react"; -import TextInput from "./TextInput"; - -export default { - title: "Components/TextInput", - component: TextInput, -}; - -export const Default = args => { - const [value, setValue] = useState(""); - return <TextInput {...args} value={value} onChange={setValue} />; -}; - -Default.args = { hasClearButton: false }; diff --git a/frontend/src/metabase/status/components/DatabaseStatus/DatabaseStatus.tsx b/frontend/src/metabase/status/components/DatabaseStatus/DatabaseStatus.tsx index 648c702d064..ca39fcfe10c 100644 --- a/frontend/src/metabase/status/components/DatabaseStatus/DatabaseStatus.tsx +++ b/frontend/src/metabase/status/components/DatabaseStatus/DatabaseStatus.tsx @@ -1,9 +1,10 @@ import React, { useState } from "react"; import { isSyncInProgress } from "metabase/lib/syncing"; +import { Database } from "metabase-types/api/database"; +import { User } from "metabase-types/api/user"; import useStatusVisibility from "../../hooks/use-status-visibility"; import DatabaseStatusLarge from "../DatabaseStatusLarge"; import DatabaseStatusSmall from "../DatabaseStatusSmall"; -import { Database, User } from "../../types"; export interface DatabaseStatusProps { user?: User; diff --git a/frontend/src/metabase/status/components/DatabaseStatus/DatabaseStatus.unit.spec.tsx b/frontend/src/metabase/status/components/DatabaseStatus/DatabaseStatus.unit.spec.tsx index fb55a9f8c66..4dc1b10dac0 100644 --- a/frontend/src/metabase/status/components/DatabaseStatus/DatabaseStatus.unit.spec.tsx +++ b/frontend/src/metabase/status/components/DatabaseStatus/DatabaseStatus.unit.spec.tsx @@ -1,14 +1,15 @@ import React from "react"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; +import { createDatabase } from "metabase-types/api/database"; +import { createUser } from "metabase-types/api/user"; import DatabaseStatus from "./DatabaseStatus"; -import { Database, User } from "../../types"; describe("DatabaseStatus", () => { it("should toggle between small and large versions", () => { - const user = getUser({ id: 1 }); + const user = createUser({ id: 1 }); const databases = [ - getDatabase({ creator_id: 1, initial_sync_status: "incomplete" }), + createDatabase({ creator_id: 1, initial_sync_status: "incomplete" }), ]; render(<DatabaseStatus user={user} databases={databases} />); @@ -28,9 +29,9 @@ describe("DatabaseStatus", () => { }); it("should not render when databases are created by another user", () => { - const user = getUser({ id: 1 }); + const user = createUser({ id: 1 }); const databases = [ - getDatabase({ creator_id: 2, initial_sync_status: "incomplete" }), + createDatabase({ creator_id: 2, initial_sync_status: "incomplete" }), ]; render(<DatabaseStatus user={user} databases={databases} />); @@ -38,15 +39,3 @@ describe("DatabaseStatus", () => { expect(screen.queryByText("Syncing…")).not.toBeInTheDocument(); }); }); - -const getUser = (opts?: Partial<User>): User => ({ - id: 1, -}); - -const getDatabase = (opts?: Partial<Database>): Database => ({ - id: 1, - name: "Our database", - is_sample: false, - initial_sync_status: "complete", - ...opts, -}); diff --git a/frontend/src/metabase/status/components/DatabaseStatusLarge/DatabaseStatusLarge.stories.tsx b/frontend/src/metabase/status/components/DatabaseStatusLarge/DatabaseStatusLarge.stories.tsx new file mode 100644 index 00000000000..b3b2c7bbc42 --- /dev/null +++ b/frontend/src/metabase/status/components/DatabaseStatusLarge/DatabaseStatusLarge.stories.tsx @@ -0,0 +1,32 @@ +import React from "react"; +import { ComponentStory } from "@storybook/react"; +import { createDatabase } from "metabase-types/api/database"; +import DatabaseStatusLarge from "./DatabaseStatusLarge"; + +export default { + title: "Status/DatabaseStatusLarge", + component: DatabaseStatusLarge, + argTypes: { onCollapse: { action: "onCollapse" } }, +}; + +const Template: ComponentStory<typeof DatabaseStatusLarge> = args => { + return <DatabaseStatusLarge {...args} />; +}; + +export const Incomplete = Template.bind({}); +Incomplete.args = { + databases: [createDatabase({ initial_sync_status: "incomplete" })], + isActive: true, +}; + +export const Complete = Template.bind({}); +Complete.args = { + databases: [createDatabase({ initial_sync_status: "complete" })], + isActive: true, +}; + +export const Aborted = Template.bind({}); +Aborted.args = { + databases: [createDatabase({ initial_sync_status: "aborted" })], + isActive: true, +}; diff --git a/frontend/src/metabase/status/components/DatabaseStatusLarge/DatabaseStatusLarge.tsx b/frontend/src/metabase/status/components/DatabaseStatusLarge/DatabaseStatusLarge.tsx index cfcfa1f80ed..9d7edba9224 100644 --- a/frontend/src/metabase/status/components/DatabaseStatusLarge/DatabaseStatusLarge.tsx +++ b/frontend/src/metabase/status/components/DatabaseStatusLarge/DatabaseStatusLarge.tsx @@ -5,7 +5,7 @@ import { } from "metabase/lib/syncing"; import React from "react"; import { t } from "ttag"; -import { Database } from "../../types"; +import { Database } from "metabase-types/api/database"; import Icon from "../../../components/Icon"; import { StatusCardRoot, @@ -26,11 +26,13 @@ import useStatusVisibility from "../../hooks/use-status-visibility"; export interface DatabaseStatusLargeProps { databases: Database[]; + isActive?: boolean; onCollapse?: () => void; } const DatabaseStatusLarge = ({ databases, + isActive, onCollapse, }: DatabaseStatusLargeProps): JSX.Element => { return ( @@ -43,7 +45,11 @@ const DatabaseStatusLarge = ({ </StatusHeader> <StatusBody> {databases.map(database => ( - <StatusCard key={database.id} database={database} /> + <StatusCard + key={database.id} + database={database} + isActive={isActive} + /> ))} </StatusBody> </StatusRoot> @@ -52,10 +58,14 @@ const DatabaseStatusLarge = ({ interface StatusCardProps { database: Database; + isActive?: boolean; } -const StatusCard = ({ database }: StatusCardProps): JSX.Element | null => { - const isVisible = useStatusVisibility(isSyncInProgress(database)); +const StatusCard = ({ + database, + isActive, +}: StatusCardProps): JSX.Element | null => { + const isVisible = useStatusVisibility(isActive || isSyncInProgress(database)); if (!isVisible) { return null; diff --git a/frontend/src/metabase/status/components/DatabaseStatusLarge/DatabaseStatusLarge.unit.spec.tsx b/frontend/src/metabase/status/components/DatabaseStatusLarge/DatabaseStatusLarge.unit.spec.tsx index d1358150d04..285ee205ed1 100644 --- a/frontend/src/metabase/status/components/DatabaseStatusLarge/DatabaseStatusLarge.unit.spec.tsx +++ b/frontend/src/metabase/status/components/DatabaseStatusLarge/DatabaseStatusLarge.unit.spec.tsx @@ -1,15 +1,15 @@ import React from "react"; import { render, screen } from "@testing-library/react"; +import { createDatabase } from "metabase-types/api/database"; import DatabaseStatusLarge from "./DatabaseStatusLarge"; -import { Database } from "../../types"; describe("DatabaseStatusLarge", () => { it("should render in-progress status", () => { const databases = [ - getDatabase({ + createDatabase({ initial_sync_status: "incomplete", }), - getDatabase({ + createDatabase({ initial_sync_status: "complete", }), ]; @@ -22,22 +22,22 @@ describe("DatabaseStatusLarge", () => { it("should render complete status", () => { const before = [ - getDatabase({ + createDatabase({ id: 1, initial_sync_status: "incomplete", }), - getDatabase({ + createDatabase({ id: 2, initial_sync_status: "complete", }), ]; const after = [ - getDatabase({ + createDatabase({ id: 1, initial_sync_status: "complete", }), - getDatabase({ + createDatabase({ id: 2, initial_sync_status: "complete", }), @@ -52,22 +52,22 @@ describe("DatabaseStatusLarge", () => { it("should render error status", () => { const before = [ - getDatabase({ + createDatabase({ id: 1, initial_sync_status: "incomplete", }), - getDatabase({ + createDatabase({ id: 2, initial_sync_status: "complete", }), ]; const after = [ - getDatabase({ + createDatabase({ id: 1, initial_sync_status: "aborted", }), - getDatabase({ + createDatabase({ id: 2, initial_sync_status: "complete", }), @@ -80,11 +80,3 @@ describe("DatabaseStatusLarge", () => { expect(screen.getByText("Sync failed")).toBeInTheDocument(); }); }); - -const getDatabase = (opts?: Partial<Database>): Database => ({ - id: 1, - name: "Our database", - is_sample: false, - initial_sync_status: "complete", - ...opts, -}); diff --git a/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.stories.tsx b/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.stories.tsx new file mode 100644 index 00000000000..a4021e2a652 --- /dev/null +++ b/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.stories.tsx @@ -0,0 +1,29 @@ +import React from "react"; +import { ComponentStory } from "@storybook/react"; +import { createDatabase } from "metabase-types/api/database"; +import DatabaseStatusSmall from "./DatabaseStatusSmall"; + +export default { + title: "Status/DatabaseStatusSmall", + component: DatabaseStatusSmall, + argTypes: { onExpand: { action: "onExpand" } }, +}; + +const Template: ComponentStory<typeof DatabaseStatusSmall> = args => { + return <DatabaseStatusSmall {...args} />; +}; + +export const Incomplete = Template.bind({}); +Incomplete.args = { + databases: [createDatabase({ initial_sync_status: "incomplete" })], +}; + +export const Complete = Template.bind({}); +Complete.args = { + databases: [createDatabase({ initial_sync_status: "complete" })], +}; + +export const Aborted = Template.bind({}); +Aborted.args = { + databases: [createDatabase({ initial_sync_status: "aborted" })], +}; diff --git a/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.styled.tsx b/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.styled.tsx index fed745c2201..76ed03f2db3 100644 --- a/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.styled.tsx +++ b/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.styled.tsx @@ -2,7 +2,7 @@ import styled from "styled-components"; import { color, lighten } from "metabase/lib/colors"; import Icon from "metabase/components/Icon"; import LoadingSpinner from "metabase/components/LoadingSpinner"; -import { InitialSyncStatus } from "../../types"; +import { InitialSyncStatus } from "metabase-types/api/database"; interface Props { status: InitialSyncStatus; diff --git a/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.tsx b/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.tsx index 7449634416b..af2976d0aeb 100644 --- a/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.tsx +++ b/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.tsx @@ -3,7 +3,7 @@ import { t } from "ttag"; import { isReducedMotionPreferred } from "metabase/lib/dom"; import { isSyncAborted, isSyncInProgress } from "metabase/lib/syncing"; import Tooltip from "metabase/components/Tooltip"; -import { Database, InitialSyncStatus } from "../../types"; +import { Database, InitialSyncStatus } from "metabase-types/api/database"; import { StatusRoot, StatusIconContainer, diff --git a/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.unit.spec.tsx b/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.unit.spec.tsx index 9a66d23b593..d393e4a6792 100644 --- a/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.unit.spec.tsx +++ b/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.unit.spec.tsx @@ -1,15 +1,15 @@ import React from "react"; import { render, screen } from "@testing-library/react"; +import { createDatabase } from "metabase-types/api/database"; import DatabaseStatusSmall from "./DatabaseStatusSmall"; -import { Database } from "../../types"; describe("DatabaseStatusSmall", () => { it("should render in-progress status", () => { const databases = [ - getDatabase({ + createDatabase({ initial_sync_status: "incomplete", }), - getDatabase({ + createDatabase({ initial_sync_status: "complete", }), ]; @@ -21,10 +21,10 @@ describe("DatabaseStatusSmall", () => { it("should render complete status", () => { const databases = [ - getDatabase({ + createDatabase({ initial_sync_status: "complete", }), - getDatabase({ + createDatabase({ initial_sync_status: "complete", }), ]; @@ -36,10 +36,10 @@ describe("DatabaseStatusSmall", () => { it("should render error status", () => { const databases = [ - getDatabase({ + createDatabase({ initial_sync_status: "aborted", }), - getDatabase({ + createDatabase({ initial_sync_status: "complete", }), ]; @@ -49,11 +49,3 @@ describe("DatabaseStatusSmall", () => { expect(screen.getByLabelText("Error syncing")).toBeInTheDocument(); }); }); - -const getDatabase = (opts?: Partial<Database>): Database => ({ - id: 1, - name: "Our database", - is_sample: false, - initial_sync_status: "complete", - ...opts, -}); diff --git a/frontend/src/metabase/status/containers/DatabaseStatus/DatabaseStatus.tsx b/frontend/src/metabase/status/containers/DatabaseStatus/DatabaseStatus.tsx index 69f54973aa5..ddc428b7618 100644 --- a/frontend/src/metabase/status/containers/DatabaseStatus/DatabaseStatus.tsx +++ b/frontend/src/metabase/status/containers/DatabaseStatus/DatabaseStatus.tsx @@ -3,8 +3,8 @@ import _ from "underscore"; import Databases from "metabase/entities/databases"; import { isSyncInProgress } from "metabase/lib/syncing"; import { getUser } from "metabase/selectors/user"; +import { Database } from "metabase-types/api/database"; import DatabaseStatus from "../../components/DatabaseStatus"; -import { Database } from "../../types"; const RELOAD_INTERVAL = 2000; -- GitLab