Skip to content
Open
75 changes: 55 additions & 20 deletions packages/app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,32 @@ import "@malloy-publisher/sdk/styles.css";
import "@malloydata/malloy-explorer/styles.css";
import { CssBaseline } from "@mui/material";
import { ThemeProvider } from "@mui/material/styles";
import * as React from "react";
import { lazy, Suspense, useMemo } from "react";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { HeaderProps } from "./components/Header";
import { Loading } from "./components/common/Loading";
import { HeaderProps } from "./components/layout/Header/Header";
import theme from "./theme";

/**
* Vite automatically handles code splitting and chunking when using
* React.lazy and dynamic import() statements for lazy loading React
* components.
*/
const HomePage = React.lazy(() => import("./components/HomePage"));
const MainPage = React.lazy(() => import("./components/MainPage"));
const ModelPage = React.lazy(() => import("./components/ModelPage"));
const PackagePage = React.lazy(() => import("./components/PackagePage"));
const ProjectPage = React.lazy(() => import("./components/ProjectPage"));
const RouteError = React.lazy(() => import("./components/RouteError"));
const WorkbookPage = React.lazy(() => import("./components/WorkbookPage"));
const HomePage = lazy(() => import("./components/pages/HomePage/HomePage"));
const MainPage = lazy(() => import("./components/layout/MainPage/MainPage"));
const ModelPage = lazy(() => import("./components/pages/ModelPage/ModelPage"));
const PackagePage = lazy(
() => import("./components/pages/PackagePage/PackagePage"),
);
const ProjectPage = lazy(
() => import("./components/pages/ProjectPage/ProjectPage"),
);
const RouteError = lazy(
() => import("./components/common/RouteError/RouteError"),
);
const WorkbookPage = lazy(
() => import("./components/pages/WorkbookPage/WorkbookPage"),
);

// Create router configuration function
export const createMalloyRouter = (
Expand All @@ -39,32 +48,54 @@ export const createMalloyRouter = (
<WorkbookStorageProvider workbookStorage={workbookStorage}>
<ThemeProvider theme={theme}>
<CssBaseline />
<MainPage headerProps={headerProps} />
<Suspense fallback={<Loading />}>
<MainPage headerProps={headerProps} />
</Suspense>
</ThemeProvider>
</WorkbookStorageProvider>
</ServerProvider>
),
errorElement: <RouteError />,
children: [
{
path: "",
element: <HomePage />,
index: true,
element: (
<Suspense fallback={<Loading />}>
<HomePage />
</Suspense>
),
},
{
path: ":projectName",
element: <ProjectPage />,
element: (
<Suspense fallback={<Loading />}>
<ProjectPage />
</Suspense>
),
},
{
path: ":projectName/:packageName",
element: <PackagePage />,
element: (
<Suspense fallback={<Loading />}>
<PackagePage />
</Suspense>
),
},
{
path: ":projectName/:packageName/*",
element: <ModelPage />,
element: (
<Suspense fallback={<Loading />}>
<ModelPage />
</Suspense>
),
},
{
path: ":projectName/:packageName/workbook/:workspace/:workbookPath",
element: <WorkbookPage />,
element: (
<Suspense fallback={<Loading />}>
<WorkbookPage />
</Suspense>
),
},
],
},
Expand All @@ -77,11 +108,15 @@ export interface MalloyPublisherAppProps {
workbookStorage: WorkbookStorage;
}

export const MalloyPublisherApp: React.FC<MalloyPublisherAppProps> = ({
workbookStorage,
export const MalloyPublisherApp = ({
basePath = "/",
workbookStorage,
headerProps,
}) => {
const router = createMalloyRouter(basePath, workbookStorage, headerProps);
}: MalloyPublisherAppProps) => {
const router = useMemo(
() => createMalloyRouter(basePath, workbookStorage, headerProps),
[basePath, workbookStorage, headerProps],
);

return <RouterProvider router={router} />;
};
102 changes: 102 additions & 0 deletions packages/app/src/components/common/Loading/Loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import Box from "@mui/material/Box";
import CircularProgress from "@mui/material/CircularProgress";
import Typography from "@mui/material/Typography";

export interface LoadingProps {
text?: string;
/**
* The size of the CircularProgress component
* @default 20
*/
size?: number | string;
/**
* The color of the CircularProgress component
* @default "primary"
*/
color?:
| "primary"
| "secondary"
| "error"
| "info"
| "success"
| "warning"
| "inherit";
/**
* The thickness of the circular progress
* @default 3.6
*/
thickness?: number;
/**
* Whether to center the component
* @default true
*/
centered?: boolean;
/**
* Custom spacing between spinner and text
* @default 2
*/
spacing?: number;
/**
* Typography variant for the text
* @default "body1"
*/
textVariant?:
| "h1"
| "h2"
| "h3"
| "h4"
| "h5"
| "h6"
| "subtitle1"
| "subtitle2"
| "body1"
| "body2"
| "caption"
| "overline";
}

export function Loading({
text,
size = 20,
color = "primary",
thickness = 3.6,
centered = true,
spacing = 2,
textVariant = "body2",
}: LoadingProps) {
const content = (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: spacing,
}}
>
<CircularProgress size={size} color={color} thickness={thickness} />
{text && (
<Typography variant={textVariant} color="text.secondary">
{text}
</Typography>
)}
</Box>
);

