diff --git a/frontend/src/metabase/containers/SyncingModal/types.ts b/frontend/src/metabase-types/api/automagic-dashboards.ts similarity index 66% rename from frontend/src/metabase/containers/SyncingModal/types.ts rename to frontend/src/metabase-types/api/automagic-dashboards.ts index d295e291afa8e17667cfd3ed04e0e09b5df08344..4b50aba8cd0a4857ae968b1f0127e91d8d8c2066 100644 --- a/frontend/src/metabase/containers/SyncingModal/types.ts +++ b/frontend/src/metabase-types/api/automagic-dashboards.ts @@ -1,9 +1,6 @@ -export interface Database { - id: number; - is_sample: boolean; -} - export interface DatabaseCandidate { + id: string; + schema: string; tables: TableCandidate[]; } diff --git a/frontend/src/metabase-types/api/collection.ts b/frontend/src/metabase-types/api/collection.ts new file mode 100644 index 0000000000000000000000000000000000000000..070c7b8d7506e64846d057c6232f05505c947aa2 --- /dev/null +++ b/frontend/src/metabase-types/api/collection.ts @@ -0,0 +1,3 @@ +export interface Collection { + id: number; +} diff --git a/frontend/src/metabase-types/api/dashboard.ts b/frontend/src/metabase-types/api/dashboard.ts new file mode 100644 index 0000000000000000000000000000000000000000..ba4da2c8c2bd58014959fab9a5df4b6779ecfbc2 --- /dev/null +++ b/frontend/src/metabase-types/api/dashboard.ts @@ -0,0 +1,5 @@ +export interface Dashboard { + id: number; + name: string; + model?: string; +} diff --git a/frontend/src/metabase-types/api/database.ts b/frontend/src/metabase-types/api/database.ts index f88eb0f49176f06381ff6ba2bad26f555c750ea0..654615c0247173b16aa2fa7168b797e24f8605d7 100644 --- a/frontend/src/metabase-types/api/database.ts +++ b/frontend/src/metabase-types/api/database.ts @@ -3,16 +3,8 @@ export type InitialSyncStatus = "incomplete" | "complete" | "aborted"; export interface Database { id: number; name: string; + engine: string; is_sample: boolean; 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/index.ts b/frontend/src/metabase-types/api/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..76c2d58ae7f1fbe9dc763746069113fb5e318e93 --- /dev/null +++ b/frontend/src/metabase-types/api/index.ts @@ -0,0 +1,5 @@ +export * from "./automagic-dashboards"; +export * from "./collection"; +export * from "./dashboard"; +export * from "./database"; +export * from "./user"; diff --git a/frontend/src/metabase-types/api/mocks/automagic-dashboards.ts b/frontend/src/metabase-types/api/mocks/automagic-dashboards.ts new file mode 100644 index 0000000000000000000000000000000000000000..c44a194fab6b1d5d534997052623ea8c477c7f70 --- /dev/null +++ b/frontend/src/metabase-types/api/mocks/automagic-dashboards.ts @@ -0,0 +1,18 @@ +import { DatabaseCandidate, TableCandidate } from "metabase-types/api"; + +export const createMockDatabaseCandidate = ( + opts?: Partial<DatabaseCandidate>, +): DatabaseCandidate => ({ + id: "1/public", + schema: "public", + tables: [], + ...opts, +}); + +export const createMockTableCandidate = ( + opts?: Partial<TableCandidate>, +): TableCandidate => ({ + title: "Sample table", + url: "/auto/1", + ...opts, +}); diff --git a/frontend/src/metabase-types/api/mocks/collection.ts b/frontend/src/metabase-types/api/mocks/collection.ts new file mode 100644 index 0000000000000000000000000000000000000000..e5aec646dce92fa37f006c932eecbde974bf520d --- /dev/null +++ b/frontend/src/metabase-types/api/mocks/collection.ts @@ -0,0 +1,8 @@ +import { Collection } from "metabase-types/api"; + +export const createMockCollection = ( + opts?: Partial<Collection>, +): Collection => ({ + id: 1, + ...opts, +}); diff --git a/frontend/src/metabase-types/api/mocks/dashboard.ts b/frontend/src/metabase-types/api/mocks/dashboard.ts new file mode 100644 index 0000000000000000000000000000000000000000..fd90320bc8584da96b9d5ec5233fa62b5285c7ac --- /dev/null +++ b/frontend/src/metabase-types/api/mocks/dashboard.ts @@ -0,0 +1,7 @@ +import { Dashboard } from "metabase-types/api"; + +export const createMockDashboard = (opts?: Partial<Dashboard>): Dashboard => ({ + id: 1, + name: "Dashboard", + ...opts, +}); diff --git a/frontend/src/metabase-types/api/mocks/database.ts b/frontend/src/metabase-types/api/mocks/database.ts new file mode 100644 index 0000000000000000000000000000000000000000..5c9b691e62f81a478de93f6cd8361b94980fb418 --- /dev/null +++ b/frontend/src/metabase-types/api/mocks/database.ts @@ -0,0 +1,11 @@ +import { Database } from "metabase-types/api"; + +export const createMockDatabase = (opts?: Partial<Database>): Database => ({ + id: 1, + name: "Database", + engine: "H2", + is_sample: false, + creator_id: undefined, + initial_sync_status: "complete", + ...opts, +}); diff --git a/frontend/src/metabase-types/api/mocks/index.ts b/frontend/src/metabase-types/api/mocks/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..76c2d58ae7f1fbe9dc763746069113fb5e318e93 --- /dev/null +++ b/frontend/src/metabase-types/api/mocks/index.ts @@ -0,0 +1,5 @@ +export * from "./automagic-dashboards"; +export * from "./collection"; +export * from "./dashboard"; +export * from "./database"; +export * from "./user"; diff --git a/frontend/src/metabase-types/api/mocks/user.ts b/frontend/src/metabase-types/api/mocks/user.ts new file mode 100644 index 0000000000000000000000000000000000000000..cab74145396ffdc7353f638a1be97765ff98844a --- /dev/null +++ b/frontend/src/metabase-types/api/mocks/user.ts @@ -0,0 +1,10 @@ +import { User } from "metabase-types/api"; + +export const createMockUser = (opts?: Partial<User>): User => ({ + id: 1, + first_name: "Testy", + is_superuser: false, + has_invited_second_user: false, + personal_collection_id: 1, + ...opts, +}); diff --git a/frontend/src/metabase-types/api/user.ts b/frontend/src/metabase-types/api/user.ts index 3041f062a1aec42169c30c736ff79a23bdbb0ad1..f06f2e422779459160954bed2ed94d62ca73564f 100644 --- a/frontend/src/metabase-types/api/user.ts +++ b/frontend/src/metabase-types/api/user.ts @@ -1,8 +1,7 @@ export interface User { id: number; + first_name: string; + is_superuser: boolean; + has_invited_second_user: boolean; + personal_collection_id: number; } - -export const createUser = (opts?: Partial<User>): User => ({ - id: 1, - ...opts, -}); diff --git a/frontend/src/metabase-types/store/index.ts b/frontend/src/metabase-types/store/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..10cd3a7f3eeb0da5a6123735fd81cc6e96bf5478 --- /dev/null +++ b/frontend/src/metabase-types/store/index.ts @@ -0,0 +1,2 @@ +export * from "./settings"; +export * from "./state"; diff --git a/frontend/src/metabase-types/store/mocks/index.ts b/frontend/src/metabase-types/store/mocks/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..10cd3a7f3eeb0da5a6123735fd81cc6e96bf5478 --- /dev/null +++ b/frontend/src/metabase-types/store/mocks/index.ts @@ -0,0 +1,2 @@ +export * from "./settings"; +export * from "./state"; diff --git a/frontend/src/metabase-types/store/mocks/settings.ts b/frontend/src/metabase-types/store/mocks/settings.ts new file mode 100644 index 0000000000000000000000000000000000000000..db1cb318e62fe6dc99cc1c418866f3e20c3cd28b --- /dev/null +++ b/frontend/src/metabase-types/store/mocks/settings.ts @@ -0,0 +1,8 @@ +import { SettingsState } from "metabase-types/store"; + +export const createMockSettingsState = ( + opts?: Partial<SettingsState>, +): SettingsState => ({ + values: {}, + ...opts, +}); diff --git a/frontend/src/metabase-types/store/mocks/state.ts b/frontend/src/metabase-types/store/mocks/state.ts new file mode 100644 index 0000000000000000000000000000000000000000..5f5779a878a8351420f45c6cd38e2ad8b812b513 --- /dev/null +++ b/frontend/src/metabase-types/store/mocks/state.ts @@ -0,0 +1,7 @@ +import { State } from "metabase-types/store"; +import { createMockSettingsState } from "metabase-types/store/mocks"; + +export const createMockState = (opts?: Partial<State>): State => ({ + settings: createMockSettingsState(), + ...opts, +}); diff --git a/frontend/src/metabase-types/store/settings.ts b/frontend/src/metabase-types/store/settings.ts new file mode 100644 index 0000000000000000000000000000000000000000..054b5825a78e17ec58b689d698c3c2537db4b3b6 --- /dev/null +++ b/frontend/src/metabase-types/store/settings.ts @@ -0,0 +1,3 @@ +export interface SettingsState { + values: Record<string, unknown>; +} diff --git a/frontend/src/metabase-types/store/state.ts b/frontend/src/metabase-types/store/state.ts new file mode 100644 index 0000000000000000000000000000000000000000..3789eb909918e9f81b132e382492f24b25431f17 --- /dev/null +++ b/frontend/src/metabase-types/store/state.ts @@ -0,0 +1,5 @@ +import { SettingsState } from "./settings"; + +export interface State { + settings: SettingsState; +} diff --git a/frontend/src/metabase/containers/SyncingModal/SyncingModal.tsx b/frontend/src/metabase/containers/SyncingModal/SyncingModal.tsx index f4336d7088f9e9fecfff39b9a921c60af690e9e4..91cc7b85e5cf2d98aaf1712af8a3925c8bf46f77 100644 --- a/frontend/src/metabase/containers/SyncingModal/SyncingModal.tsx +++ b/frontend/src/metabase/containers/SyncingModal/SyncingModal.tsx @@ -5,7 +5,7 @@ import Settings from "metabase/lib/settings"; import Databases from "metabase/entities/databases"; import DatabaseCandidates from "metabase/entities/database-candidates"; import SyncingModal from "metabase/components/SyncingModal"; -import { Database, DatabaseCandidate } from "./types"; +import { Database, DatabaseCandidate } from "metabase-types/api"; interface DatabaseProps { databases: Database[]; diff --git a/frontend/src/metabase/home/homepage/analytics.ts b/frontend/src/metabase/home/homepage/analytics.ts index da50dbbbd00028d68d39d540d9535a36dfd0d041..2b89db6c2126143e12d0c18bc4df83cd7e6bd020 100644 --- a/frontend/src/metabase/home/homepage/analytics.ts +++ b/frontend/src/metabase/home/homepage/analytics.ts @@ -1,5 +1,5 @@ import { trackStructEvent } from "metabase/lib/analytics"; -import { Database, Dashboard } from "./types"; +import { Database, Dashboard } from "metabase-types/api"; export const trackCollectionClick = () => { trackStructEvent("Homepage", "Browse Items Clicked"); diff --git a/frontend/src/metabase/home/homepage/components/CollectionSection/CollectionSection.tsx b/frontend/src/metabase/home/homepage/components/CollectionSection/CollectionSection.tsx index d94e722c120ad32b4b7c0dca4bc24c14319c5a3a..57624a6da1957b01a15fa54c1b8b1faf769c70b7 100644 --- a/frontend/src/metabase/home/homepage/components/CollectionSection/CollectionSection.tsx +++ b/frontend/src/metabase/home/homepage/components/CollectionSection/CollectionSection.tsx @@ -3,7 +3,7 @@ import { t } from "ttag"; import CollectionList from "metabase/components/CollectionList"; import { ROOT_COLLECTION } from "metabase/entities/collections"; import * as Urls from "metabase/lib/urls"; -import { Collection, User } from "../../types"; +import { Collection, User } from "metabase-types/api"; import Section, { SectionHeader, SectionTitle } from "../Section"; import { CollectionContent, diff --git a/frontend/src/metabase/home/homepage/components/CollectionSection/CollectionSection.unit.spec.tsx b/frontend/src/metabase/home/homepage/components/CollectionSection/CollectionSection.unit.spec.tsx index 7d50304195e58507a84fff415d29838feb6780fc..3904b0b4d5b81a73c3534679c06e615bd833472b 100644 --- a/frontend/src/metabase/home/homepage/components/CollectionSection/CollectionSection.unit.spec.tsx +++ b/frontend/src/metabase/home/homepage/components/CollectionSection/CollectionSection.unit.spec.tsx @@ -1,6 +1,6 @@ import React from "react"; import { render, screen } from "@testing-library/react"; -import { Collection, User } from "../../types"; +import { createMockCollection, createMockUser } from "metabase-types/api/mocks"; import CollectionSection from "./CollectionSection"; const CollectionListMock = () => <div>CollectionList</div>; @@ -9,8 +9,8 @@ jest.mock("metabase/components/CollectionList", () => CollectionListMock); describe("CollectionSection", () => { it("should display the list when there are non-personal collections", () => { - const user = getUser(); - const collections = [getCollection()]; + const user = createMockUser({ personal_collection_id: 1 }); + const collections = [createMockCollection({ id: 2 })]; render(<CollectionSection user={user} collections={collections} />); @@ -18,8 +18,10 @@ describe("CollectionSection", () => { }); it("should display an empty state when there are no non-personal collections", () => { - const user = getUser(); - const collections = [getCollection({ id: user.personal_collection_id })]; + const user = createMockUser(); + const collections = [ + createMockCollection({ id: user.personal_collection_id }), + ]; render(<CollectionSection user={user} collections={collections} />); @@ -27,25 +29,13 @@ describe("CollectionSection", () => { }); it("should display a special empty state for admins", () => { - const user = getUser({ is_superuser: true }); - const collections = [getCollection({ id: user.personal_collection_id })]; + const user = createMockUser({ is_superuser: true }); + const collections = [ + createMockCollection({ id: user.personal_collection_id }), + ]; render(<CollectionSection user={user} collections={collections} />); expect(screen.getByText(/Save dashboards/)).toBeInTheDocument(); }); }); - -const getUser = (opts?: Partial<User>): User => ({ - id: 1, - first_name: "John", - is_superuser: false, - personal_collection_id: "personal", - has_invited_second_user: false, - ...opts, -}); - -const getCollection = (opts?: Partial<Collection>): Collection => ({ - id: "root", - ...opts, -}); diff --git a/frontend/src/metabase/home/homepage/components/DatabaseSection/DatabaseSection.tsx b/frontend/src/metabase/home/homepage/components/DatabaseSection/DatabaseSection.tsx index bfef994fd298236a98d6dbccd48bfaf055820162..7d0dc3e6b647cccc231f54808920d1eaebf0d1d7 100644 --- a/frontend/src/metabase/home/homepage/components/DatabaseSection/DatabaseSection.tsx +++ b/frontend/src/metabase/home/homepage/components/DatabaseSection/DatabaseSection.tsx @@ -5,7 +5,7 @@ import Ellipsified from "metabase/components/Ellipsified"; import ModalWithTrigger from "metabase/components/ModalWithTrigger"; import Tooltip from "metabase/components/Tooltip"; import * as Urls from "metabase/lib/urls"; -import { Database, User } from "../../types"; +import { Database, User } from "metabase-types/api"; import Section, { SectionCloseIcon, SectionHeader, diff --git a/frontend/src/metabase/home/homepage/components/DatabaseSection/DatabaseSection.unit.spec.tsx b/frontend/src/metabase/home/homepage/components/DatabaseSection/DatabaseSection.unit.spec.tsx index 7806c298f63fef344df7537d63ed1300db462ea8..dce6bc0d897a6f0eca567d68001e28da6af87348 100644 --- a/frontend/src/metabase/home/homepage/components/DatabaseSection/DatabaseSection.unit.spec.tsx +++ b/frontend/src/metabase/home/homepage/components/DatabaseSection/DatabaseSection.unit.spec.tsx @@ -1,13 +1,13 @@ import React from "react"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -import { Database, User } from "../../types"; +import { createMockDatabase, createMockUser } from "metabase-types/api/mocks"; import DatabaseSection from "./DatabaseSection"; describe("DatabaseSection", () => { it("should display databases", () => { - const user = getUser(); - const databases = [getDatabase({ name: "Our database" })]; + const user = createMockUser(); + const databases = [createMockDatabase({ name: "Our database" })]; render(<DatabaseSection user={user} databases={databases} showData />); @@ -17,8 +17,8 @@ describe("DatabaseSection", () => { }); it("should not be visible when hidden by the setting", () => { - const user = getUser(); - const databases = [getDatabase({ name: "Our database" })]; + const user = createMockUser(); + const databases = [createMockDatabase({ name: "Our database" })]; render( <DatabaseSection user={user} databases={databases} showData={false} />, @@ -29,8 +29,8 @@ describe("DatabaseSection", () => { }); it("should not be visible when hidden by the setting", () => { - const user = getUser(); - const databases = [getDatabase({ name: "Our database" })]; + const user = createMockUser(); + const databases = [createMockDatabase({ name: "Our database" })]; render( <DatabaseSection user={user} databases={databases} showData={false} />, @@ -41,7 +41,7 @@ describe("DatabaseSection", () => { }); it("should not be visible for regular users when there are no databases", () => { - const user = getUser(); + const user = createMockUser(); render(<DatabaseSection user={user} databases={[]} showData />); @@ -49,7 +49,7 @@ describe("DatabaseSection", () => { }); it("should be visible for admin users when there are no databases", () => { - const user = getUser({ is_superuser: true }); + const user = createMockUser({ is_superuser: true }); render(<DatabaseSection user={user} databases={[]} showData />); @@ -58,7 +58,7 @@ describe("DatabaseSection", () => { }); it("should allow admins to hide the section", () => { - const user = getUser({ is_superuser: true }); + const user = createMockUser({ is_superuser: true }); const onHideData = jest.fn(); render( @@ -77,7 +77,7 @@ describe("DatabaseSection", () => { }); it("should not allow regular users to hide the section", () => { - const user = getUser({ is_superuser: false }); + const user = createMockUser({ is_superuser: false }); const onHideData = jest.fn(); render( @@ -92,21 +92,3 @@ describe("DatabaseSection", () => { expect(screen.queryByLabelText("close icon")).not.toBeInTheDocument(); }); }); - -const getUser = (opts?: Partial<User>): User => ({ - id: 1, - first_name: "John", - is_superuser: false, - has_invited_second_user: false, - personal_collection_id: "personal", - ...opts, -}); - -const getDatabase = (opts?: Partial<Database>): Database => ({ - id: 1, - name: "Our database", - engine: "postgres", - is_sample: false, - initial_sync_status: "complete", - ...opts, -}); diff --git a/frontend/src/metabase/home/homepage/components/GreetingSection/GreetingSection.tsx b/frontend/src/metabase/home/homepage/components/GreetingSection/GreetingSection.tsx index 4019e7df27853527abe4c157626a2226aa7a3fb3..7dce320c9927e2c5bffad5857dc752e8a91b2459 100644 --- a/frontend/src/metabase/home/homepage/components/GreetingSection/GreetingSection.tsx +++ b/frontend/src/metabase/home/homepage/components/GreetingSection/GreetingSection.tsx @@ -3,7 +3,7 @@ import { t } from "ttag"; import MetabotLogo from "metabase/components/MetabotLogo"; import Tooltip from "metabase/components/Tooltip"; import Greeting from "metabase/lib/greeting"; -import { User } from "../../types"; +import { User } from "metabase-types/api"; import Section from "../Section"; import { GreetingContent, GreetingTitle } from "./GreetingSection.styled"; diff --git a/frontend/src/metabase/home/homepage/components/GreetingSection/GreetingSection.unit.spec.tsx b/frontend/src/metabase/home/homepage/components/GreetingSection/GreetingSection.unit.spec.tsx index a012345a0ce91b491d417e2e51cb9b7384129dad..615948c5b5200db6d189a7327268a5181e6d70e9 100644 --- a/frontend/src/metabase/home/homepage/components/GreetingSection/GreetingSection.unit.spec.tsx +++ b/frontend/src/metabase/home/homepage/components/GreetingSection/GreetingSection.unit.spec.tsx @@ -1,23 +1,14 @@ import React from "react"; import { render, screen } from "@testing-library/react"; -import { User } from "../../types"; +import { createMockUser } from "metabase-types/api/mocks"; import GreetingSection from "./GreetingSection"; describe("GreetingSection", () => { it("should display a personal greeting", () => { - const user = getUser({ first_name: "John" }); + const user = createMockUser({ first_name: "John" }); render(<GreetingSection user={user} />); expect(screen.getByText(/John/)).toBeInTheDocument(); }); }); - -const getUser = (opts?: Partial<User>): User => ({ - id: 1, - first_name: "John", - is_superuser: false, - has_invited_second_user: false, - personal_collection_id: "personal", - ...opts, -}); diff --git a/frontend/src/metabase/home/homepage/components/Homepage/Homepage.tsx b/frontend/src/metabase/home/homepage/components/Homepage/Homepage.tsx index b79b605743eaacbabe17b2706cb894d0e3e5eccc..909d90eefe4f13f076207c31d57c2fb1bebd7d28 100644 --- a/frontend/src/metabase/home/homepage/components/Homepage/Homepage.tsx +++ b/frontend/src/metabase/home/homepage/components/Homepage/Homepage.tsx @@ -13,7 +13,7 @@ import { Database, DatabaseCandidate, User, -} from "../../types"; +} from "metabase-types/api"; export interface HomepageProps { user: User; diff --git a/frontend/src/metabase/home/homepage/components/StartSection/StartSection.tsx b/frontend/src/metabase/home/homepage/components/StartSection/StartSection.tsx index 9efc47071fa143dcf90fd1bc4dfb58485e89fe05..80410bae1ca38d0a66fc77a5c6d40cce0c2c1e9b 100644 --- a/frontend/src/metabase/home/homepage/components/StartSection/StartSection.tsx +++ b/frontend/src/metabase/home/homepage/components/StartSection/StartSection.tsx @@ -6,7 +6,7 @@ import Link from "metabase/components/Link"; import { ROOT_COLLECTION } from "metabase/entities/collections"; import Settings from "metabase/lib/settings"; import * as Urls from "metabase/lib/urls"; -import { Dashboard, Database, User } from "../../types"; +import { Dashboard, Database, User } from "metabase-types/api"; import Section, { SectionHeader, SectionTitle } from "../Section"; import { BannerCloseIcon, diff --git a/frontend/src/metabase/home/homepage/components/StartSection/StartSection.unit.spec.tsx b/frontend/src/metabase/home/homepage/components/StartSection/StartSection.unit.spec.tsx index d31a6f924e8b4fbde00d81b79603f1821d223693..d7ed23354995d95499931b20948cf46d5ba6e619 100644 --- a/frontend/src/metabase/home/homepage/components/StartSection/StartSection.unit.spec.tsx +++ b/frontend/src/metabase/home/homepage/components/StartSection/StartSection.unit.spec.tsx @@ -1,14 +1,18 @@ import React from "react"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -import { Dashboard, Database, User } from "../../types"; +import { + createMockDashboard, + createMockDatabase, + createMockUser, +} from "metabase-types/api/mocks"; import StartSection from "./StartSection"; describe("StartSection", () => { it("should show pinned dashboards", () => { - const user = getUser(); - const databases = [getDatabase()]; - const dashboards = [getDashboard({ name: "Our dashboard" })]; + const user = createMockUser(); + const databases = [createMockDatabase()]; + const dashboards = [createMockDashboard({ name: "Our dashboard" })]; render( <StartSection @@ -26,9 +30,9 @@ describe("StartSection", () => { }); it("should show a banner for admins when there are no user databases", () => { - const user = getUser({ is_superuser: true }); - const databases = [getDatabase({ is_sample: true })]; - const dashboards = [getDashboard({ name: "Our dashboard" })]; + const user = createMockUser({ is_superuser: true }); + const databases = [createMockDatabase({ is_sample: true })]; + const dashboards = [createMockDashboard({ name: "Our dashboard" })]; render( <StartSection @@ -46,8 +50,8 @@ describe("StartSection", () => { }); it("should not show a banner for regular users when there are no user databases", () => { - const user = getUser(); - const dashboards = [getDashboard({ name: "Our dashboard" })]; + const user = createMockUser(); + const dashboards = [createMockDashboard({ name: "Our dashboard" })]; render( <StartSection @@ -65,7 +69,7 @@ describe("StartSection", () => { }); it("should show a banner for admins when there are no pinned dashboards", () => { - const user = getUser({ is_superuser: true }); + const user = createMockUser({ is_superuser: true }); render( <StartSection @@ -82,7 +86,7 @@ describe("StartSection", () => { }); it("should show a banner for regular users when there are no pinned dashboards", () => { - const user = getUser(); + const user = createMockUser(); render( <StartSection @@ -99,7 +103,7 @@ describe("StartSection", () => { }); it("should not hide the section for admins when there is no content", () => { - const user = getUser({ is_superuser: true }); + const user = createMockUser({ is_superuser: true }); render( <StartSection @@ -115,7 +119,7 @@ describe("StartSection", () => { }); it("should hide the section for regular users when there is no content", () => { - const user = getUser(); + const user = createMockUser(); render( <StartSection @@ -130,8 +134,8 @@ describe("StartSection", () => { }); it("should allow admins to hide the dashboard banner", () => { - const user = getUser({ is_superuser: true }); - const databases = [getDatabase()]; + const user = createMockUser({ is_superuser: true }); + const databases = [createMockDatabase()]; const onHidePinMessage = jest.fn(); render( @@ -149,8 +153,8 @@ describe("StartSection", () => { }); it("should not allow regular users to hide the dashboard banner", () => { - const user = getUser(); - const databases = [getDatabase()]; + const user = createMockUser(); + const databases = [createMockDatabase()]; const onHidePinMessage = jest.fn(); render( @@ -166,27 +170,3 @@ describe("StartSection", () => { expect(screen.queryByLabelText("close icon")).not.toBeInTheDocument(); }); }); - -const getUser = (opts?: Partial<User>): User => ({ - id: 1, - first_name: "John", - is_superuser: false, - has_invited_second_user: false, - personal_collection_id: "personal", - ...opts, -}); - -const getDatabase = (opts?: Partial<Database>): Database => ({ - id: 1, - name: "Our database", - engine: "postgres", - is_sample: false, - initial_sync_status: "complete", - ...opts, -}); - -const getDashboard = (opts?: Partial<Dashboard>): Dashboard => ({ - id: 1, - name: "Our dashboard", - ...opts, -}); diff --git a/frontend/src/metabase/home/homepage/components/SyncingSection/SyncingSection.tsx b/frontend/src/metabase/home/homepage/components/SyncingSection/SyncingSection.tsx index 24ce5587e985a8c14e22c5beab7cddac3cdb0255..b17903fadd7d1571cff3e431960facfb81c7301a 100644 --- a/frontend/src/metabase/home/homepage/components/SyncingSection/SyncingSection.tsx +++ b/frontend/src/metabase/home/homepage/components/SyncingSection/SyncingSection.tsx @@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useState } from "react"; import { isSyncInProgress } from "metabase/lib/syncing"; import Modal from "metabase/components/Modal"; import SyncingModal from "metabase/containers/SyncingModal"; -import { Database, User } from "../../types"; +import { Database, User } from "metabase-types/api"; export interface SyncingSectionProps { user: User; diff --git a/frontend/src/metabase/home/homepage/components/SyncingSection/SyncingSection.unit.spec.tsx b/frontend/src/metabase/home/homepage/components/SyncingSection/SyncingSection.unit.spec.tsx index 5cc9ac45e25a4cc749917c1ada8a40d2beac710d..799a4d0b7032eb647b37297b9be038253ffb2c1c 100644 --- a/frontend/src/metabase/home/homepage/components/SyncingSection/SyncingSection.unit.spec.tsx +++ b/frontend/src/metabase/home/homepage/components/SyncingSection/SyncingSection.unit.spec.tsx @@ -1,17 +1,17 @@ import React from "react"; import { render, screen } from "@testing-library/react"; import SyncingSection from "./SyncingSection"; -import { User, Database } from "../../types"; +import { createMockDatabase, createMockUser } from "metabase-types/api/mocks"; const SyncingModal = () => <div>Explore sample data</div>; jest.mock("metabase/containers/SyncingModal", () => SyncingModal); describe("SyncingSection", () => { it("should display a modal for a syncing database", () => { - const user = getUser({ id: 1 }); + const user = createMockUser({ id: 1 }); const databases = [ - getDatabase({ is_sample: true }), - getDatabase({ creator_id: 1, initial_sync_status: "incomplete" }), + createMockDatabase({ is_sample: true }), + createMockDatabase({ creator_id: 1, initial_sync_status: "incomplete" }), ]; const onHideSyncingModal = jest.fn(); @@ -29,10 +29,10 @@ describe("SyncingSection", () => { }); it("should not display the modal when it was already shown", () => { - const user = getUser({ id: 1 }); + const user = createMockUser({ id: 1 }); const databases = [ - getDatabase({ is_sample: true }), - getDatabase({ creator_id: 1, initial_sync_status: "incomplete" }), + createMockDatabase({ is_sample: true }), + createMockDatabase({ creator_id: 1, initial_sync_status: "incomplete" }), ]; const onHideSyncingModal = jest.fn(); @@ -50,10 +50,10 @@ describe("SyncingSection", () => { }); it("should not display the modal when the user is not the database creator", () => { - const user = getUser({ id: 1 }); + const user = createMockUser({ id: 1 }); const databases = [ - getDatabase({ is_sample: true }), - getDatabase({ creator_id: 2, initial_sync_status: "incomplete" }), + createMockDatabase({ is_sample: true }), + createMockDatabase({ creator_id: 2, initial_sync_status: "incomplete" }), ]; const onHideSyncingModal = jest.fn(); @@ -70,21 +70,3 @@ describe("SyncingSection", () => { expect(onHideSyncingModal).not.toHaveBeenCalled(); }); }); - -const getUser = (opts?: Partial<User>): User => ({ - id: 1, - first_name: "John", - is_superuser: false, - has_invited_second_user: false, - personal_collection_id: "personal", - ...opts, -}); - -const getDatabase = (opts?: Partial<Database>): Database => ({ - id: 1, - name: "Our database", - engine: "postgres", - is_sample: false, - initial_sync_status: "complete", - ...opts, -}); diff --git a/frontend/src/metabase/home/homepage/components/XraySection/XraySection.tsx b/frontend/src/metabase/home/homepage/components/XraySection/XraySection.tsx index 3953deb56154b0fefe39086cc98582ff71d05a6c..b80f4b42488ba8ad2805f772d84084dac2f35312 100644 --- a/frontend/src/metabase/home/homepage/components/XraySection/XraySection.tsx +++ b/frontend/src/metabase/home/homepage/components/XraySection/XraySection.tsx @@ -5,7 +5,7 @@ import Ellipsified from "metabase/components/Ellipsified"; import ModalWithTrigger from "metabase/components/ModalWithTrigger"; import Select, { Option } from "metabase/components/Select"; import Tooltip from "metabase/components/Tooltip"; -import { DatabaseCandidate, TableCandidate, User } from "../../types"; +import { DatabaseCandidate, TableCandidate, User } from "metabase-types/api"; import Section, { SectionCloseIcon, SectionHeader, diff --git a/frontend/src/metabase/home/homepage/components/XraySection/XraySection.unit.spec.tsx b/frontend/src/metabase/home/homepage/components/XraySection/XraySection.unit.spec.tsx index 50145848f0e6a29a382876a0de074cc58abd9f67..bb770946deebfaa8c2723046243bcdb84aa1632a 100644 --- a/frontend/src/metabase/home/homepage/components/XraySection/XraySection.unit.spec.tsx +++ b/frontend/src/metabase/home/homepage/components/XraySection/XraySection.unit.spec.tsx @@ -1,15 +1,19 @@ import React from "react"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -import { DatabaseCandidate, TableCandidate, User } from "../../types"; +import { + createMockDatabaseCandidate, + createMockTableCandidate, + createMockUser, +} from "metabase-types/api/mocks"; import XraySection from "./XraySection"; describe("XraySection", () => { it("should display table candidates", () => { - const user = getUser(); + const user = createMockUser(); const databaseCandidates = [ - getDatabaseCandidate({ - tables: [getTableCandidate({ title: "Orders table" })], + createMockDatabaseCandidate({ + tables: [createMockTableCandidate({ title: "Orders table" })], }), ]; @@ -22,10 +26,10 @@ describe("XraySection", () => { }); it("should allow admins to hide the section", () => { - const user = getUser({ is_superuser: true }); + const user = createMockUser({ is_superuser: true }); const databaseCandidates = [ - getDatabaseCandidate({ - tables: [getTableCandidate({ title: "Orders table" })], + createMockDatabaseCandidate({ + tables: [createMockTableCandidate({ title: "Orders table" })], }), ]; const onHideXrays = jest.fn(); @@ -45,10 +49,10 @@ describe("XraySection", () => { }); it("should not allow non-admins to hide the section", () => { - const user = getUser({ is_superuser: false }); + const user = createMockUser({ is_superuser: false }); const databaseCandidates = [ - getDatabaseCandidate({ - tables: [getTableCandidate({ title: "Orders table" })], + createMockDatabaseCandidate({ + tables: [createMockTableCandidate({ title: "Orders table" })], }), ]; @@ -58,15 +62,15 @@ describe("XraySection", () => { }); it("should allow changing database schema for table candidates", () => { - const user = getUser(); + const user = createMockUser(); const databaseCandidates = [ - getDatabaseCandidate({ + createMockDatabaseCandidate({ schema: "public", - tables: [getTableCandidate({ title: "Public table" })], + tables: [createMockTableCandidate({ title: "Public table" })], }), - getDatabaseCandidate({ + createMockDatabaseCandidate({ schema: "admin", - tables: [getTableCandidate({ title: "Admin table" })], + tables: [createMockTableCandidate({ title: "Admin table" })], }), ]; @@ -82,26 +86,3 @@ describe("XraySection", () => { expect(screen.getByText("Admin table")).toBeInTheDocument(); }); }); - -const getUser = (opts?: Partial<User>): User => ({ - id: 1, - first_name: "John", - is_superuser: false, - has_invited_second_user: false, - personal_collection_id: "personal", - ...opts, -}); - -const getTableCandidate = (opts?: Partial<TableCandidate>): TableCandidate => ({ - title: "Our table", - url: "/auto", - ...opts, -}); - -const getDatabaseCandidate = ( - opts?: Partial<DatabaseCandidate>, -): DatabaseCandidate => ({ - schema: "public", - tables: [], - ...opts, -}); diff --git a/frontend/src/metabase/home/homepage/containers/HomepageApp/HomepageApp.tsx b/frontend/src/metabase/home/homepage/containers/HomepageApp/HomepageApp.tsx index 994f13de21d518fd2991af4b3a7c81da132afa86..a939b4af61a735e771648ae363045f1484b256ce 100644 --- a/frontend/src/metabase/home/homepage/containers/HomepageApp/HomepageApp.tsx +++ b/frontend/src/metabase/home/homepage/containers/HomepageApp/HomepageApp.tsx @@ -5,6 +5,7 @@ import { ROOT_COLLECTION } from "metabase/entities/collections"; import DatabaseCandidates from "metabase/entities/database-candidates"; import Search from "metabase/entities/search"; import { getUser } from "metabase/selectors/user"; +import { State } from "metabase-types/store"; import Homepage from "../../components/Homepage"; import { hideData, @@ -17,7 +18,6 @@ import { getShowData, getShowPinMessage, getShowSyncingModal, - getShowXrays, } from "../../selectors"; import { trackCollectionClick, @@ -58,7 +58,7 @@ const databaseCandidatesProps = { loadingAndErrorWrapper: false, }; -const mapStateToProps = (state: any) => ({ +const mapStateToProps = (state: State) => ({ user: getUser(state), showData: getShowData(state), showPinMessage: getShowPinMessage(state), diff --git a/frontend/src/metabase/home/homepage/selectors.ts b/frontend/src/metabase/home/homepage/selectors.ts index 85d2baf59a035ca42530f159d85deaa5b7a6990b..be39fcbd7e1f956a06892fab3340014709ce4416 100644 --- a/frontend/src/metabase/home/homepage/selectors.ts +++ b/frontend/src/metabase/home/homepage/selectors.ts @@ -1,40 +1,42 @@ import { createSelector } from "reselect"; +import { Dashboard, Database } from "metabase-types/api"; +import { State } from "metabase-types/store"; import { createCandidatesQuery } from "./utils/database-candidates"; +export interface CandidatesProps { + databases?: Database[]; + dashboards?: Dashboard[]; +} + export const getCandidatesQuery = createSelector( - (state: any, props: any) => props.databases, - (state: any, props: any) => props.dashboards, - (state: any) => getShowXrays(state), - (state: any) => getEnableXrays(state), + (state: State, props: CandidatesProps) => props.databases, + (state: State, props: CandidatesProps) => props.dashboards, + (state: State) => getShowXrays(state), + (state: State) => getEnableXrays(state), createCandidatesQuery, ); -export const getSettings = createSelector<any, any, any>( - state => state.settings, +export const getSettings = createSelector( + (state: State) => state.settings, settings => settings.values, ); -export const getShowData = createSelector( - [getSettings], - settings => settings["show-homepage-data"], +export const getShowData = createSelector([getSettings], settings => + Boolean(settings["show-homepage-data"]), ); -export const getShowXrays = createSelector( - [getSettings], - settings => settings["show-homepage-xrays"], +export const getShowXrays = createSelector([getSettings], settings => + Boolean(settings["show-homepage-xrays"]), ); -export const getEnableXrays = createSelector( - [getSettings], - settings => settings["enable-xrays"], +export const getEnableXrays = createSelector([getSettings], settings => + Boolean(settings["enable-xrays"]), ); -export const getShowPinMessage = createSelector( - [getSettings], - settings => settings["show-homepage-pin-message"], +export const getShowPinMessage = createSelector([getSettings], settings => + Boolean(settings["show-homepage-pin-message"]), ); -export const getShowSyncingModal = createSelector( - [getSettings], - settings => settings["show-database-syncing-modal"], +export const getShowSyncingModal = createSelector([getSettings], settings => + Boolean(settings["show-database-syncing-modal"]), ); diff --git a/frontend/src/metabase/home/homepage/types.ts b/frontend/src/metabase/home/homepage/types.ts deleted file mode 100644 index e37e3f75cb6855fe0645db4f1c18efd57749effb..0000000000000000000000000000000000000000 --- a/frontend/src/metabase/home/homepage/types.ts +++ /dev/null @@ -1,38 +0,0 @@ -type InitialSyncStatus = "incomplete" | "complete" | "aborted"; - -export interface User { - id: number; - first_name: string; - is_superuser: boolean; - has_invited_second_user: boolean; - personal_collection_id: string; -} - -export interface Database { - id: number; - name: string; - engine: string; - is_sample: boolean; - creator_id?: number; - initial_sync_status: InitialSyncStatus; -} - -export interface Collection { - id: string; -} - -export interface Dashboard { - id: number; - name: string; - model?: string; -} - -export interface DatabaseCandidate { - schema: string; - tables: TableCandidate[]; -} - -export interface TableCandidate { - title: string; - url: string; -} diff --git a/frontend/src/metabase/home/homepage/utils/database-candidates.ts b/frontend/src/metabase/home/homepage/utils/database-candidates.ts index ff5302b69897c9be31e4deb61ffde6a92ed7a6ec..2187f03f6eb35b5e452f13b5ca87139318608666 100644 --- a/frontend/src/metabase/home/homepage/utils/database-candidates.ts +++ b/frontend/src/metabase/home/homepage/utils/database-candidates.ts @@ -1,5 +1,5 @@ import { isSyncCompleted } from "metabase/lib/syncing"; -import { Dashboard, Database } from "../types"; +import { Dashboard, Database } from "metabase-types/api"; export const createCandidatesQuery = ( databases: Database[] = [], diff --git a/frontend/src/metabase/setup/containers/CompletedStep/CompletedStep.tsx b/frontend/src/metabase/setup/containers/CompletedStep/CompletedStep.tsx index 38e5b61e8160feb50ffa401f2c2dc5b7df760122..65c2d11f7594c838a61377dbff04eb48a3d39f10 100644 --- a/frontend/src/metabase/setup/containers/CompletedStep/CompletedStep.tsx +++ b/frontend/src/metabase/setup/containers/CompletedStep/CompletedStep.tsx @@ -1,9 +1,10 @@ import { connect } from "react-redux"; +import { State } from "metabase-types/store"; import CompletedStep from "../../components/CompletedStep"; import { COMPLETED_STEP } from "../../constants"; import { getUser, isStepActive } from "../../selectors"; -const mapStateToProps = (state: any) => ({ +const mapStateToProps = (state: State) => ({ user: getUser(state), isStepActive: isStepActive(state, COMPLETED_STEP), }); diff --git a/frontend/src/metabase/setup/containers/DatabaseHelp/DatabaseHelp.tsx b/frontend/src/metabase/setup/containers/DatabaseHelp/DatabaseHelp.tsx index 3d9e05150e2cef637c007f3d58fbfef970b427bf..bda943f62fabbc71c05662fdf03db8804653d563 100644 --- a/frontend/src/metabase/setup/containers/DatabaseHelp/DatabaseHelp.tsx +++ b/frontend/src/metabase/setup/containers/DatabaseHelp/DatabaseHelp.tsx @@ -1,9 +1,10 @@ import { connect } from "react-redux"; +import { State } from "metabase-types/store"; import DatabaseHelp from "../../components/DatabaseHelp"; import { DATABASE_STEP } from "../../constants"; import { getDatabaseEngine, isStepActive } from "../../selectors"; -const mapStateToProps = (state: any) => ({ +const mapStateToProps = (state: State) => ({ engine: getDatabaseEngine(state), isStepActive: isStepActive(state, DATABASE_STEP), }); diff --git a/frontend/src/metabase/setup/containers/DatabaseStep/DatabaseStep.tsx b/frontend/src/metabase/setup/containers/DatabaseStep/DatabaseStep.tsx index b08be91f49f9d63520cb75e7da5e736eeb877aee..b50f130ab21de233c76f1e958160108afe5cc75f 100644 --- a/frontend/src/metabase/setup/containers/DatabaseStep/DatabaseStep.tsx +++ b/frontend/src/metabase/setup/containers/DatabaseStep/DatabaseStep.tsx @@ -1,5 +1,6 @@ import { connect } from "react-redux"; import Settings from "metabase/lib/settings"; +import { State } from "metabase-types/store"; import DatabaseStep from "../../components/DatabaseStep"; import { setDatabase, setInvite, setStep, submitDatabase } from "../../actions"; import { @@ -19,7 +20,7 @@ import { } from "../../selectors"; import { DatabaseInfo, InviteInfo } from "../../types"; -const mapStateToProps = (state: any) => ({ +const mapStateToProps = (state: State) => ({ user: getUser(state), database: getDatabase(state), engine: getDatabaseEngine(state), diff --git a/frontend/src/metabase/setup/containers/LanguageStep/LanguageStep.tsx b/frontend/src/metabase/setup/containers/LanguageStep/LanguageStep.tsx index 773e2b5a0c623f0ede7b54aedda43c3ac8808d5b..e6d8a4bd5c833cbc754264036076578d9989a7cb 100644 --- a/frontend/src/metabase/setup/containers/LanguageStep/LanguageStep.tsx +++ b/frontend/src/metabase/setup/containers/LanguageStep/LanguageStep.tsx @@ -1,5 +1,6 @@ import { connect } from "react-redux"; import Settings from "metabase/lib/settings"; +import { State } from "metabase-types/store"; import LanguageStep from "../../components/LanguageStep"; import { setLocale, setStep } from "../../actions"; import { LANGUAGE_STEP, USER_STEP } from "../../constants"; @@ -11,7 +12,7 @@ import { } from "../../selectors"; import { Locale } from "../../types"; -const mapStateToProps = (state: any) => ({ +const mapStateToProps = (state: State) => ({ locale: getLocale(state), localeData: Settings.get("available-locales"), isStepActive: isStepActive(state, LANGUAGE_STEP), diff --git a/frontend/src/metabase/setup/containers/PreferencesStep/PreferencesStep.tsx b/frontend/src/metabase/setup/containers/PreferencesStep/PreferencesStep.tsx index 43f9a8ba6e7d032c6b9e011e47a14cd4e818bea5..9e6acb41f28a2ceb380d982dc639994e8c7f67c0 100644 --- a/frontend/src/metabase/setup/containers/PreferencesStep/PreferencesStep.tsx +++ b/frontend/src/metabase/setup/containers/PreferencesStep/PreferencesStep.tsx @@ -1,4 +1,5 @@ import { connect } from "react-redux"; +import { State } from "metabase-types/store"; import PreferencesStep from "../../components/PreferencesStep"; import { setTracking, submitSetup, setStep } from "../../actions"; import { @@ -14,7 +15,7 @@ import { isSetupCompleted, } from "../../selectors"; -const mapStateToProps = (state: any) => ({ +const mapStateToProps = (state: State) => ({ isTrackingAllowed: isTrackingAllowed(state), isStepActive: isStepActive(state, PREFERENCES_STEP), isStepCompleted: isStepCompleted(state, PREFERENCES_STEP), diff --git a/frontend/src/metabase/setup/containers/SettingsPage/SettingsPage.tsx b/frontend/src/metabase/setup/containers/SettingsPage/SettingsPage.tsx index f2d198f59f45a195cfd45f884e73e59826c442cb..a17f0f0d44eb6dec3b664b8b3fadb3360306f3a5 100644 --- a/frontend/src/metabase/setup/containers/SettingsPage/SettingsPage.tsx +++ b/frontend/src/metabase/setup/containers/SettingsPage/SettingsPage.tsx @@ -1,9 +1,10 @@ import { connect } from "react-redux"; +import { State } from "metabase-types/store"; import SettingsPage from "../../components/SettingsPage"; import { trackStepSeen } from "../../analytics"; import { getStep } from "../../selectors"; -const mapStateToProps = (state: any) => ({ +const mapStateToProps = (state: State) => ({ step: getStep(state), }); diff --git a/frontend/src/metabase/setup/containers/SetupApp/SetupApp.tsx b/frontend/src/metabase/setup/containers/SetupApp/SetupApp.tsx index 401561ead33052b1d3c94b4413fba1c59e12a103..d678c073b4024572e547900079b1650caf786300 100644 --- a/frontend/src/metabase/setup/containers/SetupApp/SetupApp.tsx +++ b/frontend/src/metabase/setup/containers/SetupApp/SetupApp.tsx @@ -1,9 +1,10 @@ import { connect } from "react-redux"; import Setup from "../../components/Setup"; +import { State } from "metabase-types/store"; import { WELCOME_STEP } from "../../constants"; import { isStepActive } from "../../selectors"; -const mapStateToProps = (state: any) => ({ +const mapStateToProps = (state: State) => ({ isWelcome: isStepActive(state, WELCOME_STEP), }); diff --git a/frontend/src/metabase/setup/containers/UserStep/UserStep.tsx b/frontend/src/metabase/setup/containers/UserStep/UserStep.tsx index 73c13bbe7dc0ad2410eeb514beda14d94fb2d159..374460a122562b5c101fa2ba7dcc61a8343167c7 100644 --- a/frontend/src/metabase/setup/containers/UserStep/UserStep.tsx +++ b/frontend/src/metabase/setup/containers/UserStep/UserStep.tsx @@ -1,5 +1,6 @@ import { connect } from "react-redux"; import Settings from "metabase/lib/settings"; +import { State } from "metabase-types/store"; import UserStep from "../../components/UserStep"; import { setUser, validatePassword, setStep } from "../../actions"; import { trackUserStepCompleted } from "../../analytics"; @@ -12,7 +13,7 @@ import { } from "../../selectors"; import { UserInfo } from "../../types"; -const mapStateToProps = (state: any) => ({ +const mapStateToProps = (state: State) => ({ user: getUser(state), isHosted: Settings.isHosted(), isStepActive: isStepActive(state, USER_STEP), diff --git a/frontend/src/metabase/status/components/DatabaseStatus/DatabaseStatus.tsx b/frontend/src/metabase/status/components/DatabaseStatus/DatabaseStatus.tsx index ca39fcfe10c13a7fd599e29d7eb950fa8c5b1ae3..c0944448a3f496fe8215ca1cd0ec4ceb83b3afbe 100644 --- a/frontend/src/metabase/status/components/DatabaseStatus/DatabaseStatus.tsx +++ b/frontend/src/metabase/status/components/DatabaseStatus/DatabaseStatus.tsx @@ -1,7 +1,6 @@ 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 { Database, User } from "metabase-types/api"; import useStatusVisibility from "../../hooks/use-status-visibility"; import DatabaseStatusLarge from "../DatabaseStatusLarge"; import DatabaseStatusSmall from "../DatabaseStatusSmall"; 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 4dc1b10dac0be08a2cddb9acaf14067347ff7673..dd1dec3cba262d916f36296e0a634556e9265542 100644 --- a/frontend/src/metabase/status/components/DatabaseStatus/DatabaseStatus.unit.spec.tsx +++ b/frontend/src/metabase/status/components/DatabaseStatus/DatabaseStatus.unit.spec.tsx @@ -1,15 +1,14 @@ 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 { createMockDatabase, createMockUser } from "metabase-types/api/mocks"; import DatabaseStatus from "./DatabaseStatus"; describe("DatabaseStatus", () => { it("should toggle between small and large versions", () => { - const user = createUser({ id: 1 }); + const user = createMockUser({ id: 1 }); const databases = [ - createDatabase({ creator_id: 1, initial_sync_status: "incomplete" }), + createMockDatabase({ creator_id: 1, initial_sync_status: "incomplete" }), ]; render(<DatabaseStatus user={user} databases={databases} />); @@ -29,9 +28,9 @@ describe("DatabaseStatus", () => { }); it("should not render when databases are created by another user", () => { - const user = createUser({ id: 1 }); + const user = createMockUser({ id: 1 }); const databases = [ - createDatabase({ creator_id: 2, initial_sync_status: "incomplete" }), + createMockDatabase({ creator_id: 2, initial_sync_status: "incomplete" }), ]; render(<DatabaseStatus user={user} databases={databases} />); diff --git a/frontend/src/metabase/status/components/DatabaseStatusLarge/DatabaseStatusLarge.stories.tsx b/frontend/src/metabase/status/components/DatabaseStatusLarge/DatabaseStatusLarge.stories.tsx index b3b2c7bbc425d36ccba9378519b2ea9eca4138a7..ee32f93336203246bb2874c4e43acec121c9efce 100644 --- a/frontend/src/metabase/status/components/DatabaseStatusLarge/DatabaseStatusLarge.stories.tsx +++ b/frontend/src/metabase/status/components/DatabaseStatusLarge/DatabaseStatusLarge.stories.tsx @@ -1,6 +1,6 @@ import React from "react"; import { ComponentStory } from "@storybook/react"; -import { createDatabase } from "metabase-types/api/database"; +import { createMockDatabase } from "metabase-types/api/mocks"; import DatabaseStatusLarge from "./DatabaseStatusLarge"; export default { @@ -15,18 +15,18 @@ const Template: ComponentStory<typeof DatabaseStatusLarge> = args => { export const Incomplete = Template.bind({}); Incomplete.args = { - databases: [createDatabase({ initial_sync_status: "incomplete" })], + databases: [createMockDatabase({ initial_sync_status: "incomplete" })], isActive: true, }; export const Complete = Template.bind({}); Complete.args = { - databases: [createDatabase({ initial_sync_status: "complete" })], + databases: [createMockDatabase({ initial_sync_status: "complete" })], isActive: true, }; export const Aborted = Template.bind({}); Aborted.args = { - databases: [createDatabase({ initial_sync_status: "aborted" })], + databases: [createMockDatabase({ 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 9d7edba922454683b4217f65bd9f11afb05e25ac..5e78ae3a3249128b6bc5c6764c717a05eec809d7 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 "metabase-types/api/database"; +import { Database } from "metabase-types/api"; import Icon from "../../../components/Icon"; import { StatusCardRoot, 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 285ee205ed1099e12cc5684d48d301cfe0acf7c7..b7d19a84987aaa219134744ca4e29d908adbee1f 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 { createMockDatabase } from "metabase-types/api/mocks"; import DatabaseStatusLarge from "./DatabaseStatusLarge"; describe("DatabaseStatusLarge", () => { it("should render in-progress status", () => { const databases = [ - createDatabase({ + createMockDatabase({ initial_sync_status: "incomplete", }), - createDatabase({ + createMockDatabase({ initial_sync_status: "complete", }), ]; @@ -22,22 +22,22 @@ describe("DatabaseStatusLarge", () => { it("should render complete status", () => { const before = [ - createDatabase({ + createMockDatabase({ id: 1, initial_sync_status: "incomplete", }), - createDatabase({ + createMockDatabase({ id: 2, initial_sync_status: "complete", }), ]; const after = [ - createDatabase({ + createMockDatabase({ id: 1, initial_sync_status: "complete", }), - createDatabase({ + createMockDatabase({ id: 2, initial_sync_status: "complete", }), @@ -52,22 +52,22 @@ describe("DatabaseStatusLarge", () => { it("should render error status", () => { const before = [ - createDatabase({ + createMockDatabase({ id: 1, initial_sync_status: "incomplete", }), - createDatabase({ + createMockDatabase({ id: 2, initial_sync_status: "complete", }), ]; const after = [ - createDatabase({ + createMockDatabase({ id: 1, initial_sync_status: "aborted", }), - createDatabase({ + createMockDatabase({ id: 2, initial_sync_status: "complete", }), diff --git a/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.stories.tsx b/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.stories.tsx index a4021e2a65274819a3a3f0350ca0841d77dfc668..a19f087264fe3b6c7a861aa839d1472f4340c4ab 100644 --- a/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.stories.tsx +++ b/frontend/src/metabase/status/components/DatabaseStatusSmall/DatabaseStatusSmall.stories.tsx @@ -1,6 +1,6 @@ import React from "react"; import { ComponentStory } from "@storybook/react"; -import { createDatabase } from "metabase-types/api/database"; +import { createMockDatabase } from "metabase-types/api/mocks"; import DatabaseStatusSmall from "./DatabaseStatusSmall"; export default { @@ -15,15 +15,15 @@ const Template: ComponentStory<typeof DatabaseStatusSmall> = args => { export const Incomplete = Template.bind({}); Incomplete.args = { - databases: [createDatabase({ initial_sync_status: "incomplete" })], + databases: [createMockDatabase({ initial_sync_status: "incomplete" })], }; export const Complete = Template.bind({}); Complete.args = { - databases: [createDatabase({ initial_sync_status: "complete" })], + databases: [createMockDatabase({ initial_sync_status: "complete" })], }; export const Aborted = Template.bind({}); Aborted.args = { - databases: [createDatabase({ initial_sync_status: "aborted" })], + databases: [createMockDatabase({ 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 76ed03f2db3d31f9f63a8a159dfabac060a39e42..1bce0dd27aa13b6acd97d50280592861f1c61211 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 "metabase-types/api/database"; +import { InitialSyncStatus } from "metabase-types/api"; 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 af2976d0aebe3fd9539c82ac026e7bb3932cbb22..c3e5ed5318cdba37f32c94f6d5be48e4129c155d 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 "metabase-types/api/database"; +import { Database, InitialSyncStatus } from "metabase-types/api"; 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 d393e4a67925e0f172a4dc19b49aab17453e4991..5a034e9fdecf39659f84b54be5abd663be20d10e 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 { createMockDatabase } from "metabase-types/api/mocks"; import DatabaseStatusSmall from "./DatabaseStatusSmall"; describe("DatabaseStatusSmall", () => { it("should render in-progress status", () => { const databases = [ - createDatabase({ + createMockDatabase({ initial_sync_status: "incomplete", }), - createDatabase({ + createMockDatabase({ initial_sync_status: "complete", }), ]; @@ -21,10 +21,10 @@ describe("DatabaseStatusSmall", () => { it("should render complete status", () => { const databases = [ - createDatabase({ + createMockDatabase({ initial_sync_status: "complete", }), - createDatabase({ + createMockDatabase({ initial_sync_status: "complete", }), ]; @@ -36,10 +36,10 @@ describe("DatabaseStatusSmall", () => { it("should render error status", () => { const databases = [ - createDatabase({ + createMockDatabase({ initial_sync_status: "aborted", }), - createDatabase({ + createMockDatabase({ initial_sync_status: "complete", }), ]; diff --git a/frontend/src/metabase/status/containers/DatabaseStatus/DatabaseStatus.tsx b/frontend/src/metabase/status/containers/DatabaseStatus/DatabaseStatus.tsx index ddc428b7618cf83eca8fafda451d94ac7fe45c56..a2e63c864d446de6ae6afa21ea1f61039fffd6c4 100644 --- a/frontend/src/metabase/status/containers/DatabaseStatus/DatabaseStatus.tsx +++ b/frontend/src/metabase/status/containers/DatabaseStatus/DatabaseStatus.tsx @@ -3,18 +3,19 @@ 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 { Database } from "metabase-types/api"; +import { State } from "metabase-types/store"; import DatabaseStatus from "../../components/DatabaseStatus"; const RELOAD_INTERVAL = 2000; const databasesProps = { loadingAndErrorWrapper: false, - reloadInterval: (state: any, props: any, databases: Database[] = []) => + reloadInterval: (state: State, props: unknown, databases: Database[] = []) => databases.some(isSyncInProgress) ? RELOAD_INTERVAL : 0, }; -const mapStateToProps = (state: any) => ({ +const mapStateToProps = (state: State) => ({ user: getUser(state), }); diff --git a/frontend/src/metabase/status/containers/StatusListing/StatusListing.tsx b/frontend/src/metabase/status/containers/StatusListing/StatusListing.tsx index 5cdad2cf8bc2980fe20fe00b793b3a2268886219..4b0f97cee0b9c598a0f9241c45ca46e4ac4b7878 100644 --- a/frontend/src/metabase/status/containers/StatusListing/StatusListing.tsx +++ b/frontend/src/metabase/status/containers/StatusListing/StatusListing.tsx @@ -1,8 +1,9 @@ import { connect } from "react-redux"; import { getUserIsAdmin } from "metabase/selectors/user"; +import { State } from "metabase-types/store"; import StatusListing from "../../components/StatusListing"; -const mapStateToProps = (state: any) => ({ +const mapStateToProps = (state: State) => ({ isAdmin: getUserIsAdmin(state), });