mirror of
https://github.com/rowyio/rowy.git
synced 2025-12-29 00:16:39 +01:00
Merge branch 'anishroy' of https://github.com/iamanishroy/rowy into develop
This commit is contained in:
252
src/components/TableToolbar/ManageColumns.tsx
Normal file
252
src/components/TableToolbar/ManageColumns.tsx
Normal file
@@ -0,0 +1,252 @@
|
||||
import {
|
||||
useEffect,
|
||||
useRef,
|
||||
useMemo,
|
||||
useState,
|
||||
ChangeEvent,
|
||||
forwardRef,
|
||||
} from "react";
|
||||
import { useAtom, useSetAtom } from "jotai";
|
||||
import { isEqual } from "lodash-es";
|
||||
import { colord } from "colord";
|
||||
import {
|
||||
DragDropContext,
|
||||
Droppable,
|
||||
Draggable,
|
||||
DropResult,
|
||||
} from "react-beautiful-dnd";
|
||||
|
||||
import { Box, AutocompleteProps, Theme } from "@mui/material";
|
||||
import VisibilityIcon from "@mui/icons-material/VisibilityOutlined";
|
||||
// import VisibilityOffIcon from "@mui/icons-material/VisibilityOffOutlined";
|
||||
import ViewColumnOutlinedIcon from "@mui/icons-material/ViewColumnOutlined";
|
||||
import IconSlash from "@src/components/IconSlash";
|
||||
import DragIndicatorOutlinedIcon from "@mui/icons-material/DragIndicatorOutlined";
|
||||
|
||||
import ColumnSelect, { ColumnItem } from "@src/components/Table/ColumnSelect";
|
||||
import ButtonWithStatus from "@src/components/ButtonWithStatus";
|
||||
|
||||
import {
|
||||
globalScope,
|
||||
userSettingsAtom,
|
||||
updateUserSettingsAtom,
|
||||
} from "@src/atoms/globalScope";
|
||||
import {
|
||||
tableScope,
|
||||
tableIdAtom,
|
||||
updateColumnAtom,
|
||||
} from "@src/atoms/tableScope";
|
||||
import { formatSubTableName } from "@src/utils/table";
|
||||
|
||||
export default function ManageColumns() {
|
||||
const buttonRef = useRef<HTMLButtonElement>(null);
|
||||
|
||||
const [userSettings] = useAtom(userSettingsAtom, globalScope);
|
||||
const [tableId] = useAtom(tableIdAtom, tableScope);
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
// Store local selection here
|
||||
// Initialize hiddenFields from user doc
|
||||
const userDocHiddenFields = useMemo(
|
||||
() =>
|
||||
userSettings.tables?.[formatSubTableName(tableId)]?.hiddenFields ?? [],
|
||||
[userSettings.tables, tableId]
|
||||
);
|
||||
|
||||
const [hiddenFields, setHiddenFields] =
|
||||
useState<string[]>(userDocHiddenFields);
|
||||
useEffect(() => {
|
||||
setHiddenFields(userDocHiddenFields);
|
||||
}, [userDocHiddenFields]);
|
||||
|
||||
// const tableColumns = tableColumnsOrdered.map(({ key, name }) => ({
|
||||
// value: key,
|
||||
// label: name,
|
||||
// }));
|
||||
|
||||
// Save when MultiSelect closes
|
||||
const [updateUserSettings] = useAtom(updateUserSettingsAtom, globalScope);
|
||||
const handleSave = () => {
|
||||
// Only update if there were any changes because it’s slow to update
|
||||
if (!isEqual(hiddenFields, userDocHiddenFields) && updateUserSettings) {
|
||||
updateUserSettings({
|
||||
tables: { [formatSubTableName(tableId)]: { hiddenFields } },
|
||||
});
|
||||
}
|
||||
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
// disable drag if search box is not empty
|
||||
const [disableDrag, setDisableDrag] = useState<boolean>(false);
|
||||
|
||||
const renderOption: AutocompleteProps<
|
||||
any,
|
||||
true,
|
||||
false,
|
||||
any
|
||||
>["renderOption"] = (props, option, { selected }) => {
|
||||
const slashColor = (theme: Theme) =>
|
||||
colord(theme.palette.background.paper)
|
||||
.mix("#fff", theme.palette.mode === "dark" ? 0.16 : 0)
|
||||
.alpha(1);
|
||||
return (
|
||||
<Draggable
|
||||
draggableId={option.value}
|
||||
index={option.index}
|
||||
isDragDisabled={disableDrag}
|
||||
>
|
||||
{(provided) => (
|
||||
<li {...props} ref={provided.innerRef} {...provided.draggableProps}>
|
||||
<Box
|
||||
sx={[{ position: "relative", height: "1.5rem" }]}
|
||||
{...provided.dragHandleProps}
|
||||
>
|
||||
<DragIndicatorOutlinedIcon
|
||||
color="disabled"
|
||||
sx={[{ marginRight: "6px", opacity: disableDrag ? 0.6 : 1 }]}
|
||||
/>
|
||||
</Box>
|
||||
<ColumnItem option={option}>
|
||||
<Box
|
||||
sx={[
|
||||
{ position: "relative", height: "1.5rem" },
|
||||
selected
|
||||
? { color: "primary.main" }
|
||||
: {
|
||||
opacity: 0,
|
||||
".MuiAutocomplete-option.Mui-focused &": {
|
||||
opacity: 0.5,
|
||||
},
|
||||
},
|
||||
]}
|
||||
>
|
||||
<VisibilityIcon />
|
||||
<IconSlash
|
||||
sx={[
|
||||
{
|
||||
"& .icon-slash-mask": {
|
||||
stroke: (theme) => slashColor(theme).toHslString(),
|
||||
},
|
||||
".Mui-focused & .icon-slash-mask": {
|
||||
stroke: (theme) =>
|
||||
slashColor(theme)
|
||||
.mix(
|
||||
theme.palette.primary.main,
|
||||
theme.palette.action.selectedOpacity +
|
||||
theme.palette.action.hoverOpacity
|
||||
)
|
||||
.alpha(1)
|
||||
.toHslString(),
|
||||
},
|
||||
},
|
||||
selected ? { strokeDashoffset: 0 } : {},
|
||||
]}
|
||||
/>
|
||||
</Box>
|
||||
</ColumnItem>
|
||||
</li>
|
||||
)}
|
||||
</Draggable>
|
||||
);
|
||||
};
|
||||
|
||||
const updateColumn = useSetAtom(updateColumnAtom, tableScope);
|
||||
function handleOnDragEnd(result: DropResult) {
|
||||
if (!result.destination) return;
|
||||
updateColumn({
|
||||
key: result.draggableId,
|
||||
config: {},
|
||||
index: result.destination.index,
|
||||
});
|
||||
}
|
||||
|
||||
function checkToDisableDrag(e: ChangeEvent<HTMLInputElement>) {
|
||||
setDisableDrag(e.target.value !== "");
|
||||
}
|
||||
|
||||
const ListboxComponent = forwardRef(function ListboxComponent(
|
||||
props: React.HTMLAttributes<HTMLElement>,
|
||||
ulRef: any /*React.ForwardedRef<HTMLUListElement>*/
|
||||
) {
|
||||
const { children, ...other } = props;
|
||||
|
||||
return (
|
||||
<DragDropContext onDragEnd={handleOnDragEnd}>
|
||||
<Droppable droppableId="columns_manager" direction="vertical">
|
||||
{(provided) => (
|
||||
<ul
|
||||
{...other}
|
||||
{...provided.droppableProps}
|
||||
ref={(ref) => {
|
||||
provided.innerRef(ref);
|
||||
if (ulRef !== null) {
|
||||
ulRef(ref);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
{provided.placeholder}
|
||||
</ul>
|
||||
)}
|
||||
</Droppable>
|
||||
</DragDropContext>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<ButtonWithStatus
|
||||
startIcon={<ViewColumnOutlinedIcon />}
|
||||
onClick={() => setOpen((o) => !o)}
|
||||
active={hiddenFields.length > 0}
|
||||
ref={buttonRef}
|
||||
>
|
||||
{"Columns"}
|
||||
</ButtonWithStatus>
|
||||
|
||||
<ColumnSelect
|
||||
TextFieldProps={{
|
||||
style: { display: "none" },
|
||||
onInput: checkToDisableDrag,
|
||||
SelectProps: {
|
||||
open,
|
||||
MenuProps: {
|
||||
anchorEl: buttonRef.current,
|
||||
anchorOrigin: { vertical: "bottom", horizontal: "left" },
|
||||
transformOrigin: { vertical: "top", horizontal: "left" },
|
||||
sx: {
|
||||
"& .MuiAutocomplete-listbox .MuiAutocomplete-option[aria-selected=true]":
|
||||
{
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
{...{
|
||||
AutocompleteProps: {
|
||||
renderOption,
|
||||
ListboxComponent,
|
||||
// ListboxProps: {
|
||||
// ...provided.droppableProps,
|
||||
// ref: provided.innerRef,
|
||||
// },
|
||||
},
|
||||
}}
|
||||
label="Hidden fields"
|
||||
labelPlural="fields"
|
||||
value={hiddenFields ?? []}
|
||||
onChange={(updates: string[]) => {
|
||||
setHiddenFields(updates);
|
||||
setDisableDrag(false);
|
||||
}}
|
||||
onClose={handleSave}
|
||||
clearText="Show all"
|
||||
selectAllText="Hide all"
|
||||
doneText="Apply"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -14,7 +14,8 @@ import { ButtonSkeleton } from "./TableToolbarSkeleton";
|
||||
import AddRow from "./AddRow";
|
||||
import LoadedRowsStatus from "./LoadedRowsStatus";
|
||||
import TableSettings from "./TableSettings";
|
||||
import HiddenFields from "./HiddenFields";
|
||||
// import HiddenFields from "./HiddenFields";
|
||||
import ManageColumns from "./ManageColumns";
|
||||
import RowHeight from "./RowHeight";
|
||||
import TableInformation from "./TableInformation";
|
||||
|
||||
@@ -89,7 +90,8 @@ export default function TableToolbar() {
|
||||
>
|
||||
<AddRow />
|
||||
<div /> {/* Spacer */}
|
||||
<HiddenFields />
|
||||
{/* <HiddenFields /> */}
|
||||
<ManageColumns />
|
||||
<Suspense fallback={<ButtonSkeleton />}>
|
||||
<Filters />
|
||||
</Suspense>
|
||||
|
||||
Reference in New Issue
Block a user