if (centered) {
return (
<Box
sx={{
display: "flex",
justifyContent: "center",
alignItems: "center",
minHeight: "200px",
width: "100%",
}}
>
{content}
</Box>
);
}

return content;
}
2 changes: 2 additions & 0 deletions packages/app/src/components/common/Loading/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { Loading } from "./Loading";
export type { LoadingProps } from "./Loading";
2 changes: 2 additions & 0 deletions packages/app/src/components/common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./RouteError/RouteError";
export * from "./Loading";
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useRouterClickHandler } from "@malloy-publisher/sdk";
import { ChevronRight } from "@mui/icons-material";
import { Box, Chip } from "@mui/material";
import Box from "@mui/material/Box";
import Chip from "@mui/material/Chip";
import Breadcrumbs from "@mui/material/Breadcrumbs";
import { useParams } from "react-router-dom";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import MenuIcon from "@mui/icons-material/Menu";
import {
AppBar,
Box,
Button,
IconButton,
Menu,
MenuItem,
Stack,
Toolbar,
Typography,
useMediaQuery,
useTheme,
} from "@mui/material";
import AppBar from "@mui/material/AppBar";
import MenuItem from "@mui/material/MenuItem";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import IconButton from "@mui/material/IconButton";
import Menu from "@mui/material/Menu";
import Stack from "@mui/material/Stack";
import Toolbar from "@mui/material/Toolbar";
import Typography from "@mui/material/Typography";
import useMediaQuery from "@mui/material/useMediaQuery";
import { useTheme } from "@mui/material/styles";
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import BreadcrumbNav from "./BreadcrumbNav";
import BreadcrumbNav from "../BreadcrumNav/BreadcrumbNav";

export interface HeaderProps {
logoHeader?: React.ReactElement;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Box } from "@mui/material";
import Container from "@mui/material/Container";
import { Outlet } from "react-router-dom";
import Header, { HeaderProps } from "./Header";
import Header, { HeaderProps } from "../Header/Header";

interface PublisherConfigProps {
headerProps?: HeaderProps;
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/components/layout/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from "./Header";
export type { HeaderProps } from "./Header";
export { default as MainPage } from "./MainPage/MainPage";
export { default as BreadcrumbNav } from "./BreadcrumNav/BreadcrumbNav";
5 changes: 5 additions & 0 deletions packages/app/src/components/pages/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export { default as HomePage } from "./HomePage/HomePage";
export { default as ProjectPage } from "./ProjectPage/ProjectPage";
export { default as PackagePage } from "./PackagePage/PackagePage";
export { default as ModelPage } from "./ModelPage/ModelPage";
export { default as WorkbookPage } from "./WorkbookPage/WorkbookPage";
8 changes: 4 additions & 4 deletions packages/app/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Main App exports
export { MalloyPublisherApp, createMalloyRouter } from "./App";
export { createMalloyRouter, MalloyPublisherApp } from "./App";
export type { MalloyPublisherAppProps } from "./App";

// Theme exports
export * from "./components/layout/Header";
export { default as theme } from "./theme";
export * from "./components";
// Additional component exports for advanced usage
export { default as BreadcrumbNav } from "./components/BreadcrumbNav";
export { default as ToggleColorMode } from "./components/ToggleColorMode";
export { default as BreadcrumbNav } from "./components/layout/BreadcrumNav/BreadcrumbNav";
export { default as ToggleColorMode } from "./components/theme/ToggleColorMode/ToggleColorMode";