diff --git a/package.json b/package.json index 49ab7540..96ed4cbe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "Rowy", "version": "2.0.0-rc.0", - "homepage": "https://rowy.io/", + "homepage": "https://rowy.io", "repository": { "type": "git", "url": "https://github.com/rowyio/rowy.git" diff --git a/src/App.tsx b/src/App.tsx index 98e88fee..7afbecab 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -23,6 +23,7 @@ import routes from "constants/routes"; import AuthPage from "pages/Auth"; import SignOutPage from "pages/Auth/SignOut"; import SignUpPage from "pages/Auth/SignUp"; +import DeployPage from "pages/Deploy"; import TestPage from "pages/Test"; import RowyRunTestPage from "pages/RowyRunTest"; import PageNotFound from "pages/PageNotFound"; @@ -94,6 +95,11 @@ export default function App() { path={routes.setup} render={() => } /> + } + /> @@ -55,33 +55,32 @@ export default function BrandedBackground() { ].join(", ") }; } - - #root { - cursor: default; - } - - .wrapper { - display: grid; - place-items: center; - align-content: center; - gap: ${theme.spacing(3)}; - grid-auto-rows: max-content; - - ${["top", "right", "bottom", "left"] - .map( - (side) => - `padding-${side}: max(env(safe-area-inset-${side}), ${theme.spacing( - 1 - )});` - ) - .join("\n")} - - min-height: ${ - fullScreenHeight > 0 ? `${fullScreenHeight}px` : "100vh" - }; - } `} ); } + +export function Wrapper(props: BoxProps) { + const fullScreenHeight = use100vh() ?? 0; + + return ( + ({ xs: theme.spacing(2), sm: theme.spacing(3) }), + gridAutoRows: "max-content", + minHeight: fullScreenHeight > 0 ? `${fullScreenHeight}px` : "100vh", + + pt: (theme) => `max(env(safe-area-inset-top), ${theme.spacing(1)})`, + pb: (theme) => `max(env(safe-area-inset-bottom), ${theme.spacing(1)})`, + pl: (theme) => `max(env(safe-area-inset-left), ${theme.spacing(1)})`, + pr: (theme) => `max(env(safe-area-inset-right), ${theme.spacing(1)})`, + ...props.sx, + }} + /> + ); +} diff --git a/src/components/Auth/AuthLayout.tsx b/src/components/Auth/AuthLayout.tsx index a095298d..80f625aa 100644 --- a/src/components/Auth/AuthLayout.tsx +++ b/src/components/Auth/AuthLayout.tsx @@ -7,14 +7,15 @@ import { LinkProps, } from "@mui/material"; import { alpha } from "@mui/material/styles"; -import BrandedBackground from "assets/BrandedBackground"; +import BrandedBackground, { Wrapper } from "assets/BrandedBackground"; import Logo from "assets/Logo"; import { useAppContext } from "contexts/AppContext"; -import { homepage } from "@root/package.json"; +import { EXTERNAL_LINKS } from "constants/externalLinks"; export interface IAuthLayoutProps { hideLogo?: boolean; + hideProject?: boolean; title?: React.ReactNode; description?: React.ReactNode; children: React.ReactNode; @@ -23,6 +24,7 @@ export interface IAuthLayoutProps { export default function AuthLayout({ hideLogo, + hideProject, title, description, children, @@ -39,7 +41,7 @@ export default function AuthLayout({ }; return ( -
+ theme.spacing(2) } : {}}> @@ -115,43 +121,42 @@ export default function AuthLayout({ Project: {projectId} - - {homepage.split("//").pop()?.replace(/\//g, "")} + + {EXTERNAL_LINKS.homepage.split("//").pop()?.replace(/\//g, "")} - + Discord - + Twitter
- + Docs - + Privacy - + Terms -
+
); } diff --git a/src/components/Auth/MarketingBanner.tsx b/src/components/Auth/MarketingBanner.tsx new file mode 100644 index 00000000..bc0f91d7 --- /dev/null +++ b/src/components/Auth/MarketingBanner.tsx @@ -0,0 +1,94 @@ +import { Stack, Paper, Typography, Button } from "@mui/material"; +import { alpha } from "@mui/material/styles"; +import DiscordIcon from "assets/icons/Discord"; +import TwitterIcon from "@mui/icons-material/Twitter"; + +import Logo from "assets/Logo"; +import { EXTERNAL_LINKS } from "constants/externalLinks"; + +export default function MarketingBanner() { + return ( + alpha(theme.palette.background.paper, 0.5), + backdropFilter: "blur(20px) saturate(150%)", + + pt: (theme) => `max(env(safe-area-inset-top), ${theme.spacing(8)})`, + pb: (theme) => `max(env(safe-area-inset-bottom), ${theme.spacing(8)})`, + pl: (theme) => `max(env(safe-area-inset-left), ${theme.spacing(8)})`, + pr: 8, + }} + > + + + + + +
+ + Manage Firestore data in a spreadsheet-like UI + + + Write Cloud Functions effortlessly in the browser + + + Connect to your favorite third party platforms + +
+ + + + + +
+
+ ); +} diff --git a/src/components/Home/AccessDenied.tsx b/src/components/Home/AccessDenied.tsx index dbdd8cf7..e2ac2f48 100644 --- a/src/components/Home/AccessDenied.tsx +++ b/src/components/Home/AccessDenied.tsx @@ -5,7 +5,7 @@ import SecurityIcon from "@mui/icons-material/SecurityOutlined"; import EmptyState from "components/EmptyState"; -import WIKI_LINKS from "constants/wikiLinks"; +import { WIKI_LINKS } from "constants/externalLinks"; import routes from "constants/routes"; import { useAppContext } from "@src/contexts/AppContext"; diff --git a/src/components/Settings/ProjectSettings/About.tsx b/src/components/Settings/ProjectSettings/About.tsx index 88708a9b..84827fc8 100644 --- a/src/components/Settings/ProjectSettings/About.tsx +++ b/src/components/Settings/ProjectSettings/About.tsx @@ -4,13 +4,16 @@ import { differenceInDays } from "date-fns"; import { Grid, Typography, Button, Link, Divider } from "@mui/material"; import LoadingButton from "@mui/lab/LoadingButton"; +import GitHubIcon from "@mui/icons-material/GitHub"; +import DiscordIcon from "assets/icons/Discord"; +import TwitterIcon from "@mui/icons-material/Twitter"; import Logo from "assets/Logo"; import InlineOpenInNewIcon from "components/InlineOpenInNewIcon"; import { name, version, repository } from "@root/package.json"; import { useAppContext } from "contexts/AppContext"; -import WIKI_LINKS from "constants/wikiLinks"; +import { EXTERNAL_LINKS, WIKI_LINKS } from "constants/externalLinks"; const useLastCheckedUpdateState = createPersistedState( "__ROWY__LAST_CHECKED_UPDATE" @@ -82,41 +85,44 @@ export default function About() { />
- + - } + href={EXTERNAL_LINKS.gitHub} target="_blank" rel="noopener noreferrer" > GitHub - - + - } + href={EXTERNAL_LINKS.discord} target="_blank" rel="noopener noreferrer" > Discord - - + - } + href={EXTERNAL_LINKS.twitter} target="_blank" rel="noopener noreferrer" > Twitter - - +
@@ -126,29 +132,27 @@ export default function About() {
- + {checkState === "LOADING" ? ( + Checking for updates… + ) : latestUpdate === null ? ( + Up to date + ) : ( + + Update available:{" "} + + {latestUpdate.tag_name} + + + + )} + + {name} v{version} - {checkState === "LOADING" ? ( - - Checking for updates… - - ) : latestUpdate === null ? ( - - Up to date - - ) : ( - - Update available: {latestUpdate.tag_name} - - - )} diff --git a/src/components/Settings/ProjectSettings/RowyRun.tsx b/src/components/Settings/ProjectSettings/RowyRun.tsx index 806cd65f..1619a1f5 100644 --- a/src/components/Settings/ProjectSettings/RowyRun.tsx +++ b/src/components/Settings/ProjectSettings/RowyRun.tsx @@ -14,9 +14,9 @@ import LoadingButton from "@mui/lab/LoadingButton"; import InlineOpenInNewIcon from "components/InlineOpenInNewIcon"; import { IProjectSettingsChildProps } from "pages/Settings/ProjectSettings"; -import WIKI_LINKS from "constants/wikiLinks"; +import { EXTERNAL_LINKS } from "constants/externalLinks"; import { name } from "@root/package.json"; -import { runRoutes, runRepoUrl } from "constants/runRoutes"; +import { runRoutes } from "constants/runRoutes"; const useLastCheckedUpdateState = createPersistedState( "__ROWY__RUN_LAST_CHECKED_UPDATE" @@ -74,8 +74,10 @@ export default function RowyRun({ // https://docs.github.com/en/rest/reference/repos#get-the-latest-release const endpoint = - runRepoUrl.replace("github.com", "api.github.com/repos") + - "/releases/latest"; + EXTERNAL_LINKS.rowyRunGitHub.replace( + "github.com", + "api.github.com/repos" + ) + "/releases/latest"; try { const versionReq = await fetch( settings.rowyRunUrl + runRoutes.version.path, @@ -121,7 +123,7 @@ export default function RowyRun({ const deployButton = window.location.hostname.includes("rowy.app") ? ( ) : ( - ); @@ -147,7 +153,7 @@ export default function RowyRun({ such as table action scripts, user management, and easy Cloud Function deployment.{" "} @@ -162,29 +168,27 @@ export default function RowyRun({
- + {checkState === "LOADING" ? ( + Checking for updates… + ) : latestUpdate === null ? ( + Up to date + ) : ( + + Update available:{" "} + + {latestUpdate.tag_name} + + + + )} + + {name} Run v{version} - {checkState === "LOADING" ? ( - - Checking for updates… - - ) : latestUpdate === null ? ( - - Up to date - - ) : ( - - Update available: {latestUpdate.tag_name} - - - )} diff --git a/src/components/Setup/Step1RowyRun.tsx b/src/components/Setup/Step1RowyRun.tsx index 812f4cb8..712f11db 100644 --- a/src/components/Setup/Step1RowyRun.tsx +++ b/src/components/Setup/Step1RowyRun.tsx @@ -11,7 +11,8 @@ import SetupItem from "./SetupItem"; import { name } from "@root/package.json"; import { rowyRun } from "utils/rowyRun"; -import { runRepoUrl, runRoutes } from "constants/runRoutes"; +import { runRoutes } from "constants/runRoutes"; +import { EXTERNAL_LINKS } from "constants/externalLinks"; export default function Step1RowyRun({ completion, @@ -63,7 +64,7 @@ export default function Step1RowyRun({ const deployButton = window.location.hostname.includes("rowy.app") ? ( ) : ( - - - - +
@@ -115,6 +41,31 @@ export default function SignUpPage() { } > + + By signing up, you agree to our{" "} + + Terms and Conditions + {" "} + and{" "} + + Privacy Policy + + . +
diff --git a/src/pages/Deploy.tsx b/src/pages/Deploy.tsx new file mode 100644 index 00000000..83eb9a3b --- /dev/null +++ b/src/pages/Deploy.tsx @@ -0,0 +1,80 @@ +import { useLocation } from "react-router-dom"; +import queryString from "query-string"; + +import { useMediaQuery, Stack, Typography, Link, Button } from "@mui/material"; +import OpenInNewIcon from "@mui/icons-material/OpenInNew"; + +import MarketingBanner from "components/Auth/MarketingBanner"; +import AuthLayout from "components/Auth/AuthLayout"; + +import { EXTERNAL_LINKS } from "constants/externalLinks"; +import { name } from "@root/package.json"; + +export default function DeployPage() { + const { search } = useLocation(); + const parsed = queryString.parse(search); + + const uiConfig: firebaseui.auth.Config = {}; + if (typeof parsed.redirect === "string" && parsed.redirect.length > 0) { + uiConfig.signInSuccessUrl = parsed.redirect; + } + + const isMobile = useMediaQuery((theme: any) => theme.breakpoints.down("md")); + + return ( + + + +
+ + To get started with {name}, set up {name} Run on your Google Cloud + Platform project with this one-click deploy button. + + } + > + + Run on Google Cloud + + + + By setting up {name}, you agree to our{" "} + + Terms and Conditions + {" "} + and{" "} + + Privacy Policy + + . + + +
+
+ ); +} diff --git a/src/pages/RowyRunTest.tsx b/src/pages/RowyRunTest.tsx index 801959ce..cde72586 100644 --- a/src/pages/RowyRunTest.tsx +++ b/src/pages/RowyRunTest.tsx @@ -18,7 +18,7 @@ import { } from "@mui/material"; import { useConfirmation } from "components/ConfirmationDialog"; import { useProjectContext } from "@src/contexts/ProjectContext"; -import { runRoutes } from "@src/constants/runRoutes"; +import { runRoutes } from "constants/runRoutes"; const useBodyCacheState = createPersistedState("__ROWY__RR_TEST_REQ_BODY"); export default function TestView() { diff --git a/src/pages/Setup.tsx b/src/pages/Setup.tsx index 97090780..176b9cc4 100644 --- a/src/pages/Setup.tsx +++ b/src/pages/Setup.tsx @@ -23,7 +23,7 @@ import LoadingButton from "@mui/lab/LoadingButton"; import ChevronLeftIcon from "@mui/icons-material/ChevronLeft"; import ChevronRightIcon from "@mui/icons-material/ChevronRight"; -import BrandedBackground from "assets/BrandedBackground"; +import BrandedBackground, { Wrapper } from "assets/BrandedBackground"; import Logo from "assets/Logo"; import ScrollableDialogContent from "components/Modal/ScrollableDialogContent"; import { SlideTransition } from "components/Modal/SlideTransition"; @@ -246,7 +246,7 @@ export default function SetupPage() { }; return ( -
+ -
+ ); } diff --git a/src/theme/components.tsx b/src/theme/components.tsx index 7c6f2e72..761baba4 100644 --- a/src/theme/components.tsx +++ b/src/theme/components.tsx @@ -54,6 +54,8 @@ export const components = (theme: Theme): ThemeOptions => { }, }, + body: { cursor: "default" }, + "code, pre, pre.MuiTypography-root": { fontFamily: theme.typography.fontFamilyMono, letterSpacing: 0,