mirror of
https://github.com/rowyio/rowy.git
synced 2025-12-29 00:16:39 +01:00
Merge branch 'develop' into rc
This commit is contained in:
@@ -22,12 +22,11 @@ to start.
|
||||
|
||||
## Working on existing issues
|
||||
|
||||
If you are working on an [issue](https://github.com/rowyio/rowy/issues), share
|
||||
that you are working on it by commenting on the issue and posting a message on
|
||||
#contributions channel in Rowy's
|
||||
[Discord](https://discord.com/invite/fjBugmvzZP). This allows others in the
|
||||
community and the maintainers a chance to provide feedback and guidance before
|
||||
you spend time working on it.
|
||||
If you are working on an [issue](https://github.com/rowyio/rowy/issues), share that you are working on it by commenting on the issue and posting a message on #contributions channel in Rowy's [Discord](https://discord.com/invite/fjBugmvzZP).
|
||||
This allows others in the community and the maintainers a chance to provide feedback and guidance before you spend time working on it.
|
||||
Before you get started working on an [issue](https://github.com/rowyio/rowy/issues), please make sure to share that you are working on it by commenting on the issue and posting a message on #contributions channel in Rowy's [Discord](https://discord.com/invite/fjBugmvzZP). The maintainers will then assign the issue to you after making sure any relevant information or context in addition is provided before you can start on the task.
|
||||
|
||||
Once you are assigned a task, please provide periodic updates or share any questions or roadblocks on either discord or the Github issue, so that the commmunity or the project maintainers can provide you any feedback or guidance as needed. If you are inactive for more than 1-2 week on a issue that was assigned to you, then we will assume you have stopped working on it and we will unassign it from you - so that we can give a chance to others in the community to work on it.
|
||||
|
||||
## File a feature request
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import "tinymce/plugins/image";
|
||||
import "tinymce/plugins/paste";
|
||||
import "tinymce/plugins/help";
|
||||
import "tinymce/plugins/code";
|
||||
import "tinymce/plugins/fullscreen";
|
||||
|
||||
const Styles = styled("div", {
|
||||
shouldForwardProp: (prop) => prop !== "focus",
|
||||
@@ -120,6 +121,10 @@ const Styles = styled("div", {
|
||||
0 0 0 1px ${theme.palette.action.inputOutline} inset`,
|
||||
}
|
||||
: {},
|
||||
"& .tox-tinymce.tox-fullscreen": {
|
||||
zIndex: theme.zIndex.modal,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -149,6 +154,9 @@ export default function RichTextEditor({
|
||||
<GlobalStyles
|
||||
styles={{
|
||||
".tox": {
|
||||
// "& .tox-editor-container": {
|
||||
// backgroundColor: theme.palette.background.paper,
|
||||
// },
|
||||
"& .tox-menu.tox-menu, &.tox-tinymce-aux .tox-toolbar__overflow.tox-toolbar__overflow":
|
||||
{
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
@@ -242,10 +250,16 @@ export default function RichTextEditor({
|
||||
].join("\n"),
|
||||
minHeight: 300,
|
||||
menubar: false,
|
||||
plugins: ["autoresize", "lists link image", "paste help", "code"],
|
||||
plugins: [
|
||||
"fullscreen",
|
||||
"autoresize",
|
||||
"lists link image",
|
||||
"paste help",
|
||||
"code",
|
||||
],
|
||||
statusbar: false,
|
||||
toolbar:
|
||||
"formatselect | bold italic forecolor | link | bullist numlist outdent indent | removeformat code | help",
|
||||
"formatselect | bold italic forecolor | link | fullscreen | bullist numlist outdent indent | removeformat code | help",
|
||||
body_id: id,
|
||||
}}
|
||||
value={value}
|
||||
|
||||
@@ -7,6 +7,10 @@ import {
|
||||
getCoreRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table";
|
||||
import type {
|
||||
ColumnPinningState,
|
||||
VisibilityState,
|
||||
} from "@tanstack/react-table";
|
||||
import { DropResult } from "react-beautiful-dnd";
|
||||
import { get } from "lodash-es";
|
||||
|
||||
@@ -15,7 +19,6 @@ import TableHeader from "./TableHeader";
|
||||
import TableBody from "./TableBody";
|
||||
import FinalColumn from "./FinalColumn/FinalColumn";
|
||||
import ContextMenu from "./ContextMenu";
|
||||
|
||||
import EmptyState from "@src/components/EmptyState";
|
||||
// import BulkActions from "./BulkActions";
|
||||
|
||||
@@ -28,11 +31,10 @@ import {
|
||||
tablePageAtom,
|
||||
updateColumnAtom,
|
||||
} from "@src/atoms/tableScope";
|
||||
|
||||
import { getFieldType, getFieldProp } from "@src/components/fields";
|
||||
import { TableRow, ColumnConfig } from "@src/types/table";
|
||||
import { useKeyboardNavigation } from "./useKeyboardNavigation";
|
||||
import { useSaveColumnSizing } from "./useSaveColumnSizing";
|
||||
import type { TableRow, ColumnConfig } from "@src/types/table";
|
||||
|
||||
export const DEFAULT_ROW_HEIGHT = 41;
|
||||
export const DEFAULT_COL_WIDTH = 150;
|
||||
@@ -130,20 +132,24 @@ export default function Table({
|
||||
}, [tableColumnsOrdered, canAddColumns, canEditCells]);
|
||||
|
||||
// Get user’s hidden columns from props and memoize into a `VisibilityState`
|
||||
const columnVisibility = useMemo(() => {
|
||||
const columnVisibility: VisibilityState = useMemo(() => {
|
||||
if (!Array.isArray(hiddenColumns)) return {};
|
||||
return hiddenColumns.reduce((a, c) => ({ ...a, [c]: false }), {});
|
||||
}, [hiddenColumns]);
|
||||
|
||||
// Get frozen columns and memoize into a `ColumnPinningState`
|
||||
const columnPinning = useMemo(
|
||||
const columnPinning: ColumnPinningState = useMemo(
|
||||
() => ({
|
||||
left: columns.filter((c) => c.meta?.fixed && c.id).map((c) => c.id!),
|
||||
left: columns
|
||||
.filter(
|
||||
(c) => c.meta?.fixed && c.id && columnVisibility[c.id] !== false
|
||||
)
|
||||
.map((c) => c.id!),
|
||||
}),
|
||||
[columns]
|
||||
[columns, columnVisibility]
|
||||
);
|
||||
const lastFrozen: string | undefined =
|
||||
columnPinning.left[columnPinning.left.length - 1];
|
||||
columnPinning.left![columnPinning.left!.length - 1];
|
||||
|
||||
// Call TanStack Table
|
||||
const table = useReactTable({
|
||||
|
||||
@@ -68,11 +68,11 @@ export function useVirtualization(
|
||||
const columnDef = leafColumns[index].columnDef;
|
||||
const schemaWidth = columnDef.size;
|
||||
const localWidth = columnSizing[columnDef.id || ""];
|
||||
const definedWidth = localWidth || schemaWidth;
|
||||
|
||||
return Math.max(
|
||||
MIN_COL_WIDTH,
|
||||
localWidth || schemaWidth || DEFAULT_COL_WIDTH
|
||||
);
|
||||
if (definedWidth === undefined) return DEFAULT_COL_WIDTH;
|
||||
if (definedWidth < MIN_COL_WIDTH) return MIN_COL_WIDTH;
|
||||
return definedWidth;
|
||||
},
|
||||
[leafColumns, columnSizing]
|
||||
),
|
||||
|
||||
@@ -105,7 +105,7 @@ export default function BuildLogsSnack({
|
||||
p: 2,
|
||||
pt: 1,
|
||||
borderRadius: 1,
|
||||
zIndex: 1,
|
||||
zIndex: (theme) => theme.zIndex.snackbar,
|
||||
transition: (theme) => theme.transitions.create("height"),
|
||||
height: expanded ? "calc(100% - 300px)" : 50,
|
||||
}}
|
||||
|
||||
@@ -1,12 +1,26 @@
|
||||
import { useEffect, useRef, useMemo, useState } from "react";
|
||||
import { useAtom } from "jotai";
|
||||
import {
|
||||
useEffect,
|
||||
useRef,
|
||||
useMemo,
|
||||
useState,
|
||||
forwardRef,
|
||||
ChangeEvent,
|
||||
} 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 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";
|
||||
@@ -16,7 +30,11 @@ import {
|
||||
userSettingsAtom,
|
||||
updateUserSettingsAtom,
|
||||
} from "@src/atoms/projectScope";
|
||||
import { tableScope, tableIdAtom } from "@src/atoms/tableScope";
|
||||
import {
|
||||
tableScope,
|
||||
tableIdAtom,
|
||||
updateColumnAtom,
|
||||
} from "@src/atoms/tableScope";
|
||||
import { formatSubTableName } from "@src/utils/table";
|
||||
|
||||
export default function HiddenFields() {
|
||||
@@ -57,6 +75,9 @@ export default function HiddenFields() {
|
||||
}
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
// disable drag if search box is not empty
|
||||
const [disableDrag, setDisableDrag] = useState<boolean>(false);
|
||||
const renderOption: AutocompleteProps<
|
||||
any,
|
||||
true,
|
||||
@@ -67,49 +88,119 @@ export default function HiddenFields() {
|
||||
colord(theme.palette.background.paper)
|
||||
.mix("#fff", theme.palette.mode === "dark" ? 0.16 : 0)
|
||||
.alpha(1);
|
||||
|
||||
return (
|
||||
<li {...props}>
|
||||
<ColumnItem option={option}>
|
||||
<Box
|
||||
sx={[
|
||||
{ position: "relative", height: "1.5rem" },
|
||||
selected
|
||||
? { color: "primary.main" }
|
||||
: {
|
||||
opacity: 0,
|
||||
".MuiAutocomplete-option.Mui-focused &": { opacity: 0.5 },
|
||||
<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: (theme) =>
|
||||
disableDrag ? theme.palette.action.disabledOpacity : 1,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<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>
|
||||
]}
|
||||
/>
|
||||
</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);
|
||||
|
||||
// updates column on drag end
|
||||
function handleOnDragEnd(result: DropResult) {
|
||||
if (!result.destination) return;
|
||||
updateColumn({
|
||||
key: result.draggableId,
|
||||
config: {},
|
||||
index: result.destination.index,
|
||||
});
|
||||
}
|
||||
|
||||
// checks whether to disable reordering when search filter is applied
|
||||
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
|
||||
@@ -123,6 +214,7 @@ export default function HiddenFields() {
|
||||
<ColumnSelect
|
||||
TextFieldProps={{
|
||||
style: { display: "none" },
|
||||
onInput: checkToDisableDrag,
|
||||
SelectProps: {
|
||||
open,
|
||||
MenuProps: {
|
||||
@@ -138,11 +230,19 @@ export default function HiddenFields() {
|
||||
},
|
||||
},
|
||||
}}
|
||||
{...{ AutocompleteProps: { renderOption } }}
|
||||
{...{
|
||||
AutocompleteProps: {
|
||||
renderOption,
|
||||
ListboxComponent,
|
||||
},
|
||||
}}
|
||||
label="Hidden fields"
|
||||
labelPlural="fields"
|
||||
value={hiddenFields ?? []}
|
||||
onChange={setHiddenFields}
|
||||
onChange={(updates: string[]) => {
|
||||
setHiddenFields(updates);
|
||||
setDisableDrag(false);
|
||||
}}
|
||||
onClose={handleSave}
|
||||
clearText="Show all"
|
||||
selectAllText="Hide all"
|
||||
|
||||
@@ -215,7 +215,7 @@ export function useFirestoreCollectionWithAtom<T = TableRow>(
|
||||
setDataAtom([]);
|
||||
suspended = false;
|
||||
}
|
||||
if (nextPageAtom) setNextPageAtom({ loading: false, available: true });
|
||||
if (nextPageAtom) setNextPageAtom({ loading: false, available: false });
|
||||
if (onError) onError(error);
|
||||
else handleError(error);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user