diff --git a/packages/toolpad-app/src/constants.ts b/packages/toolpad-app/src/constants.ts index 89568a53466..9d69aba8b8a 100644 --- a/packages/toolpad-app/src/constants.ts +++ b/packages/toolpad-app/src/constants.ts @@ -8,3 +8,5 @@ export const TOOLPAD_TARGET_CE = 'CE'; export const TOOLPAD_TARGET_CLOUD = 'CLOUD'; export const TOOLPAD_TARGET_PRO = 'PRO'; export const DOCUMENTATION_URL = 'https://mui.com/toolpad/getting-started/overview/'; +export const DOCUMENTATION_INSTALLATION_URL = + 'https://mui.com/toolpad/getting-started/installation/'; diff --git a/packages/toolpad-app/src/toolpad/Home/UpdateBanner.tsx b/packages/toolpad-app/src/toolpad/Home/UpdateBanner.tsx deleted file mode 100644 index 26b9fe6d51d..00000000000 --- a/packages/toolpad-app/src/toolpad/Home/UpdateBanner.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import * as React from 'react'; -import { Button, Snackbar, Stack } from '@mui/material'; -import IconButton from '@mui/material/IconButton'; -import CloseIcon from '@mui/icons-material/Close'; -import OpenInNewIcon from '@mui/icons-material/OpenInNew'; -import { DOCUMENTATION_URL, TOOLPAD_TARGET_CLOUD } from '../../constants'; -import client from '../../api'; -import useLocalStorageState from '../../utils/useLocalStorageState'; - -const CURRENT_RELEASE_VERSION = `v${process.env.TOOLPAD_VERSION}`; - -function UpdateBanner() { - const { data: latestRelease } = client.useQuery('getLatestToolpadRelease', [], { - staleTime: 1000 * 60 * 10, - enabled: process.env.TOOLPAD_TARGET !== TOOLPAD_TARGET_CLOUD, - }); - - const [dismissedVersion, setDismissedVersion] = useLocalStorageState( - 'update-banner-dismissed-version', - null, - ); - - const handleDismissClick = React.useCallback( - (event: React.SyntheticEvent | Event, reason?: string) => { - if (reason === 'clickaway' || reason === 'escapeKeyDown') { - return; - } - setDismissedVersion(CURRENT_RELEASE_VERSION); - }, - [setDismissedVersion], - ); - - const hideBanner = - (latestRelease && latestRelease.tag === CURRENT_RELEASE_VERSION) || - dismissedVersion === CURRENT_RELEASE_VERSION; - - return latestRelease ? ( - - A new version {latestRelease.tag} of Toolpad is available. - - } - action={ - - - - - - - - } - /> - ) : null; -} - -export default UpdateBanner; diff --git a/packages/toolpad-app/src/toolpad/Home/index.tsx b/packages/toolpad-app/src/toolpad/Home/index.tsx index 96156d447bf..dd2099096a3 100644 --- a/packages/toolpad-app/src/toolpad/Home/index.tsx +++ b/packages/toolpad-app/src/toolpad/Home/index.tsx @@ -51,7 +51,6 @@ import DialogForm from '../../components/DialogForm'; import type { Deployment } from '../../../prisma/generated/client'; import useLatest from '../../utils/useLatest'; import ToolpadShell from '../ToolpadShell'; -import UpdateBanner from './UpdateBanner'; import getReadableDuration from '../../utils/readableDuration'; import EditableText from '../../components/EditableText'; import type { AppMeta } from '../../server/data'; @@ -789,7 +788,6 @@ export default function Home() { duplicateApp={duplicateApp} /> )} - ) : null} setCreateDialogOpen(false)} /> diff --git a/packages/toolpad-app/src/toolpad/ToolpadShell.tsx b/packages/toolpad-app/src/toolpad/ToolpadShell.tsx deleted file mode 100644 index 886a0b68de9..00000000000 --- a/packages/toolpad-app/src/toolpad/ToolpadShell.tsx +++ /dev/null @@ -1,195 +0,0 @@ -import * as React from 'react'; -import { - styled, - AppBar, - Box, - Toolbar, - IconButton, - Menu, - MenuItem, - Divider, - ListItemText, - Tooltip, - Chip, - Link, - useTheme, -} from '@mui/material'; -import HelpOutlinedIcon from '@mui/icons-material/HelpOutlined'; -import OpenInNewIcon from '@mui/icons-material/OpenInNew'; -import Image from 'next/image'; -import useMenu from '../utils/useMenu'; -import { - TOOLPAD_TARGET_CLOUD, - TOOLPAD_TARGET_CE, - TOOLPAD_TARGET_PRO, - DOCUMENTATION_URL, -} from '../constants'; -import productIconDark from '../../public/product-icon-dark.svg'; -import productIconLight from '../../public/product-icon-light.svg'; - -const REPORT_BUG_URL = - 'https://github.com/mui/mui-toolpad/issues/new?assignees=&labels=status%3A+needs+triage&template=1.bug.yml'; -const FEATURE_REQUEST_URL = 'https://github.com/mui/mui-toolpad/issues'; - -interface FeedbackMenuItemLinkProps { - href: string; - children: React.ReactNode; -} - -function FeedbackMenuItemLink({ href, children }: FeedbackMenuItemLinkProps) { - return ( - - {children} - - - ); -} - -export interface ToolpadShellProps { - actions?: React.ReactNode; - status?: React.ReactNode; - children?: React.ReactNode; -} - -const ToolpadShellRoot = styled('div')({ - width: '100vw', - minHeight: '100vh', - display: 'flex', - flexDirection: 'column', -}); - -const ViewPort = styled('div')({ - flex: 1, - overflow: 'auto', - position: 'relative', -}); - -function getReadableTarget(): string { - switch (process.env.TOOLPAD_TARGET) { - case TOOLPAD_TARGET_CLOUD: - return 'Cloud'; - case TOOLPAD_TARGET_CE: - return 'Community'; - case TOOLPAD_TARGET_PRO: - return 'Pro'; - default: - return 'Unknown'; - } -} - -function UserFeedback() { - const { buttonProps, menuProps } = useMenu(); - - return ( - - - - - - - - Documentation - Report bug - - Request or upvote feature - - - {getReadableTarget()} - Version {process.env.TOOLPAD_VERSION} - Build {process.env.TOOLPAD_BUILD} - - - ); -} -export interface HeaderProps { - actions?: React.ReactNode; - status?: React.ReactNode; -} - -function Header({ actions, status }: HeaderProps) { - const theme = useTheme(); - return ( - - - - - - Toolpad product icon - - MUI Toolpad - - - - {process.env.TOOLPAD_DEMO ? ( - - ) : null} - - - {actions} - - - {status} - - - - - ); -} - -export default function ToolpadShell({ children, ...props }: ToolpadShellProps) { - return ( - -
- {children} - - ); -} diff --git a/packages/toolpad-app/src/toolpad/ToolpadShell/Header/UserFeedback/index.tsx b/packages/toolpad-app/src/toolpad/ToolpadShell/Header/UserFeedback/index.tsx new file mode 100644 index 00000000000..38f3e3a9cf2 --- /dev/null +++ b/packages/toolpad-app/src/toolpad/ToolpadShell/Header/UserFeedback/index.tsx @@ -0,0 +1,89 @@ +import * as React from 'react'; +import { Chip, Divider, ListItemText, IconButton, Menu, MenuItem, Tooltip } from '@mui/material'; +import HelpOutlinedIcon from '@mui/icons-material/HelpOutlined'; +import OpenInNewIcon from '@mui/icons-material/OpenInNew'; +import useMenu from '../../../../utils/useMenu'; +import { + TOOLPAD_TARGET_CLOUD, + TOOLPAD_TARGET_CE, + TOOLPAD_TARGET_PRO, + DOCUMENTATION_URL, + DOCUMENTATION_INSTALLATION_URL, +} from '../../../../constants'; +import client from '../../../../api'; + +const REPORT_BUG_URL = + 'https://github.com/mui/mui-toolpad/issues/new?assignees=&labels=status%3A+needs+triage&template=1.bug.yml'; +const FEATURE_REQUEST_URL = 'https://github.com/mui/mui-toolpad/issues'; +const CURRENT_RELEASE_VERSION = `v${process.env.TOOLPAD_VERSION}`; + +interface FeedbackMenuItemLinkProps { + href: string; + children: React.ReactNode; +} + +function FeedbackMenuItemLink({ href, children }: FeedbackMenuItemLinkProps) { + return ( + + {children} + + + ); +} + +function getReadableTarget(): string { + switch (process.env.TOOLPAD_TARGET) { + case TOOLPAD_TARGET_CLOUD: + return 'Cloud'; + case TOOLPAD_TARGET_CE: + return 'Community Edition'; + case TOOLPAD_TARGET_PRO: + return 'Pro'; + default: + return 'Unknown'; + } +} + +function UserFeedback() { + const { buttonProps, menuProps } = useMenu(); + + const { data: latestRelease } = client.useQuery('getLatestToolpadRelease', [], { + staleTime: 1000 * 60 * 10, + enabled: process.env.TOOLPAD_TARGET !== TOOLPAD_TARGET_CLOUD, + }); + + return ( + + + + + + + + Documentation + Report bug + + Request or upvote feature + + + {getReadableTarget()} + {latestRelease && latestRelease.tag !== CURRENT_RELEASE_VERSION ? ( + + Version {process.env.TOOLPAD_VERSION} + + + ) : ( + Version {process.env.TOOLPAD_VERSION} + )} + Build {process.env.TOOLPAD_BUILD} + + + ); +} + +export default UserFeedback; diff --git a/packages/toolpad-app/src/toolpad/ToolpadShell/Header/index.tsx b/packages/toolpad-app/src/toolpad/ToolpadShell/Header/index.tsx new file mode 100644 index 00000000000..fc552b1d231 --- /dev/null +++ b/packages/toolpad-app/src/toolpad/ToolpadShell/Header/index.tsx @@ -0,0 +1,92 @@ +import * as React from 'react'; +import { AppBar, Box, Toolbar, Tooltip, Chip, Link, useTheme } from '@mui/material'; +import Image from 'next/image'; +import UserFeedback from './UserFeedback'; +import productIconDark from '../../../../public/product-icon-dark.svg'; +import productIconLight from '../../../../public/product-icon-light.svg'; + +export interface HeaderProps { + actions?: React.ReactNode; + status?: React.ReactNode; +} + +function Header({ actions, status }: HeaderProps) { + const theme = useTheme(); + return ( + + + + + + Toolpad product icon + + MUI Toolpad + + + + {process.env.TOOLPAD_DEMO ? ( + + ) : null} + + + {actions} + + + {status} + + + + + ); +} + +export default Header; diff --git a/packages/toolpad-app/src/toolpad/ToolpadShell/index.tsx b/packages/toolpad-app/src/toolpad/ToolpadShell/index.tsx new file mode 100644 index 00000000000..9a1e8c3f4d7 --- /dev/null +++ b/packages/toolpad-app/src/toolpad/ToolpadShell/index.tsx @@ -0,0 +1,31 @@ +import * as React from 'react'; +import { styled } from '@mui/material'; +import Header from './Header'; + +export interface ToolpadShellProps { + actions?: React.ReactNode; + status?: React.ReactNode; + children?: React.ReactNode; +} + +const ToolpadShellRoot = styled('div')({ + width: '100vw', + minHeight: '100vh', + display: 'flex', + flexDirection: 'column', +}); + +const ViewPort = styled('div')({ + flex: 1, + overflow: 'auto', + position: 'relative', +}); + +export default function ToolpadShell({ children, ...props }: ToolpadShellProps) { + return ( + +
+ {children} + + ); +}