From 2bf681951042cfa2de7961f9ac469c860834c1c3 Mon Sep 17 00:00:00 2001 From: dbarabashh Date: Fri, 6 Dec 2024 23:30:42 +0100 Subject: [PATCH 1/6] preserve wallet expanded state when applying filters in DataTable --- src/components/DataTable/index.tsx | 70 +++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 12 deletions(-) diff --git a/src/components/DataTable/index.tsx b/src/components/DataTable/index.tsx index 38a0bcc47ba..debe472e133 100644 --- a/src/components/DataTable/index.tsx +++ b/src/components/DataTable/index.tsx @@ -52,9 +52,9 @@ const DataTable = ({ }: DataTableProps) => { const [isVisible, setIsVisible] = useState(true) const [currentData, setCurrentData] = useState(data) - const [expanded, setExpanded] = useState({}) - const previousExpandedRef = useRef({}) - const previousDataRef = useRef(data) + const [expanded, setExpanded] = useState>({}) + const previousExpandedRef = useRef>({}) + const previousDataRef = useRef(data) const table = useReactTable({ data: currentData, @@ -62,7 +62,9 @@ const DataTable = ({ state: { expanded, }, - onExpandedChange: setExpanded, + onExpandedChange: (updater) => + setExpanded(updater as Record), + getRowId: (row: unknown) => `${row.name}`, getRowCanExpand: (row) => { const rowData = row.original as { canExpand?: boolean } return rowData.canExpand !== undefined ? rowData.canExpand : true @@ -78,26 +80,61 @@ const DataTable = ({ } as TableMeta, }) + const getExpandedWalletNames = ( + expanded: Record + ): string[] => { + return Object.entries(expanded) + .filter(([_, isExpanded]) => isExpanded) + .map(([key]) => key) + } + + console.log(data) + + const createNewExpandedState = ( + newData: TData[], + currentExpanded: Record + ): Record => { + const expandedNames = new Set(getExpandedWalletNames(currentExpanded)) + console.log("expandedNames", expandedNames) + + return newData.reduce>((acc, item) => { + if (hasNameProperty(item)) { + acc[item.name] = expandedNames.has(item.name) + } + return acc + }, {}) + } + + useEffect(() => { + if (data !== previousDataRef.current) { + const newExpanded = createNewExpandedState(data, expanded) + setExpanded(newExpanded) + previousDataRef.current = data + previousExpandedRef.current = expanded + } + }, [data, expanded]) + useEffect(() => { const prev = previousExpandedRef.current const current = expanded - // Find newly expanded rows const newlyExpanded = Object.entries(current) .filter(([key, value]) => value === true && prev[key] !== true) .map(([key]) => key) if (newlyExpanded.length > 0) { const row = table.getRowModel().rowsById[newlyExpanded[0]] - trackCustomEvent({ - eventCategory: matomoEventCategory, - eventAction: "expanded", - eventName: (row.original as { name: string }).name, - }) + if (row) { + trackCustomEvent({ + eventCategory: matomoEventCategory, + eventAction: "expanded", + eventName: (row.original as { name: string }).name, + }) + } } previousExpandedRef.current = expanded - }, [expanded]) + }, [expanded, table, matomoEventCategory]) useEffect(() => { if (JSON.stringify(data) !== JSON.stringify(previousDataRef.current)) { @@ -111,7 +148,16 @@ const DataTable = ({ return () => clearTimeout(timer) } - }, [data]) + }, [data, table]) + + function hasNameProperty(item: TData): item is TData & { name: string } { + return ( + typeof item === "object" && + item !== null && + "name" in item && + typeof (item as unknown).name === "string" + ) + } return (
From 2173861e199814d03c85bc5b9045a599c614d5cc Mon Sep 17 00:00:00 2001 From: dbarabashh Date: Fri, 6 Dec 2024 23:47:11 +0100 Subject: [PATCH 2/6] improve type safety with TableRowData interface --- src/components/DataTable/index.tsx | 53 ++++++++++++++---------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/src/components/DataTable/index.tsx b/src/components/DataTable/index.tsx index debe472e133..f3547f7fcc2 100644 --- a/src/components/DataTable/index.tsx +++ b/src/components/DataTable/index.tsx @@ -1,4 +1,4 @@ -import { FC, Fragment, useEffect, useRef, useState } from "react" +import { FC, Fragment, useCallback, useEffect, useRef, useState } from "react" import { ColumnDef, flexRender, @@ -18,7 +18,14 @@ import { import { trackCustomEvent } from "@/lib/utils/matomo" -type DataTableProps = TableProps & { +interface TableRowData { + name: string + id?: string | number + description?: string + url?: string +} + +type DataTableProps = TableProps & { columns: ColumnDef[] data: TData[] subComponent?: FC @@ -38,7 +45,7 @@ export type TableMeta = { [key: string]: string | number | ((open: boolean) => void) } -const DataTable = ({ +const DataTable = ({ columns, data, subComponent, @@ -64,7 +71,7 @@ const DataTable = ({ }, onExpandedChange: (updater) => setExpanded(updater as Record), - getRowId: (row: unknown) => `${row.name}`, + getRowId: (row: TData) => `${row.name}`, getRowCanExpand: (row) => { const rowData = row.original as { canExpand?: boolean } return rowData.canExpand !== undefined ? rowData.canExpand : true @@ -88,22 +95,20 @@ const DataTable = ({ .map(([key]) => key) } - console.log(data) - - const createNewExpandedState = ( - newData: TData[], - currentExpanded: Record - ): Record => { - const expandedNames = new Set(getExpandedWalletNames(currentExpanded)) - console.log("expandedNames", expandedNames) + const createNewExpandedState = useCallback( + ( + newData: TData[], + currentExpanded: Record + ): Record => { + const expandedNames = new Set(getExpandedWalletNames(currentExpanded)) - return newData.reduce>((acc, item) => { - if (hasNameProperty(item)) { + return newData.reduce>((acc, item) => { acc[item.name] = expandedNames.has(item.name) - } - return acc - }, {}) - } + return acc + }, {}) + }, + [] + ) useEffect(() => { if (data !== previousDataRef.current) { @@ -112,12 +117,13 @@ const DataTable = ({ previousDataRef.current = data previousExpandedRef.current = expanded } - }, [data, expanded]) + }, [createNewExpandedState, data, expanded]) useEffect(() => { const prev = previousExpandedRef.current const current = expanded + // Find newly expanded rows const newlyExpanded = Object.entries(current) .filter(([key, value]) => value === true && prev[key] !== true) .map(([key]) => key) @@ -150,15 +156,6 @@ const DataTable = ({ } }, [data, table]) - function hasNameProperty(item: TData): item is TData & { name: string } { - return ( - typeof item === "object" && - item !== null && - "name" in item && - typeof (item as unknown).name === "string" - ) - } - return (
From 09e8b2233105b66652df8136a681640c8cc33c70 Mon Sep 17 00:00:00 2001 From: dbarabashh Date: Fri, 6 Dec 2024 23:53:13 +0100 Subject: [PATCH 3/6] preserve expanded state after removing filters in DataTable --- src/components/DataTable/index.tsx | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/components/DataTable/index.tsx b/src/components/DataTable/index.tsx index f3547f7fcc2..e3bb892d009 100644 --- a/src/components/DataTable/index.tsx +++ b/src/components/DataTable/index.tsx @@ -60,6 +60,9 @@ const DataTable = ({ const [isVisible, setIsVisible] = useState(true) const [currentData, setCurrentData] = useState(data) const [expanded, setExpanded] = useState>({}) + const [lastKnownExpanded, setLastKnownExpanded] = useState< + Record + >({}) const previousExpandedRef = useRef>({}) const previousDataRef = useRef(data) @@ -87,32 +90,33 @@ const DataTable = ({ } as TableMeta, }) - const getExpandedWalletNames = ( - expanded: Record - ): string[] => { - return Object.entries(expanded) - .filter(([_, isExpanded]) => isExpanded) - .map(([key]) => key) - } - const createNewExpandedState = useCallback( ( newData: TData[], currentExpanded: Record ): Record => { - const expandedNames = new Set(getExpandedWalletNames(currentExpanded)) - return newData.reduce>((acc, item) => { - acc[item.name] = expandedNames.has(item.name) + acc[item.name] = + lastKnownExpanded[item.name] || currentExpanded[item.name] || false return acc }, {}) }, - [] + [lastKnownExpanded] ) + useEffect(() => { + const hasExpandedItems = Object.keys(expanded).length > 0 + if (hasExpandedItems) { + setLastKnownExpanded((prev) => ({ ...prev, ...expanded })) + } + }, [expanded]) + useEffect(() => { if (data !== previousDataRef.current) { - const newExpanded = createNewExpandedState(data, expanded) + const newExpanded = createNewExpandedState( + data, + previousExpandedRef.current + ) setExpanded(newExpanded) previousDataRef.current = data previousExpandedRef.current = expanded From 7330996a6d3ae37ac682bc890651fadd29682e2b Mon Sep 17 00:00:00 2001 From: dbarabashh Date: Fri, 6 Dec 2024 23:58:27 +0100 Subject: [PATCH 4/6] improve TableRowData type exports and imports --- src/components/DataTable/index.tsx | 2 +- src/components/ProductTable/index.tsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/DataTable/index.tsx b/src/components/DataTable/index.tsx index e3bb892d009..fac2bb0c909 100644 --- a/src/components/DataTable/index.tsx +++ b/src/components/DataTable/index.tsx @@ -18,7 +18,7 @@ import { import { trackCustomEvent } from "@/lib/utils/matomo" -interface TableRowData { +export interface TableRowData { name: string id?: string | number description?: string diff --git a/src/components/ProductTable/index.tsx b/src/components/ProductTable/index.tsx index 74e96d858a2..927984905a3 100644 --- a/src/components/ProductTable/index.tsx +++ b/src/components/ProductTable/index.tsx @@ -11,14 +11,14 @@ import { ColumnDef } from "@tanstack/react-table" import type { FilterOption, TPresetFilters } from "@/lib/types" -import Table from "@/components/DataTable" +import Table, { TableRowData } from "@/components/DataTable" import Filters from "@/components/ProductTable/Filters" import MobileFilters from "@/components/ProductTable/MobileFilters" import PresetFilters from "@/components/ProductTable/PresetFilters" import { trackCustomEvent } from "@/lib/utils/matomo" -interface ProductTableProps { +interface ProductTableProps { columns: ColumnDef[] data: T[] allDataLength: number @@ -33,7 +33,7 @@ interface ProductTableProps { meta?: Record } -const ProductTable = ({ +const ProductTable = ({ columns, data, allDataLength, From 680080a16a6fa5aac452ced716b305014a7f10b3 Mon Sep 17 00:00:00 2001 From: dbarabashh Date: Sat, 7 Dec 2024 00:16:44 +0100 Subject: [PATCH 5/6] preserve wallet accordion state during filtering --- src/components/DataTable/index.tsx | 67 +++--------------------------- 1 file changed, 5 insertions(+), 62 deletions(-) diff --git a/src/components/DataTable/index.tsx b/src/components/DataTable/index.tsx index fac2bb0c909..2458ae9675f 100644 --- a/src/components/DataTable/index.tsx +++ b/src/components/DataTable/index.tsx @@ -1,4 +1,4 @@ -import { FC, Fragment, useCallback, useEffect, useRef, useState } from "react" +import { FC, Fragment, useEffect, useRef, useState } from "react" import { ColumnDef, flexRender, @@ -57,24 +57,18 @@ const DataTable = ({ matomoEventCategory, ...props }: DataTableProps) => { - const [isVisible, setIsVisible] = useState(true) - const [currentData, setCurrentData] = useState(data) const [expanded, setExpanded] = useState>({}) - const [lastKnownExpanded, setLastKnownExpanded] = useState< - Record - >({}) const previousExpandedRef = useRef>({}) - const previousDataRef = useRef(data) const table = useReactTable({ - data: currentData, + data, columns, state: { expanded, }, onExpandedChange: (updater) => setExpanded(updater as Record), - getRowId: (row: TData) => `${row.name}`, + getRowId: (row: TData) => row.name, getRowCanExpand: (row) => { const rowData = row.original as { canExpand?: boolean } return rowData.canExpand !== undefined ? rowData.canExpand : true @@ -90,39 +84,6 @@ const DataTable = ({ } as TableMeta, }) - const createNewExpandedState = useCallback( - ( - newData: TData[], - currentExpanded: Record - ): Record => { - return newData.reduce>((acc, item) => { - acc[item.name] = - lastKnownExpanded[item.name] || currentExpanded[item.name] || false - return acc - }, {}) - }, - [lastKnownExpanded] - ) - - useEffect(() => { - const hasExpandedItems = Object.keys(expanded).length > 0 - if (hasExpandedItems) { - setLastKnownExpanded((prev) => ({ ...prev, ...expanded })) - } - }, [expanded]) - - useEffect(() => { - if (data !== previousDataRef.current) { - const newExpanded = createNewExpandedState( - data, - previousExpandedRef.current - ) - setExpanded(newExpanded) - previousDataRef.current = data - previousExpandedRef.current = expanded - } - }, [createNewExpandedState, data, expanded]) - useEffect(() => { const prev = previousExpandedRef.current const current = expanded @@ -138,7 +99,7 @@ const DataTable = ({ trackCustomEvent({ eventCategory: matomoEventCategory, eventAction: "expanded", - eventName: (row.original as { name: string }).name, + eventName: row.original.name, }) } } @@ -146,20 +107,6 @@ const DataTable = ({ previousExpandedRef.current = expanded }, [expanded, table, matomoEventCategory]) - useEffect(() => { - if (JSON.stringify(data) !== JSON.stringify(previousDataRef.current)) { - setIsVisible(false) - const timer = setTimeout(() => { - setCurrentData(data) - table.resetExpanded() - setIsVisible(true) - previousDataRef.current = data - }, 25) // Adjust this value to match your CSS transition duration - - return () => clearTimeout(timer) - } - }, [data, table]) - return (
@@ -183,11 +130,7 @@ const DataTable = ({
- + {table.getRowModel().rows?.length ? ( table.getRowModel().rows.map((row, idx) => ( From e439a13d071460ee4ab85b8932c8c737030cd507 Mon Sep 17 00:00:00 2001 From: dbarabashh Date: Sat, 7 Dec 2024 00:19:35 +0100 Subject: [PATCH 6/6] Restore smooth transition animation --- src/components/DataTable/index.tsx | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/components/DataTable/index.tsx b/src/components/DataTable/index.tsx index 2458ae9675f..75e14c162ae 100644 --- a/src/components/DataTable/index.tsx +++ b/src/components/DataTable/index.tsx @@ -57,11 +57,14 @@ const DataTable = ({ matomoEventCategory, ...props }: DataTableProps) => { + const [isVisible, setIsVisible] = useState(true) + const [currentData, setCurrentData] = useState(data) const [expanded, setExpanded] = useState>({}) const previousExpandedRef = useRef>({}) + const previousDataRef = useRef(data) const table = useReactTable({ - data, + data: currentData, columns, state: { expanded, @@ -107,6 +110,19 @@ const DataTable = ({ previousExpandedRef.current = expanded }, [expanded, table, matomoEventCategory]) + useEffect(() => { + if (JSON.stringify(data) !== JSON.stringify(previousDataRef.current)) { + setIsVisible(false) + const timer = setTimeout(() => { + setCurrentData(data) + setIsVisible(true) + previousDataRef.current = data + }, 25) // Adjust this value to match your CSS transition duration + + return () => clearTimeout(timer) + } + }, [data]) + return (
@@ -130,7 +146,11 @@ const DataTable = ({
- + {table.getRowModel().rows?.length ? ( table.getRowModel().rows.map((row, idx) => (