update navigation for consistency

This commit is contained in:
Sidney Alcantara
2021-09-03 12:40:29 +10:00
parent bb431e56c2
commit b134e9c5cd
10 changed files with 134 additions and 221 deletions

View File

@@ -107,7 +107,8 @@ export default function App() {
path={routes.home}
render={() => (
<Navigation
title={
title="Home"
titleComponent={
<div style={{ textAlign: "center" }}>
<Logo />
</div>

View File

@@ -1,4 +1,4 @@
import { useLocation, Link } from "react-router-dom";
import { useLocation } from "react-router-dom";
import {
Drawer,
@@ -6,7 +6,6 @@ import {
Stack,
IconButton,
List,
MenuItem,
ListItemIcon,
ListItemText,
Divider,
@@ -19,7 +18,8 @@ import CloseIcon from "assets/icons/Backburger";
import { APP_BAR_HEIGHT } from ".";
import Logo from "assets/Logo";
import NavDrawerItem from "./NavDrawerItem";
import NavItem from "./NavItem";
import NavTableSection from "./NavTableSection";
import { useRowyContext } from "contexts/RowyContext";
import { routes } from "constants/routes";
@@ -28,17 +28,14 @@ export const NAV_DRAWER_WIDTH = 256;
export interface INavDrawerProps extends DrawerProps {
currentSection?: string;
currentTable?: string;
onClose: NonNullable<DrawerProps["onClose"]>;
}
export default function NavDrawer({
currentSection,
currentTable = "",
...props
}: INavDrawerProps) {
const { userClaims, sections } = useRowyContext();
const { pathname } = useLocation();
const closeDrawer = (e: {}) => props.onClose(e, "escapeKeyDown");
@@ -67,72 +64,51 @@ export default function NavDrawer({
<nav>
<List disablePadding>
<li>
<MenuItem
component={Link}
to={routes.home}
selected={pathname === routes.home}
onClick={closeDrawer}
>
<NavItem to={routes.home} onClick={closeDrawer}>
<ListItemIcon>
<HomeIcon />
</ListItemIcon>
<ListItemText primary="Home" />
</MenuItem>
</NavItem>
</li>
<li>
<MenuItem
component={Link}
to={routes.userSettings}
selected={pathname === routes.userSettings}
onClick={closeDrawer}
>
<NavItem to={routes.userSettings} onClick={closeDrawer}>
<ListItemIcon>
<SettingsIcon />
</ListItemIcon>
<ListItemText primary="Settings" />
</MenuItem>
</NavItem>
</li>
{userClaims?.roles?.includes("ADMIN") && (
<li>
<MenuItem
component={Link}
to={routes.projectSettings}
selected={pathname === routes.projectSettings}
onClick={closeDrawer}
>
<NavItem to={routes.projectSettings} onClick={closeDrawer}>
<ListItemIcon>
<ProjectSettingsIcon />
</ListItemIcon>
<ListItemText primary="Project Settings" />
</MenuItem>
</NavItem>
</li>
)}
{userClaims?.roles?.includes("ADMIN") && (
<li>
<MenuItem
component={Link}
to={routes.userManagement}
selected={pathname === routes.userManagement}
onClick={closeDrawer}
>
<NavItem to={routes.userManagement} onClick={closeDrawer}>
<ListItemIcon>
<UserManagementIcon />
</ListItemIcon>
<ListItemText primary="User Management" />
</MenuItem>
</NavItem>
</li>
)}
<Divider variant="middle" sx={{ mt: 1, mb: 1 }} />
<Divider variant="middle" sx={{ my: 1 }} />
{sections &&
Object.entries(sections).map(([section, tables]) => (
<NavDrawerItem
<NavTableSection
key={section}
section={section}
tables={tables}
currentSection={currentSection}
currentTable={currentTable}
closeDrawer={closeDrawer}
/>
))}

View File

@@ -1,130 +0,0 @@
import { useState } from "react";
import { Link } from "react-router-dom";
import clsx from "clsx";
import { makeStyles, createStyles } from "@material-ui/styles";
import { List, MenuItem, ListItemText, Collapse } from "@material-ui/core";
import ArrowDropDownIcon from "@material-ui/icons/ArrowDropDown";
import { Table } from "contexts/RowyContext";
import { routes } from "constants/routes";
const useStyles = makeStyles((theme) =>
createStyles({
listItem: {
width: `calc(100% - ${theme.spacing(2)})`,
margin: theme.spacing(0, 1),
padding: theme.spacing(0.75, 0.25, 0.75, 1),
},
listItemSelected: {
"&&, &&:hover": { backgroundColor: theme.palette.action.selected },
"$listItem&:before": {
top: (36 - 16) / 2,
},
},
listItemIcon: {},
listItemText: {
...theme.typography.body2,
display: "block",
color: "inherit",
},
dropdownIcon: {
color: theme.palette.action.active,
transition: theme.transitions.create("transform"),
},
dropdownIconOpen: { transform: "rotate(180deg)" },
childListItem: {
minHeight: 36,
paddingLeft: theme.spacing(4),
},
childListItemText: {
...theme.typography.body2,
display: "block",
color: "inherit",
},
})
);
export interface INavDrawerItemProps {
section: string;
tables: Table[];
currentSection?: string;
currentTable: string;
closeDrawer: (e: {}) => void;
}
export default function NavDrawerItem({
section,
tables,
currentSection,
currentTable,
closeDrawer,
}: INavDrawerItemProps) {
const classes = useStyles();
const [open, setOpen] = useState(section === currentSection);
return (
<li>
<MenuItem
// button
classes={{
root: clsx(
classes.listItem,
!open && currentSection === section && classes.listItemSelected
),
}}
selected={!open && currentSection === section}
onClick={() => setOpen((o) => !o)}
>
<ListItemText
primary={section}
classes={{ primary: classes.listItemText }}
/>
<ArrowDropDownIcon
className={clsx(
classes.dropdownIcon,
open && classes.dropdownIconOpen
)}
/>
</MenuItem>
<Collapse in={open}>
<List disablePadding>
{tables.map((table) => (
<li key={table.collection}>
<MenuItem
// button
selected={table.collection === currentTable}
classes={{
root: clsx(classes.listItem, classes.childListItem),
selected: classes.listItemSelected,
}}
component={Link}
to={
table.isCollectionGroup
? `${routes.tableGroup}/${table.collection}`
: `${routes.table}/${table.collection.replace(
/\//g,
"~2F"
)}`
}
onClick={closeDrawer}
>
<ListItemText
primary={table.name}
classes={{ primary: classes.childListItemText }}
/>
</MenuItem>
</li>
))}
</List>
</Collapse>
</li>
);
}

View File

@@ -0,0 +1,20 @@
import { Link, useLocation } from "react-router-dom";
import { MenuItem, MenuItemProps } from "@material-ui/core";
export default function NavItem(props: MenuItemProps<Link>) {
const { pathname } = useLocation();
return (
<MenuItem
component={Link}
selected={pathname === props.to}
{...props}
sx={{
"&&::before": {
left: "auto",
right: 0,
},
}}
/>
);
}

View File

@@ -0,0 +1,66 @@
import { useState } from "react";
import { List, ListItemText, Collapse } from "@material-ui/core";
import ArrowDropDownIcon from "@material-ui/icons/ArrowDropDown";
import NavItem from "./NavItem";
import { Table } from "contexts/RowyContext";
import { routes } from "constants/routes";
export interface INavDrawerItemProps {
section: string;
tables: Table[];
currentSection?: string;
closeDrawer: (e: {}) => void;
}
export default function NavDrawerItem({
section,
tables,
currentSection,
closeDrawer,
}: INavDrawerItemProps) {
const [open, setOpen] = useState(section === currentSection);
return (
<li>
<NavItem
{...({ component: "button" } as any)}
selected={!open && currentSection === section}
onClick={() => setOpen((o) => !o)}
>
<ListItemText primary={section} style={{ textAlign: "left" }} />
<ArrowDropDownIcon
sx={{
color: "action.active",
transform: open ? "rotate(180deg)" : "rotate(0)",
transition: (theme) => theme.transitions.create("transform"),
}}
/>
</NavItem>
<Collapse in={open}>
<List disablePadding>
{tables.map((table) => (
<li key={table.collection}>
<NavItem
to={
table.isCollectionGroup
? `${routes.tableGroup}/${table.collection}`
: `${routes.table}/${table.collection.replace(
/\//g,
"~2F"
)}`
}
onClick={closeDrawer}
>
<ListItemText primary={table.name} sx={{ pl: 2 }} />
</NavItem>
</li>
))}
</List>
</Collapse>
</li>
);
}

View File

@@ -7,7 +7,6 @@ import {
IconButton,
Box,
Typography,
Fade,
} from "@material-ui/core";
import MenuIcon from "@material-ui/icons/Menu";
@@ -21,24 +20,22 @@ export const APP_BAR_HEIGHT = 56;
export interface INavigationProps {
children: ReactNode;
title?: ReactNode;
title: string;
titleComponent?: ReactNode;
currentSection?: string;
currentTable?: string;
}
export default function Navigation({
children,
title,
titleComponent,
currentSection,
currentTable,
}: INavigationProps) {
const [open, setOpen] = useState(false);
if (typeof title === "string")
document.title = `${title} | ${projectId} | ${name}`;
const trigger = useScrollTrigger({ disableHysteresis: true, threshold: 0 });
document.title = `${title}${projectId}${name}`;
return (
<>
<AppBar
@@ -88,12 +85,10 @@ export default function Navigation({
</IconButton>
<Box sx={{ flex: 1, userSelect: "none" }}>
{typeof title === "string" ? (
{titleComponent || (
<Typography variant="h6" component="h1" textAlign="center">
{title}
</Typography>
) : (
title
)}
</Box>
@@ -106,7 +101,6 @@ export default function Navigation({
open={open}
onClose={() => setOpen(false)}
currentSection={currentSection}
currentTable={currentTable}
/>
{children}

View File

@@ -4,17 +4,17 @@ import OpenInNewIcon from "@material-ui/icons/OpenInNew";
import { IProjectSettingsChildProps } from "pages/Settings/ProjectSettings";
import WIKI_LINKS from "constants/wikiLinks";
import { repository } from "@root/package.json";
import { name, repository } from "@root/package.json";
export default function FunctionsBuilder({
export default function CloudRun({
settings,
updateSettings,
}: IProjectSettingsChildProps) {
return (
<>
<Typography>
Functions Builder is a Cloud Run instance that deploys this projects
Cloud Functions.{" "}
{name} Run is a Cloud Run instance that deploys this projects Cloud
Functions.{" "}
<Link
href={WIKI_LINKS.functions}
target="_blank"
@@ -38,8 +38,8 @@ export default function FunctionsBuilder({
>
<Grid item xs={12} sm>
<Typography>
If you have not yet deployed Functions Builder, click this button
and follow the prompts on Cloud Shell.
If you have not yet deployed {name} Run, click this button and
follow the prompts on Cloud Shell.
</Typography>
</Grid>
@@ -53,11 +53,13 @@ export default function FunctionsBuilder({
rel="noopener noreferrer"
endIcon={<OpenInNewIcon aria-label="Open in new tab" />}
loading={
settings.buildStatus === "BUILDING" ||
settings.buildStatus === "COMPLETE"
settings.cloudRunDeployStatus === "BUILDING" ||
settings.cloudRunDeployStatus === "COMPLETE"
}
loadingIndicator={
settings.buildStatus === "COMPLETE" ? "Deployed" : undefined
settings.cloudRunDeployStatus === "COMPLETE"
? "Deployed"
: undefined
}
>
Deploy to Cloud Run
@@ -68,9 +70,9 @@ export default function FunctionsBuilder({
<TextField
label="Cloud Run Instance URL"
id="buildUrl"
defaultValue={settings.buildUrl}
onChange={(e) => updateSettings({ buildUrl: e.target.value })}
id="cloudRunUrl"
defaultValue={settings.cloudRunUrl}
onChange={(e) => updateSettings({ cloudRunUrl: e.target.value })}
fullWidth
placeholder="https://<id>.run.app"
type="url"

View File

@@ -71,14 +71,8 @@ const RowyContext = React.createContext<Partial<RowyContextProps>>({});
export default RowyContext;
export const rowyUser = (currentUser) => {
const {
displayName,
email,
uid,
emailVerified,
isAnonymous,
photoURL,
} = currentUser;
const { displayName, email, uid, emailVerified, isAnonymous, photoURL } =
currentUser;
return {
timestamp: new Date(),
displayName,
@@ -112,7 +106,7 @@ export const RowyContextProvider: React.FC = ({ children }) => {
)
.map((table) => ({
...table,
section: table.section ? table.section.trim() : "OTHER",
section: table.section ? table.section.trim() : "Other",
}));
const _sections = _groupBy(filteredTables, "section");

View File

@@ -3,8 +3,8 @@ import { Container, Stack } from "@material-ui/core";
import SettingsSkeleton from "components/Settings/SettingsSkeleton";
import SettingsSection from "components/Settings/SettingsSection";
import About from "components/Settings/ProjectSettings/About";
import CloudRun from "@src/components/Settings/ProjectSettings/CloudRun";
import Authentication from "components/Settings/ProjectSettings/Authentication";
import FunctionsBuilder from "components/Settings/ProjectSettings/FunctionsBuilder";
import { SETTINGS, PUBLIC_SETTINGS } from "config/dbPaths";
import useDoc from "hooks/useDoc";
@@ -12,6 +12,7 @@ import { db } from "@src/firebase";
import { useSnackContext } from "contexts/SnackContext";
import { useDebouncedCallback } from "use-debounce";
import { useEffect } from "react";
import { name } from "@root/package.json";
export interface IProjectSettingsChildProps {
settings: Record<string, any>;
@@ -81,12 +82,12 @@ export default function ProjectSettings() {
<About />
</SettingsSection>
<SettingsSection title="Authentication">
<Authentication {...childProps} />
<SettingsSection title={`${name} Run`}>
<CloudRun {...childProps} />
</SettingsSection>
<SettingsSection title="Functions Builder">
<FunctionsBuilder {...childProps} />
<SettingsSection title="Authentication">
<Authentication {...childProps} />
</SettingsSection>
</Stack>
)}

View File

@@ -20,9 +20,6 @@ import useRouter from "hooks/useRouter";
import { DocActions } from "hooks/useDoc";
import ActionParamsProvider from "components/fields/Action/FormDialog/Provider";
import { name } from "@root/package.json";
import { projectId } from "@src/firebase";
export default function TablePage() {
const router = useRouter();
const tableCollection = decodeURIComponent(router.match.params.id);
@@ -36,16 +33,8 @@ export default function TablePage() {
tableCollection?.split("/")[0],
])?.section;
const currentTable = tableCollection?.split("/")[0];
useEffect(() => {
const tableName =
_find(tables, ["collection", currentTable])?.name || currentTable;
document.title = `${tableName} | ${projectId} | ${name}`;
return () => {
document.title = `${projectId} | ${name}`;
};
}, [currentTable]);
const tableName =
_find(tables, ["collection", currentTable])?.name || currentTable;
let filters: RowyFilter[] = [];
const parsed = queryString.parse(router.location.search);
@@ -77,9 +66,9 @@ export default function TablePage() {
return (
<Navigation
title={<Breadcrumbs />}
title={tableName}
titleComponent={<Breadcrumbs />}
currentSection={currentSection}
currentTable={currentTable}
>
<ActionParamsProvider>
{tableState.loadingColumns && (