Merge branch 'canary-react-data-grid' of https://github.com/AntlerVC/firetable into canary-react-data-grid

This commit is contained in:
Shams mosowi
2020-11-02 12:36:50 +11:00
5 changed files with 213 additions and 162 deletions

View File

@@ -37,10 +37,9 @@ const useStyles = makeStyles((theme) =>
// divider: { margin: theme.spacing(1, 2) },
secondaryAction: { pointerEvents: "none" },
secondaryIcon: {
display: "block",
pointerEvents: "none",
color: theme.palette.action.active,
},
})
@@ -114,7 +113,7 @@ export default function UserMenu(props: IconButtonProps) {
<MenuItem onClick={handleToggleTheme}>
Dark Theme
<ListItemSecondaryAction>
<ListItemSecondaryAction className={classes.secondaryAction}>
{theme === "light" ? (
<CheckBoxOutlineBlankIcon className={classes.secondaryIcon} />
) : (

View File

@@ -16,6 +16,7 @@ import { useStyles } from "./useStyles";
import { useFiretableContext } from "contexts/firetableContext";
import { FieldType } from "constants/fields";
import useDoc from "hooks/useDoc";
export const DRAWER_WIDTH = 600;
export const DRAWER_COLLAPSED_WIDTH = 36;

View File

@@ -1,84 +1,118 @@
import React from "react";
import { Theme, createStyles, makeStyles } from "@material-ui/core/styles";
import Paper from "@material-ui/core/Paper";
import Typography from "@material-ui/core/Typography";
import Tooltip from "@material-ui/core/Tooltip";
import _find from "lodash/find";
import {
createStyles,
makeStyles,
fade,
Grow,
Paper,
Grid,
Tooltip,
IconButton,
Typography,
TextField,
MenuItem,
} from "@material-ui/core";
import ClickAwayListener from "@material-ui/core/ClickAwayListener";
import Grow from "@material-ui/core/Grow";
import Grid from "@material-ui/core/Grid";
import Popper from "@material-ui/core/Popper";
import MenuItem from "@material-ui/core/MenuItem";
import MenuList from "@material-ui/core/MenuList";
import Button from "@material-ui/core/Button";
import IconButton from "@material-ui/core/IconButton";
import CopyCellsIcon from "assets/icons/CopyCells";
import ClearSelectionIcon from "@material-ui/icons/IndeterminateCheckBox";
import DeleteIcon from "@material-ui/icons/DeleteForever";
import DropdownIcon from "@material-ui/icons/ArrowDropDown";
import ArrowDropUpIcon from "@material-ui/icons/ArrowDropUp";
import { useConfirmation } from "components/ConfirmationDialog/Context";
import { useFiretableContext } from "contexts/firetableContext";
import { useSnackContext } from "contexts/snackContext";
import { sanitiseRowData } from "utils/fns";
import { formatPath, asyncForEach } from "../../../utils/fns";
import { sanitiseRowData, formatPath, asyncForEach } from "utils/fns";
import { cloudFunction } from "firebase/callables";
import _find from "lodash/find";
const useStyles = makeStyles((theme: Theme) =>
const useStyles = makeStyles((theme) =>
createStyles({
root: {
position: "absolute",
bottom: 10,
right: 30,
position: "fixed",
bottom: theme.spacing(2),
left: "50%",
transform: "translateX(-50%)",
},
paper: {
padding: theme.spacing(2),
cornerRadius: 32,
paper: {
height: 64,
borderRadius: 32,
padding: theme.spacing(0, 1),
[theme.breakpoints.up("lg")]: { paddingRight: theme.spacing(2) },
zIndex: theme.zIndex.modal,
backgroundColor:
theme.palette.type === "light"
? theme.palette.background.default
: theme.palette.background.elevation?.[12] ??
theme.palette.background.default,
width: 470,
maxWidth: "100vw",
overflowX: "auto",
},
grid: {
height: "100%",
marginTop: 0,
marginBottom: 0,
},
spacer: { width: theme.spacing(2) },
selectedContainer: {
flexBasis: 206,
flexShrink: 0,
},
selected: {
color: theme.palette.text.disabled,
fontFeatureSettings: '"tnum"',
userSelect: "none",
display: "inline-block",
marginRight: theme.spacing(1),
minWidth: 150,
},
dropdown: {
minWidth: 120,
margin: 0,
},
inputBaseRoot: {
borderRadius: theme.shape.borderRadius,
backgroundColor:
theme.palette.type === "dark"
? fade(theme.palette.text.primary, 0.06)
: undefined,
},
dropdownLabel: {
left: theme.spacing(1.5),
top: "50%",
transform: "translateY(-50%) !important",
...theme.typography.body1,
},
dropdownLabelFocused: {
"$dropdownLabel&": { color: theme.palette.text.primary },
},
select: {
paddingTop: "6px !important",
paddingBottom: "7px !important",
},
dropdownMenu: { marginTop: theme.spacing(-3) },
})
);
export default function BulkActions({ selectedRows, columns, clearSelection }) {
const { requestConfirmation } = useConfirmation();
const { tableActions, tableState } = useFiretableContext();
const snack = useSnackContext();
const classes = useStyles();
const [open, setOpen] = React.useState(false);
const anchorRef = React.useRef<HTMLButtonElement>(null);
const handleToggle = () => {
setOpen((prevOpen) => !prevOpen);
};
const { tableActions, tableState } = useFiretableContext();
const handleClose = (event: React.MouseEvent<EventTarget>) => {
if (
anchorRef.current &&
anchorRef.current.contains(event.target as HTMLElement)
) {
return;
}
const { requestConfirmation } = useConfirmation();
const snack = useSnackContext();
setOpen(false);
};
function handleListKeyDown(event: React.KeyboardEvent) {
if (event.key === "Tab") {
event.preventDefault();
setOpen(false);
}
}
// return focus to the button when we transitioned from !open -> open
const prevOpen = React.useRef(open);
React.useEffect(() => {
if (prevOpen.current === true && open === false) {
anchorRef.current!.focus();
}
prevOpen.current = open;
}, [open]);
const actionColumns = columns
const actionColumns: { name: string; key: string; config: any }[] = columns
.filter((column) => column.type === "ACTION")
.map((column) => ({
name: column.name,
@@ -109,7 +143,10 @@ export default function BulkActions({ selectedRows, columns, clearSelection }) {
clearSelection();
};
const executeAction = async (actionColumn, actionType) => {
const executeAction = async (key: string, actionType: string) => {
const actionColumn = _find(actionColumns, { key });
if (!actionColumn) return;
console.log({ actionColumn, selectedRows, actionType });
const callableName = actionColumn.config.callableName ?? "actionScript";
@@ -148,109 +185,121 @@ export default function BulkActions({ selectedRows, columns, clearSelection }) {
);
});
};
const numberOfSelectedRows = selectedRows.length;
if (numberOfSelectedRows === 0) return null;
const numSelected = selectedRows.length;
return (
<div className={classes.root}>
<Paper elevation={5} className={classes.paper}>
<Grid direction="row" container alignItems="center">
<IconButton
size="medium"
color="inherit"
onClick={clearSelection}
aria-label="Duplicate selected rows"
<Grow in={numSelected > 0}>
<Paper elevation={8} className={classes.paper}>
<Grid
container
alignItems="center"
wrap="nowrap"
className={classes.grid}
>
<ClearSelectionIcon />
</IconButton>
<Typography variant="overline">
{numberOfSelectedRows} rows selected
</Typography>
<Grid item className={classes.selectedContainer}>
<Tooltip title="Clear selection">
<IconButton
color="secondary"
onClick={clearSelection}
aria-label="Clear selection"
>
<ClearSelectionIcon />
</IconButton>
</Tooltip>
<Grid item>
<div>
<Button
color="inherit"
ref={anchorRef}
aria-controls={open ? "menu-list-grow" : undefined}
aria-haspopup="true"
onClick={handleToggle}
<Typography variant="overline" className={classes.selected}>
{numSelected} row{numSelected !== 1 && "s"} selected
</Typography>
</Grid>
<Grid item className={classes.spacer} />
<Grid item>
<TextField
select
variant="filled"
className={classes.dropdown}
onChange={(event) => executeAction(event.target.value, "run")}
margin="dense"
InputProps={{
disableUnderline: true,
classes: { root: classes.inputBaseRoot },
}}
InputLabelProps={{
classes: {
root: classes.dropdownLabel,
focused: classes.dropdownLabelFocused,
},
}}
SelectProps={{
classes: { root: classes.select },
displayEmpty: true,
MenuProps: {
getContentAnchorEl: null,
anchorOrigin: { vertical: "top", horizontal: "left" },
transformOrigin: { vertical: "bottom", horizontal: "left" },
classes: { paper: classes.dropdownMenu },
},
IconComponent: ArrowDropUpIcon,
}}
label={`${actionColumns.length} action${
actionColumns.length !== 1 ? "s" : ""
}`}
>
{actionColumns.length} actions <DropdownIcon />
</Button>
<Popper
open={open}
anchorEl={anchorRef.current}
role={undefined}
transition
disablePortal
>
{({ TransitionProps, placement }) => (
<Grow
{...TransitionProps}
style={{
transformOrigin:
placement === "bottom" ? "center top" : "center bottom",
}}
>
<Paper>
<ClickAwayListener onClickAway={handleClose}>
<MenuList
autoFocusItem={open}
id="menu-list-grow"
onKeyDown={handleListKeyDown}
>
{actionColumns.map((action) => (
<MenuItem
onClick={(e) => {
executeAction(action, "run");
handleClose(e);
}}
>
{action.name}
</MenuItem>
))}
</MenuList>
</ClickAwayListener>
</Paper>
</Grow>
)}
</Popper>
</div>
{actionColumns.map((action) => (
<MenuItem value={action.key}>{action.name}</MenuItem>
))}
</TextField>
</Grid>
<Grid item className={classes.spacer} />
<Grid item>
<Tooltip title="Duplicate rows">
<IconButton
color="secondary"
onClick={() => {
requestConfirmation({
title: "Duplicate Rows?",
body: `Are you sure you want to duplicate the ${numSelected} selected row${
numSelected !== 1 ? "s" : ""
}?`,
confirm: "Duplicate Rows",
handleConfirm: handleDuplicate,
});
}}
aria-label="Duplicate selected rows"
>
<CopyCellsIcon />
</IconButton>
</Tooltip>
</Grid>
<Grid item>
<Tooltip title="Delete rows">
<IconButton
color="secondary"
onClick={() => {
requestConfirmation({
title: "Delete Rows?",
body: `Are you sure you want to delete the ${numSelected} select row${
numSelected !== 1 ? "s" : ""
}?`,
confirm: "Delete Rows",
handleConfirm: handleDelete,
});
}}
aria-label="Delete selected rows"
>
<DeleteIcon />
</IconButton>
</Tooltip>
</Grid>
</Grid>
<IconButton
size="medium"
color="inherit"
onClick={() => {
requestConfirmation({
title: "Duplicate Rows",
body: `Are you sure you want to create duplicate of the ${numberOfSelectedRows} select rows?`,
confirm: "Duplicate",
handleConfirm: handleDuplicate,
});
}}
aria-label="Duplicate selected rows"
>
<CopyCellsIcon />
</IconButton>
<IconButton
size="medium"
color="inherit"
onClick={() => {
requestConfirmation({
title: "Delete Rows",
body: `Are you sure you want to delete the ${numberOfSelectedRows} select rows?`,
confirm: "Delete",
handleConfirm: handleDelete,
});
}}
aria-label="Delete selected rows"
>
<DeleteIcon />
</IconButton>
</Grid>
</Paper>
</Paper>
</Grow>
</div>
);
}

View File

@@ -48,7 +48,7 @@ const useStyles = makeStyles((theme) =>
spacer: { minWidth: theme.spacing(8) },
formControl: {
dropdown: {
minWidth: 120,
margin: theme.spacing(0, 0, 0, -1),
},
@@ -139,7 +139,7 @@ export default function TableHeader({
<TextField
select
variant="filled"
className={classes.formControl}
className={classes.dropdown}
value={rowHeight ?? 43}
onChange={(event) => {
updateConfig("rowHeight", event.target.value);

View File

@@ -11,6 +11,8 @@ export const useStyles = makeStyles((theme) =>
height: `calc(100vh - ${APP_BAR_HEIGHT}px)`,
"& > .rdg": { flex: 1 },
[theme.breakpoints.down("sm")]: { width: "100%" },
},
loadingContainer: {