mirror of
https://github.com/rowyio/rowy.git
synced 2026-02-24 04:01:17 +01:00
update react-data-grid, fix side drawer navigation
This commit is contained in:
@@ -42,7 +42,7 @@
|
||||
"react": "^17.0.2",
|
||||
"react-beautiful-dnd": "^13.0.0",
|
||||
"react-color": "^2.17.3",
|
||||
"react-data-grid": "7.0.0-canary.30",
|
||||
"react-data-grid": "^7.0.0-beta.5",
|
||||
"react-div-100vh": "^0.6.0",
|
||||
"react-dnd": "^11.1.3",
|
||||
"react-dnd-html5-backend": "^11.1.3",
|
||||
|
||||
@@ -2,13 +2,19 @@ import React, { useState } from "react";
|
||||
import clsx from "clsx";
|
||||
|
||||
import { makeStyles, createStyles } from "@material-ui/styles";
|
||||
import { Tooltip, TooltipProps, Button, ButtonProps } from "@material-ui/core";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipProps,
|
||||
Typography,
|
||||
Button,
|
||||
ButtonProps,
|
||||
} from "@material-ui/core";
|
||||
|
||||
const useStyles = makeStyles((theme) =>
|
||||
createStyles({
|
||||
tooltip: {
|
||||
backgroundColor: theme.palette.background.default,
|
||||
boxShadow: theme.shadows[2],
|
||||
boxShadow: theme.shadows[8],
|
||||
|
||||
...theme.typography.body2,
|
||||
color: theme.palette.text.primary,
|
||||
@@ -27,42 +33,42 @@ const useStyles = makeStyles((theme) =>
|
||||
cursor: "default",
|
||||
|
||||
display: "grid",
|
||||
gridTemplateColumns: "40px auto",
|
||||
gap: theme.spacing(1, 2),
|
||||
gridTemplateColumns: "48px auto",
|
||||
gap: theme.spacing(1, 1.5),
|
||||
},
|
||||
emoji: {
|
||||
fontSize: `${40 / 16}rem`,
|
||||
fontWeight: 400,
|
||||
fontFamily:
|
||||
"apple color emoji, segoe ui emoji, noto color emoji, android emoji, emojisymbols, emojione mozilla, twemoji mozilla, segoe ui symbol",
|
||||
icon: {
|
||||
marginTop: theme.spacing(-0.5),
|
||||
fontSize: `${48 / 16}rem`,
|
||||
},
|
||||
message: {
|
||||
alignSelf: "center",
|
||||
},
|
||||
dismissButton: {
|
||||
marginLeft: theme.spacing(-1),
|
||||
gridColumn: 2,
|
||||
justifySelf: "flex-start",
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
export interface IRichTooltipProps extends Partial<TooltipProps> {
|
||||
export interface IRichTooltipProps
|
||||
extends Partial<Omit<TooltipProps, "title">> {
|
||||
render: (props: {
|
||||
openTooltip: () => void;
|
||||
closeTooltip: () => void;
|
||||
toggleTooltip: () => void;
|
||||
}) => TooltipProps["children"];
|
||||
|
||||
emoji?: React.ReactNode;
|
||||
message: React.ReactNode;
|
||||
icon?: React.ReactNode;
|
||||
title: React.ReactNode;
|
||||
message?: React.ReactNode;
|
||||
dismissButtonText?: React.ReactNode;
|
||||
dismissButtonProps?: Partial<ButtonProps>;
|
||||
}
|
||||
|
||||
export default function RichTooltip({
|
||||
render,
|
||||
emoji,
|
||||
icon,
|
||||
title,
|
||||
message,
|
||||
dismissButtonText,
|
||||
dismissButtonProps,
|
||||
@@ -86,11 +92,16 @@ export default function RichTooltip({
|
||||
classes={{ tooltip: classes.tooltip, arrow: classes.arrow }}
|
||||
title={
|
||||
<div className={classes.grid} onClick={closeTooltip}>
|
||||
<span className={classes.emoji}>{emoji}</span>
|
||||
<span className={classes.icon}>{icon}</span>
|
||||
|
||||
<div className={classes.message}>{message}</div>
|
||||
<div className={classes.message}>
|
||||
<Typography variant="subtitle2" gutterBottom>
|
||||
{title}
|
||||
</Typography>
|
||||
<Typography>{message}</Typography>
|
||||
</div>
|
||||
|
||||
{dismissButtonText && (
|
||||
{dismissButtonText ? (
|
||||
<Button
|
||||
{...dismissButtonProps}
|
||||
onClick={closeTooltip}
|
||||
@@ -101,6 +112,14 @@ export default function RichTooltip({
|
||||
>
|
||||
{dismissButtonText}
|
||||
</Button>
|
||||
) : (
|
||||
<Typography
|
||||
variant="caption"
|
||||
color="text.disabled"
|
||||
className={classes.dismissButton}
|
||||
>
|
||||
Click to dismiss
|
||||
</Typography>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -45,7 +45,12 @@ export default function SideDrawer() {
|
||||
setCell!((cell) => ({ column: cell!.column, row }));
|
||||
|
||||
const idx = tableState?.columns[cell!.column]?.index;
|
||||
dataGridRef?.current?.selectCell({ rowIdx: row, idx });
|
||||
console.log(
|
||||
"selectCell",
|
||||
{ rowIdx: cell!.row, idx },
|
||||
dataGridRef?.current?.selectCell
|
||||
);
|
||||
dataGridRef?.current?.selectCell({ rowIdx: row, idx }, false);
|
||||
};
|
||||
|
||||
const [urlDocState, dispatchUrlDoc] = useDoc({});
|
||||
|
||||
@@ -1,45 +1,35 @@
|
||||
import clsx from "clsx";
|
||||
import { styled } from "@material-ui/core/styles";
|
||||
import { Box } from "@material-ui/core";
|
||||
import ErrorIcon from "@material-ui/icons/ErrorOutline";
|
||||
import WarningIcon from "@material-ui/icons/WarningAmber";
|
||||
|
||||
import { makeStyles, createStyles } from "@material-ui/styles";
|
||||
import RichTooltip from "components/RichTooltip";
|
||||
|
||||
const useStyles = makeStyles((theme) =>
|
||||
createStyles({
|
||||
root: {
|
||||
"&&": {
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
padding: "var(--cell-padding)",
|
||||
const Root = styled(Box)({
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
padding: "var(--cell-padding)",
|
||||
position: "relative",
|
||||
|
||||
overflow: "hidden",
|
||||
contain: "strict",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
},
|
||||
},
|
||||
overflow: "hidden",
|
||||
contain: "strict",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
});
|
||||
|
||||
isInvalid: {
|
||||
boxShadow: `inset 0 0 0 2px ${theme.palette.error.main}`,
|
||||
},
|
||||
const Dot = styled("div")(({ theme }) => ({
|
||||
position: "absolute",
|
||||
right: -5,
|
||||
top: "50%",
|
||||
transform: "translateY(-50%)",
|
||||
zIndex: 1,
|
||||
|
||||
dot: {
|
||||
position: "absolute",
|
||||
right: -5,
|
||||
top: "50%",
|
||||
transform: "translateY(-50%)",
|
||||
zIndex: 1,
|
||||
width: 12,
|
||||
height: 12,
|
||||
|
||||
width: 12,
|
||||
height: 12,
|
||||
|
||||
borderRadius: "50%",
|
||||
backgroundColor: theme.palette.error.main,
|
||||
},
|
||||
})
|
||||
);
|
||||
borderRadius: "50%",
|
||||
backgroundColor: theme.palette.error.main,
|
||||
}));
|
||||
|
||||
export interface ICellValidationProps
|
||||
extends React.DetailedHTMLProps<
|
||||
@@ -55,13 +45,9 @@ export default function CellValidation({
|
||||
value,
|
||||
required,
|
||||
validationRegex,
|
||||
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: ICellValidationProps) {
|
||||
const classes = useStyles();
|
||||
|
||||
}: // ...props
|
||||
ICellValidationProps) {
|
||||
const isInvalid = validationRegex && !new RegExp(validationRegex).test(value);
|
||||
const isMissing = required && value === undefined;
|
||||
|
||||
@@ -69,20 +55,21 @@ export default function CellValidation({
|
||||
return (
|
||||
<>
|
||||
<RichTooltip
|
||||
emoji="⛔️"
|
||||
message="Invalid data. This row will not be registered to the database until all the required fields are validated."
|
||||
icon={<ErrorIcon fontSize="inherit" color="error" />}
|
||||
title="Invalid Data"
|
||||
message="This row will not be saved until all the required fields contain valid data"
|
||||
placement="right"
|
||||
render={({ openTooltip }) => (
|
||||
<div className={classes.dot} onClick={openTooltip} />
|
||||
)}
|
||||
render={({ openTooltip }) => <Dot onClick={openTooltip} />}
|
||||
/>
|
||||
|
||||
<div
|
||||
{...props}
|
||||
className={clsx(classes.root, classes.isInvalid, className)}
|
||||
<Root
|
||||
// {...props}
|
||||
sx={{
|
||||
boxShadow: (theme) => `inset 0 0 0 2px ${theme.palette.error.main}`,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</Root>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -90,26 +77,29 @@ export default function CellValidation({
|
||||
return (
|
||||
<>
|
||||
<RichTooltip
|
||||
emoji="⚠️"
|
||||
message="Required field. This row will not be registered to the database until all the required fields contain valid data."
|
||||
icon={<WarningIcon fontSize="inherit" color="warning" />}
|
||||
title="Required Field"
|
||||
message="This row will not be saved until all the required fields contain valid data"
|
||||
placement="right"
|
||||
render={({ openTooltip }) => (
|
||||
<div className={classes.dot} onClick={openTooltip} />
|
||||
)}
|
||||
render={({ openTooltip }) => <Dot onClick={openTooltip} />}
|
||||
/>
|
||||
|
||||
<div
|
||||
{...props}
|
||||
className={clsx(classes.root, classes.isInvalid, className)}
|
||||
<Root
|
||||
// {...props}
|
||||
sx={{
|
||||
boxShadow: (theme) => `inset 0 0 0 2px ${theme.palette.error.main}`,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</Root>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<div {...props} className={clsx(classes.root, className)}>
|
||||
<Root
|
||||
// {...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</Root>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useRef } from "react";
|
||||
import clsx from "clsx";
|
||||
import { HeaderRendererProps } from "react-data-grid";
|
||||
import { useDrag, useDrop, DragObjectWithType } from "react-dnd";
|
||||
import { useCombinedRefs } from "react-data-grid/lib/hooks";
|
||||
import useCombinedRefs from "hooks/useCombinedRefs";
|
||||
|
||||
import { makeStyles, createStyles } from "@material-ui/styles";
|
||||
import {
|
||||
@@ -36,9 +36,8 @@ const useStyles = makeStyles((theme) =>
|
||||
|
||||
cursor: "move",
|
||||
|
||||
margin: theme.spacing(0, -1.5),
|
||||
padding: theme.spacing(0, 0.5, 0, 1),
|
||||
width: `calc(100% + ${theme.spacing(1.5 * 2)})`,
|
||||
width: "100%",
|
||||
},
|
||||
isDragging: { opacity: 0.5 },
|
||||
isOver: {
|
||||
@@ -153,20 +152,16 @@ export default function DraggableHeaderRenderer<R>({
|
||||
});
|
||||
};
|
||||
|
||||
const isSorted = orderBy?.[0]?.key === (column.key as string);
|
||||
const isSorted = orderBy?.[0]?.key === column.key;
|
||||
const isAsc = isSorted && orderBy?.[0]?.direction === "asc";
|
||||
|
||||
const handleSortClick = () => {
|
||||
if (isAsc) {
|
||||
const ordering: TableOrder = [
|
||||
{ key: column.key as string, direction: "desc" },
|
||||
];
|
||||
const ordering: TableOrder = [{ key: column.key, direction: "desc" }];
|
||||
|
||||
tableActions.table.orderBy(ordering);
|
||||
} else {
|
||||
const ordering: TableOrder = [
|
||||
{ key: column.key as string, direction: "asc" },
|
||||
];
|
||||
const ordering: TableOrder = [{ key: column.key, direction: "asc" }];
|
||||
tableActions.table.orderBy(ordering);
|
||||
}
|
||||
};
|
||||
@@ -184,13 +179,13 @@ export default function DraggableHeaderRenderer<R>({
|
||||
wrap="nowrap"
|
||||
onContextMenu={handleOpenMenu}
|
||||
>
|
||||
{column.width > 140 && (
|
||||
{(column.width as number) > 140 && (
|
||||
<Tooltip
|
||||
title={
|
||||
<>
|
||||
Click to copy field key:
|
||||
<br />
|
||||
<b>{column.key as string}</b>
|
||||
<b>{column.key}</b>
|
||||
</>
|
||||
}
|
||||
enterDelay={1000}
|
||||
@@ -199,7 +194,7 @@ export default function DraggableHeaderRenderer<R>({
|
||||
<Grid
|
||||
item
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(column.key as string);
|
||||
navigator.clipboard.writeText(column.key);
|
||||
}}
|
||||
>
|
||||
{column.editable === false ? (
|
||||
@@ -215,7 +210,7 @@ export default function DraggableHeaderRenderer<R>({
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography className={classes.columnName} color="inherit">
|
||||
{column.name}
|
||||
{column.name as string}
|
||||
</Typography>
|
||||
}
|
||||
enterDelay={1000}
|
||||
@@ -253,7 +248,7 @@ export default function DraggableHeaderRenderer<R>({
|
||||
component="div"
|
||||
color="inherit"
|
||||
>
|
||||
{column.name}
|
||||
{column.name as string}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
@@ -288,7 +283,7 @@ export default function DraggableHeaderRenderer<R>({
|
||||
<IconButton
|
||||
size="small"
|
||||
className={classes.dropdownButton}
|
||||
aria-label={`Show ${column.name} column dropdown`}
|
||||
aria-label={`Show ${column.name as string} column dropdown`}
|
||||
color="inherit"
|
||||
onClick={handleOpenMenu}
|
||||
ref={buttonRef}
|
||||
@@ -308,7 +303,7 @@ export default function DraggableHeaderRenderer<R>({
|
||||
// cursor: 'move'
|
||||
// }}
|
||||
// >
|
||||
// {props.column.name}
|
||||
// {props.column.name as string}
|
||||
// </div>
|
||||
// );
|
||||
}
|
||||
|
||||
@@ -291,7 +291,7 @@ export default function ColumnMenu() {
|
||||
{getFieldProp("icon", column.type)}
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={column.name}
|
||||
primary={column.name as string}
|
||||
secondary={
|
||||
<>
|
||||
Key: <span style={{ userSelect: "all" }}>{column.key}</span>
|
||||
|
||||
@@ -13,10 +13,11 @@ const useStyles = makeStyles((theme) =>
|
||||
border: "none",
|
||||
".rdg.rdg &": { padding: theme.spacing(0, 0.75) },
|
||||
|
||||
position: "relative",
|
||||
"&::before": {
|
||||
content: "''",
|
||||
display: "block",
|
||||
width: 46,
|
||||
width: 43,
|
||||
height: "100%",
|
||||
|
||||
position: "absolute",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Stack, Button } from "@material-ui/core";
|
||||
import { Stack, Button, Typography } from "@material-ui/core";
|
||||
|
||||
import { isCollectionGroup } from "utils/fns";
|
||||
import AddRowIcon from "assets/icons/AddRow";
|
||||
@@ -105,6 +105,15 @@ export default function TableHeader() {
|
||||
{/* Spacer */} <div />
|
||||
<HiddenFields />
|
||||
<Filters />
|
||||
{/* Spacer */} <div />
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="text.disabled"
|
||||
display="block"
|
||||
style={{ userSelect: "none" }}
|
||||
>
|
||||
Loaded {tableState.rows.length} rows
|
||||
</Typography>
|
||||
<div style={{ flexGrow: 1, minWidth: 64 }} />
|
||||
<RowHeight />
|
||||
{/* Spacer */} <div />
|
||||
|
||||
@@ -29,7 +29,7 @@ export default function withSideDrawerEditor(
|
||||
<HeavyCell
|
||||
{...(props as any)}
|
||||
value={getCellValue(row, column.key)}
|
||||
name={column.name}
|
||||
name={column.name as string}
|
||||
type={(column as any).type}
|
||||
docRef={props.row.ref}
|
||||
onSubmit={() => {}}
|
||||
|
||||
@@ -13,10 +13,11 @@ const useStyles = makeStyles((theme) =>
|
||||
createStyles({
|
||||
"@global": {
|
||||
".final-column-cell": {
|
||||
".rdg .rdg-cell&": {
|
||||
".rdg.rdg .rdg-cell&": {
|
||||
backgroundColor: "var(--header-background-color)",
|
||||
borderColor: "var(--header-background-color)",
|
||||
color: theme.palette.text.disabled,
|
||||
padding: "var(--cell-padding)",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import React, { useEffect, useRef, useMemo, useState } from "react";
|
||||
import _orderBy from "lodash/orderBy";
|
||||
|
||||
import _find from "lodash/find";
|
||||
import _findIndex from "lodash/findIndex";
|
||||
import _difference from "lodash/difference";
|
||||
import _get from "lodash/get";
|
||||
|
||||
import { DndProvider } from "react-dnd";
|
||||
import { HTML5Backend } from "react-dnd-html5-backend";
|
||||
|
||||
import "react-data-grid/dist/react-data-grid.css";
|
||||
// import "react-data-grid/dist/react-data-grid.css";
|
||||
import DataGrid, {
|
||||
Column,
|
||||
SelectColumn as _SelectColumn,
|
||||
@@ -84,7 +84,11 @@ export default function Table() {
|
||||
return null;
|
||||
},
|
||||
...column,
|
||||
width: column.width ? (column.width > 380 ? 380 : column.width) : 150,
|
||||
width: (column.width as number)
|
||||
? (column.width as number) > 380
|
||||
? 380
|
||||
: (column.width as number)
|
||||
: 150,
|
||||
}))
|
||||
.filter((column) => !userDocHiddenFields.includes(column.key));
|
||||
|
||||
@@ -95,7 +99,7 @@ export default function Table() {
|
||||
{
|
||||
isNew: true,
|
||||
key: "new",
|
||||
name: "Add column",
|
||||
name: "Add Column",
|
||||
type: FieldType.last,
|
||||
index: _columns.length ?? 0,
|
||||
width: 204,
|
||||
@@ -119,7 +123,7 @@ export default function Table() {
|
||||
tableState?.rows.map((row) =>
|
||||
columns.reduce(
|
||||
(acc, currColumn) => {
|
||||
if ((currColumn.key as string).includes(".")) {
|
||||
if (currColumn.key.includes(".")) {
|
||||
return {
|
||||
...acc,
|
||||
[currColumn.key]: _get(row, currColumn.key),
|
||||
@@ -208,29 +212,29 @@ export default function Table() {
|
||||
});
|
||||
setSelectedRowsSet(newSelectedSet);
|
||||
}}
|
||||
onRowsChange={() => {
|
||||
//console.log('onRowsChange',rows)
|
||||
}}
|
||||
onFill={(e) => {
|
||||
console.log("onFill", e);
|
||||
const { columnKey, sourceRow, targetRows } = e;
|
||||
if (updateCell)
|
||||
targetRows.forEach((row) =>
|
||||
updateCell(row.ref, columnKey, sourceRow[columnKey])
|
||||
);
|
||||
return [];
|
||||
}}
|
||||
// onRowsChange={() => {
|
||||
//console.log('onRowsChange',rows)
|
||||
// }}
|
||||
// TODO: onFill={(e) => {
|
||||
// console.log("onFill", e);
|
||||
// const { columnKey, sourceRow, targetRows } = e;
|
||||
// if (updateCell)
|
||||
// targetRows.forEach((row) =>
|
||||
// updateCell(row.ref, columnKey, sourceRow[columnKey])
|
||||
// );
|
||||
// return [];
|
||||
// }}
|
||||
onPaste={(e) => {
|
||||
const copiedValue = e.sourceRow[e.sourceColumnKey];
|
||||
if (updateCell) {
|
||||
updateCell(e.targetRow.ref, e.targetColumnKey, copiedValue);
|
||||
}
|
||||
}}
|
||||
onRowClick={(rowIdx, column) => {
|
||||
onRowClick={(row, column) => {
|
||||
if (sideDrawerRef?.current) {
|
||||
sideDrawerRef.current.setCell({
|
||||
row: rowIdx,
|
||||
column: column.key as string,
|
||||
row: _findIndex(tableState.rows, { id: row.id }),
|
||||
column: column.key,
|
||||
});
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -61,10 +61,11 @@ export const useStyles = makeStyles((theme) =>
|
||||
"& .rdg-cell": {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
padding: "var(--cell-padding)",
|
||||
padding: 0,
|
||||
|
||||
overflow: "visible",
|
||||
contain: "none",
|
||||
position: "relative",
|
||||
},
|
||||
|
||||
"& .rdg-cell-frozen-last": {
|
||||
|
||||
@@ -120,7 +120,7 @@ export default function ActionFab({
|
||||
: needsConfirmation
|
||||
? () =>
|
||||
requestConfirmation({
|
||||
title: `${column.name} Confirmation`,
|
||||
title: `${column.name as string} Confirmation`,
|
||||
body: (actionState === "undo" && config.undoConfirmation
|
||||
? config.undoConfirmation
|
||||
: config.confirmation
|
||||
|
||||
@@ -52,7 +52,7 @@ export default function ParamsDialog({
|
||||
return (
|
||||
<FormDialog
|
||||
onClose={handleClose}
|
||||
title={`${column.name}`}
|
||||
title={`${column.name as string}`}
|
||||
fields={fields}
|
||||
values={{}}
|
||||
onSubmit={handleRun}
|
||||
|
||||
@@ -59,7 +59,7 @@ export default function Checkbox({
|
||||
color="success"
|
||||
/>
|
||||
}
|
||||
label={column.name}
|
||||
label={column.name as string}
|
||||
labelPlacement="start"
|
||||
classes={{ root: classes.formControlLabel, label: classes.label }}
|
||||
/>
|
||||
|
||||
@@ -68,7 +68,7 @@ export default function Checkbox({
|
||||
return (
|
||||
<FormControlLabel
|
||||
control={component}
|
||||
label={column.name}
|
||||
label={column.name as string}
|
||||
labelPlacement="start"
|
||||
// className="cell-collapse-padding"
|
||||
classes={{ root: classes.root, label: classes.label }}
|
||||
|
||||
@@ -18,7 +18,7 @@ export default function Email({
|
||||
variant="filled"
|
||||
fullWidth
|
||||
margin="none"
|
||||
placeholder={column.name}
|
||||
placeholder={column.name as string}
|
||||
onChange={onChange}
|
||||
onBlur={onBlur}
|
||||
value={value}
|
||||
|
||||
@@ -47,6 +47,7 @@ const useStyles = makeStyles((theme) =>
|
||||
chip: {
|
||||
width: "100%",
|
||||
height: 24,
|
||||
display: "flex",
|
||||
},
|
||||
|
||||
endButtonContainer: {},
|
||||
@@ -78,7 +79,7 @@ export default function File_({
|
||||
if (file) {
|
||||
upload({
|
||||
docRef: row.ref,
|
||||
fieldName: column.key as string,
|
||||
fieldName: column.key,
|
||||
files: [file],
|
||||
previousValue: value,
|
||||
onComplete: (newValue) => {
|
||||
@@ -121,7 +122,7 @@ export default function File_({
|
||||
<input {...getInputProps()} />
|
||||
|
||||
<div className={classes.chipList}>
|
||||
<Grid container spacing={0.5} wrap="nowrap">
|
||||
<Grid container spacing={0.5} wrap="nowrap" style={{ height: "100%" }}>
|
||||
{Array.isArray(value) &&
|
||||
value.map((file: FileValue) => (
|
||||
<Grid
|
||||
|
||||
@@ -132,7 +132,7 @@ export default function Image_({
|
||||
if (imageFile) {
|
||||
upload({
|
||||
docRef: row.ref,
|
||||
fieldName: column.key as string,
|
||||
fieldName: column.key,
|
||||
files: [imageFile],
|
||||
previousValue: value,
|
||||
onComplete: (newValue) => {
|
||||
@@ -184,7 +184,7 @@ export default function Image_({
|
||||
<input {...getInputProps()} />
|
||||
|
||||
<div className={classes.imglistContainer}>
|
||||
<Grid container spacing={1} wrap="nowrap">
|
||||
<Grid container spacing={0.5} wrap="nowrap">
|
||||
{Array.isArray(value) &&
|
||||
value.map((file: FileValue) => (
|
||||
<Grid item key={file.downloadURL}>
|
||||
|
||||
@@ -18,7 +18,7 @@ export default function LongText({
|
||||
variant="filled"
|
||||
fullWidth
|
||||
margin="none"
|
||||
placeholder={column.name}
|
||||
placeholder={column.name as string}
|
||||
onChange={onChange}
|
||||
onBlur={onBlur}
|
||||
value={value}
|
||||
|
||||
@@ -22,8 +22,8 @@ export default function MultiSelect({
|
||||
multiple
|
||||
freeText={config.freeText}
|
||||
disabled={disabled}
|
||||
label={column.name}
|
||||
labelPlural={column.name}
|
||||
label={column.name as string}
|
||||
labelPlural={column.name as string}
|
||||
TextFieldProps={{
|
||||
style: { display: "none" },
|
||||
SelectProps: {
|
||||
|
||||
@@ -20,7 +20,7 @@ export default function Number_({
|
||||
variant="filled"
|
||||
fullWidth
|
||||
margin="none"
|
||||
placeholder={column.name}
|
||||
placeholder={column.name as string}
|
||||
onChange={handleChange}
|
||||
onBlur={onBlur}
|
||||
value={value}
|
||||
|
||||
@@ -47,7 +47,7 @@ export default function Percentage({
|
||||
variant="filled"
|
||||
fullWidth
|
||||
margin="none"
|
||||
placeholder={column.name}
|
||||
placeholder={column.name as string}
|
||||
onChange={handleChange}
|
||||
onBlur={onBlur}
|
||||
value={typeof value === "number" ? value * 100 : value}
|
||||
|
||||
@@ -18,7 +18,7 @@ export default function Phone({
|
||||
variant="filled"
|
||||
fullWidth
|
||||
margin="none"
|
||||
placeholder={column.name}
|
||||
placeholder={column.name as string}
|
||||
onChange={onChange}
|
||||
onBlur={onBlur}
|
||||
value={value}
|
||||
|
||||
@@ -37,7 +37,7 @@ export default function Rating({
|
||||
render={({ onChange, value }) => (
|
||||
<Grid container alignItems="center" className={fieldClasses.root}>
|
||||
<MuiRating
|
||||
name={column.key as string}
|
||||
name={column.key}
|
||||
id={`sidedrawer-field-${column.key}`}
|
||||
value={typeof value === "number" ? value : 0}
|
||||
disabled={disabled}
|
||||
|
||||
@@ -29,7 +29,7 @@ export default function Rating({
|
||||
|
||||
return (
|
||||
<MuiRating
|
||||
name={`${row.id}-${column.key as string}`}
|
||||
name={`${row.id}-${column.key}`}
|
||||
value={typeof value === "number" ? value : 0}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
disabled={disabled}
|
||||
|
||||
@@ -53,7 +53,7 @@ const useStyles = makeStyles((theme) =>
|
||||
export default function RichText({ column, value }: IHeavyCellProps) {
|
||||
const { tableState } = useProjectContext();
|
||||
const classes = useStyles({
|
||||
width: column.width,
|
||||
width: column.width as number,
|
||||
rowHeight: tableState?.config?.rowHeight ?? 44,
|
||||
});
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ export default function ShortText({
|
||||
variant="filled"
|
||||
fullWidth
|
||||
margin="none"
|
||||
placeholder={column.name}
|
||||
placeholder={column.name as string}
|
||||
onChange={onChange}
|
||||
onBlur={onBlur}
|
||||
value={value}
|
||||
|
||||
@@ -22,8 +22,8 @@ export default function SingleSelect({
|
||||
multiple={false}
|
||||
freeText={config.freeText}
|
||||
disabled={disabled}
|
||||
label={column.name}
|
||||
labelPlural={column.name}
|
||||
label={column.name as string}
|
||||
labelPlural={column.name as string}
|
||||
TextFieldProps={{
|
||||
style: { display: "none" },
|
||||
SelectProps: {
|
||||
|
||||
@@ -25,7 +25,7 @@ export default function SubTable({
|
||||
return (
|
||||
<Grid container wrap="nowrap">
|
||||
<div className={fieldClasses.root}>
|
||||
{documentCount} {column.name}: {label}
|
||||
{documentCount} {column.name as string}: {label}
|
||||
</div>
|
||||
|
||||
<IconButton
|
||||
|
||||
@@ -34,7 +34,7 @@ export default function SubTable({ column, row }: IHeavyCellProps) {
|
||||
className={clsx("cell-collapse-padding", classes.root)}
|
||||
>
|
||||
<Grid item xs className={classes.labelContainer}>
|
||||
{documentCount} {column.name}: {label}
|
||||
{documentCount} {column.name as string}: {label}
|
||||
</Grid>
|
||||
|
||||
<Grid item>
|
||||
|
||||
@@ -15,7 +15,7 @@ export const useSubTableData = (
|
||||
else return row[curr];
|
||||
}, "")
|
||||
: "";
|
||||
const fieldName = column.key as string;
|
||||
const fieldName = column.key;
|
||||
const documentCount: string = row[fieldName]?.count ?? "";
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
@@ -20,7 +20,7 @@ export default function Url({
|
||||
variant="filled"
|
||||
fullWidth
|
||||
margin="none"
|
||||
placeholder={column.name}
|
||||
placeholder={column.name as string}
|
||||
onChange={onChange}
|
||||
onBlur={onBlur}
|
||||
value={value}
|
||||
|
||||
@@ -29,7 +29,7 @@ export default function withBasicCell(
|
||||
>
|
||||
<BasicCellComponent
|
||||
value={value}
|
||||
name={name}
|
||||
name={name as string}
|
||||
type={(props.column as any).type as FieldType}
|
||||
/>
|
||||
</CellValidation>
|
||||
|
||||
@@ -47,7 +47,7 @@ export default function withHeavyCell(
|
||||
// Declare basicCell here so props can be reused by HeavyCellComponent
|
||||
const basicCellProps = {
|
||||
value: localValue,
|
||||
name: props.column.name,
|
||||
name: props.column.name as string,
|
||||
type: (props.column as any).type as FieldType,
|
||||
};
|
||||
const basicCell = <BasicCellComponent {...basicCellProps} />;
|
||||
@@ -67,7 +67,7 @@ export default function withHeavyCell(
|
||||
|
||||
const handleSubmit = (value: any) => {
|
||||
if (updateCell && !readOnly) {
|
||||
updateCell(props.row.ref, props.column.key as string, value);
|
||||
updateCell(props.row.ref, props.column.key, value);
|
||||
setLocalValue(value);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -72,7 +72,7 @@ export default function withPopoverCell(
|
||||
const inlineCellRef = useRef<any>(null);
|
||||
|
||||
// TODO: Investigate if this still needs to be a state
|
||||
const value = getCellValue(props.row, props.column.key as string);
|
||||
const value = getCellValue(props.row, props.column.key);
|
||||
const [localValue, setLocalValue] = useState(value);
|
||||
useEffect(() => {
|
||||
setLocalValue(value);
|
||||
@@ -81,7 +81,7 @@ export default function withPopoverCell(
|
||||
// Declare basicCell here so props can be reused by HeavyCellComponent
|
||||
const basicCellProps = {
|
||||
value: localValue,
|
||||
name: props.column.name,
|
||||
name: props.column.name as string,
|
||||
type: (props.column as any).type as FieldType,
|
||||
};
|
||||
|
||||
@@ -100,7 +100,7 @@ export default function withPopoverCell(
|
||||
|
||||
const handleSubmit = (value: any) => {
|
||||
if (updateCell && !options?.readOnly) {
|
||||
updateCell(props.row.ref, props.column.key as string, value);
|
||||
updateCell(props.row.ref, props.column.key, value);
|
||||
setLocalValue(value);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -16,7 +16,7 @@ export interface IFieldConfig {
|
||||
icon?: React.ReactNode;
|
||||
description?: string;
|
||||
setupGuideLink?: string;
|
||||
TableCell: React.ComponentType<FormatterProps>;
|
||||
TableCell: React.ComponentType<FormatterProps<any>>;
|
||||
TableEditor: React.ComponentType<EditorProps<any, any>>;
|
||||
SideDrawerField: React.ComponentType<ISideDrawerFieldProps>;
|
||||
settings?: React.ComponentType<ISettingsProps>;
|
||||
|
||||
43
src/hooks/useCombinedRefs.ts
Normal file
43
src/hooks/useCombinedRefs.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { useCallback, Ref } from "react";
|
||||
|
||||
// From https://github.com/adazzle/react-data-grid/blob/main/src/hooks/useCombinedRefs.ts
|
||||
// The MIT License (MIT)
|
||||
|
||||
// Original work Copyright (c) 2014 Prometheus Research
|
||||
// Modified work Copyright 2015 Adazzle
|
||||
|
||||
// For the original source code please see https://github.com/prometheusresearch-archive/react-grid
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
export default function useCombinedRefs<T>(...refs: readonly Ref<T>[]) {
|
||||
return useCallback(
|
||||
(handle: T | null) => {
|
||||
for (const ref of refs) {
|
||||
if (typeof ref === "function") {
|
||||
ref(handle);
|
||||
} else if (ref !== null) {
|
||||
// @ts-expect-error: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31065
|
||||
ref.current = handle;
|
||||
}
|
||||
}
|
||||
},
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
refs
|
||||
);
|
||||
}
|
||||
13
yarn.lock
13
yarn.lock
@@ -13442,10 +13442,10 @@ react-color@^2.17.3, react-color@^2.19.3:
|
||||
reactcss "^1.2.0"
|
||||
tinycolor2 "^1.4.1"
|
||||
|
||||
react-data-grid@7.0.0-canary.30:
|
||||
version "7.0.0-canary.30"
|
||||
resolved "https://registry.yarnpkg.com/react-data-grid/-/react-data-grid-7.0.0-canary.30.tgz#779cf014abcebc41a4635c22519beb3f183e64c1"
|
||||
integrity sha512-NxGqaHnjHBWTh2eBCae5bb57+N3UBy9DQLnlg3JUZ1ggRnruXDl9Qgci6Xg2XwLdJBC5i0B0F0MbeKTucgArJA==
|
||||
react-data-grid@^7.0.0-beta.5:
|
||||
version "7.0.0-beta.5"
|
||||
resolved "https://registry.yarnpkg.com/react-data-grid/-/react-data-grid-7.0.0-beta.5.tgz#bc39ce45b7a7f42ebfb66840e0ec1c8619d60f10"
|
||||
integrity sha512-rtN4wnePrQ80UN6lYF/zUQqVVJMT3HW5bTLx9nR5XOKQiG72cGzX2d2+b+e82vUh23zTFBicEnuWSlN9Fa/83Q==
|
||||
dependencies:
|
||||
clsx "^1.1.1"
|
||||
|
||||
@@ -13547,6 +13547,11 @@ react-error-overlay@^6.0.9:
|
||||
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a"
|
||||
integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==
|
||||
|
||||
react-fast-compare@^3.1.1:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb"
|
||||
integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==
|
||||
|
||||
react-firebaseui@^5.0.2:
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-firebaseui/-/react-firebaseui-5.0.2.tgz#7496bc595454abdd3e1c10612bb3446cb125181a"
|
||||
|
||||
Reference in New Issue
Block a user