Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Column width: localstorage fix + sortable column width #289

Open
wants to merge 23 commits into
base: main
Choose a base branch
from

Conversation

MaxiLein
Copy link
Contributor

@MaxiLein MaxiLein commented May 25, 2024

Summary

  • When selecting /deselecting a column, changing the width afterwards resets the elected columns → should work now
  • Sortable column's width wasn't changeable → it is now
  • added min-width for columns (defaults to 150px)

This comment has been minimized.

This comment has been minimized.

This comment has been minimized.

@OhKai
Copy link
Contributor

OhKai commented Jun 3, 2024

This solution is probably not the most react-friendly way to do things. I am also not quite sure, why we need to do it that way. Can we implement the resizing like they do it in the example? https://codesandbox.io/p/sandbox/ant-design-resizable-table-columns-qtbr67?file=%2Fsrc%2FApp.tsx

@MaxiLein MaxiLein marked this pull request as draft June 26, 2024 19:14

This comment has been minimized.

@MaxiLein
Copy link
Contributor Author

Rewrote resizing of columns as requested

Summary

  • used react-resizable for resizing the columns
  • making columns in the ElementList resizeable is still as easy as to use one hook to overwrite the columns, before passing them as prop
  • added feature: if and only if cells of a resizeable column are truncated, the whole cells content is displayed as a tooltip when hoovering over it
Screencast.from.27.06.2024.13.00.29.webm

Details

  • react-resizable does not integrate with antdesign as seamlessly as wished (e.g. width='auto' is not supported)
  • See code comments for more detail
  • caveat: had to overwrite the components={{ header: { cell: ResizableTitle } }} of the antdesign table => using the hook suffices when using elementlist, however, when using the antdesign table, the overwrite is needed as well

@MaxiLein MaxiLein marked this pull request as ready for review June 27, 2024 11:04
@MaxiLein MaxiLein requested a review from OhKai June 27, 2024 11:04
Comment on lines 48 to 72
setTimeout(() => {
/* Hydrating */
/* Replace 'auto' width with actual px values */
const resizeableElements = document.querySelectorAll('.react-resizable');
const widthsOfResizeableElements = Array.from(resizeableElements).map(
(element: any) => element.getBoundingClientRect().width,
);
/* Get the widths */
const widths = columns.map((column: any, index: number) => {
/* Check if not resizeable */
if (notResizeabel.includes(column.key)) return column.width || minWidth;

return widthsOfResizeableElements.shift() || minWidth;
});

/* Replace width */
newColumns = newColumns.map((column: any, index: number) => {
return {
...column,
width: widths[index],
};
});

/* Update UI */
setColumnWidths((old) => ({ ...old, [resizingColumn.current]: newWidth }));
setResizeableColumns(newColumns);
}, 1_000);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a workaround to keep antdesigns 'auto' width. It replaces the auto values with the actual pixel values after everything was rendered.

This comment has been minimized.

{column.title as ReactNode}
const widths = getWidthsOfInnerElements(containerRef.current);

if (widths.some((w) => w > width)) {
Copy link
Contributor Author

@MaxiLein MaxiLein Jun 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this should be adapted in the future, as the total width can be determined by two direct children, that are displayed next to each other (such as the process / folder icon and the title)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, would be good

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed it to also check for elements that are displayed inline (i.e. use the sum of their width)

This comment has been minimized.

This comment has been minimized.

Comment on lines 349 to 353
// components: {
// body: {
// row: DraggableRow,
// },
// },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this now be passed as tableProps?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just forgot to uncomment it again -> removed comments

Comment on lines 51 to 75
setTimeout(() => {
/* Hydrating */
/* Replace 'auto' width with actual px values */
const resizeableElements = document.querySelectorAll('.react-resizable');
const widthsOfResizeableElements = Array.from(resizeableElements).map(
(element: any) => element.getBoundingClientRect().width,
);
/* Get the widths */
const widths = columns.map((column: any, index: number) => {
/* Check if not resizeable */
if (notResizeabel.includes(column.key)) return column.width || minWidth;

return widthsOfResizeableElements.shift() || minWidth;
});

/* Replace width */
newColumns = newColumns.map((column: any, index: number) => {
return {
...column,
width: widths[index],
};
});

const handleMouseMove = useCallback((event: MouseEvent) => {
if (indicatorRef.current) {
indicatorRef.current.style.left = `${event.clientX}px`;
setResizeableColumns(newColumns);
}, 1_000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Timeouts should always have a cleanup returned in an effect. Otherwise this could cause errors when the component unmounts before the delay. You can still use a ref as a flag to mark the update, if you are unable to calculate that from the given values instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added timeout clear as cleanup

Comment on lines 134 to 135
export const ResizableTitle = (props: any) => {
const { onResize, width, ...restProps } = props;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why no destructuring directly in the function declaration? And is it possible to narrow the type down?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made suggested changes


type TruncateType = {
width: number | string;
innerRender: () => JSX.Element | string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can it be () => ReactNode?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{column.title as ReactNode}
const widths = getWidthsOfInnerElements(containerRef.current);

if (widths.some((w) => w > width)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, would be good

This comment has been minimized.

This comment has been minimized.

This comment has been minimized.

This comment has been minimized.

Copy link

CLOUDRUN ACTIONS

✅ Successfully created Preview Deployment.

https://pr-289---ms-server-staging-c4f6qdpj7q-ew.a.run.app

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants