From ba517a3fda38d82e00047b40a2beba7300d0cd7d Mon Sep 17 00:00:00 2001 From: hhssb Date: Fri, 13 Dec 2024 11:08:04 +0100 Subject: [PATCH] [ui] Move column selector to tabletoolbar and change it to combobox to handle more columns --- .../components/column-selector-button.tsx | 34 +++++ .../app/search/components/column-selector.tsx | 135 +++++++++++------- .../statistical-unit-table-header.tsx | 14 +- .../app/search/components/table-toolbar.tsx | 18 ++- app/src/app/search/table-columns.tsx | 55 ++++--- 5 files changed, 169 insertions(+), 87 deletions(-) create mode 100644 app/src/app/search/components/column-selector-button.tsx diff --git a/app/src/app/search/components/column-selector-button.tsx b/app/src/app/search/components/column-selector-button.tsx new file mode 100644 index 000000000..e33b03175 --- /dev/null +++ b/app/src/app/search/components/column-selector-button.tsx @@ -0,0 +1,34 @@ +"use client"; +import { Button } from "@/components/ui/button"; +import { Settings2 } from "lucide-react"; +import { useTableColumns } from "../table-columns"; +import { ColumnSelector } from "./column-selector"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; +export const ColumnSelectorButton = () => { + const { columns, toggleColumn, profiles, setProfile } = useTableColumns(); + return ( + + + + + + + + + ); +}; diff --git a/app/src/app/search/components/column-selector.tsx b/app/src/app/search/components/column-selector.tsx index 2c25a82e0..8fee75e99 100644 --- a/app/src/app/search/components/column-selector.tsx +++ b/app/src/app/search/components/column-selector.tsx @@ -1,23 +1,20 @@ -import { Button } from "@/components/ui/button"; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuLabel, - DropdownMenuSeparator, - DropdownMenuCheckboxItem, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; -import { Settings2 } from "lucide-react"; +import { Check } from "lucide-react"; import { ColumnProfile, TableColumn } from "../search.d"; import { isEqual } from "moderndash"; - +import { + Command, + CommandGroup, + CommandInput, + CommandItem, + CommandList, + CommandSeparator, +} from "@/components/ui/command"; interface ColumnSelectorProps { columns: TableColumn[]; onToggleColumn: (column: TableColumn) => void; profiles: Record; setProfile: (profile: ColumnProfile) => void; } - export function ColumnSelector({ columns, onToggleColumn, @@ -25,47 +22,79 @@ export function ColumnSelector({ setProfile, }: ColumnSelectorProps) { return ( - - - - - - Toggle Columns - - {columns.map((column) => ( - onToggleColumn(column)} - disabled={column.type == "Always" ? true : false} + + + + + {columns.map((column) => ( + onToggleColumn(column)} + disabled={column.type == "Always" ? true : false} + className="space-x-2" + > + + {column.label} + + ))} + + + + setProfile("Brief")} + value="Brief" + className="space-x-2" + > + + Brief + + setProfile("Regular")} + value="Regular" + className="space-x-2" + > + + Regular + + setProfile("Detailed")} + value="Detailed" + className="space-x-2" > - {column.label} - - ))} - - Profiles - setProfile("Brief")} - > - Brief - - setProfile("Regular")} - > - Regular - - setProfile("Detailed")} - > - Detailed - - - + + Detailed + + + + ); } diff --git a/app/src/app/search/components/statistical-unit-table-header.tsx b/app/src/app/search/components/statistical-unit-table-header.tsx index a3cecf8dd..47ce7fc01 100644 --- a/app/src/app/search/components/statistical-unit-table-header.tsx +++ b/app/src/app/search/components/statistical-unit-table-header.tsx @@ -4,7 +4,6 @@ import { useBaseData } from "@/app/BaseDataClient"; import { Button } from "@/components/ui/button"; import { ChevronLeft, ChevronRight } from "lucide-react"; import { useTableColumns } from "../table-columns"; -import { ColumnSelector } from "./column-selector"; interface StatisticalUnitTableHeaderProps { regionLevel: number; @@ -18,7 +17,8 @@ export function StatisticalUnitTableHeader({ maxRegionLevel, }: StatisticalUnitTableHeaderProps) { const { statDefinitions, externalIdentTypes } = useBaseData(); - const { columns, visibleColumns, toggleColumn, profiles, setProfile, headerRowSuffix, headerCellSuffix } = useTableColumns(); + const { visibleColumns, headerRowSuffix, headerCellSuffix } = + useTableColumns(); return ( @@ -134,15 +134,7 @@ export function StatisticalUnitTableHeader({ ); } })} - - - - + ); diff --git a/app/src/app/search/components/table-toolbar.tsx b/app/src/app/search/components/table-toolbar.tsx index e2ea845c2..452ca891b 100644 --- a/app/src/app/search/components/table-toolbar.tsx +++ b/app/src/app/search/components/table-toolbar.tsx @@ -13,10 +13,13 @@ import { ResetFilterButton } from "@/app/search/components/reset-filter-button"; import { FilterWrapper } from "./filter-wrapper"; import { IURLSearchParamsDict } from "@/lib/url-search-params-dict"; import DataSourceFilter from "../filters/data-source/data-source-filter"; +import { ColumnSelectorButton } from "./column-selector-button"; -export default function TableToolbar({ initialUrlSearchParamsDict }: IURLSearchParamsDict) { +export default function TableToolbar({ + initialUrlSearchParamsDict, +}: IURLSearchParamsDict) { return ( -
+
@@ -32,20 +35,21 @@ export default function TableToolbar({ initialUrlSearchParamsDict }: IURLSearchP - + }> - + }> - + - - + + +
); } diff --git a/app/src/app/search/table-columns.tsx b/app/src/app/search/table-columns.tsx index 98c92f5b3..65a6122fa 100644 --- a/app/src/app/search/table-columns.tsx +++ b/app/src/app/search/table-columns.tsx @@ -129,45 +129,68 @@ export function TableColumnsProvider({ children }: { children: ReactNode }) { const [columns, setColumns] = useState([]); + // Update columns and keep user preferences + const updateColumnsWithPreferences = useCallback( + (userColumns: AdaptableTableColumn[] = []): TableColumns => { + return available_columns.map((col) => { + if (col.type === "Adaptable") { + const userColumn = userColumns.find( + (userCol) => + userCol.type === "Adaptable" && + userCol.code === col.code && + userCol.stat_code === col.stat_code + ); + return { ...col, visible: userColumn?.visible ?? col.visible }; + } + return col; + }); + }, + [available_columns] + ); + useEffect(() => { - if (available_columns.length === 0) { - return; // Wait for default columns to be available + const fallbackColumns = updateColumnsWithPreferences(); + if (fallbackColumns.length === 0) { + return; } // Try loading from localStorage first + try { const saved = localStorage.getItem(COLUMN_LOCALSTORAGE_NAME); - if (saved) { - try { - const state = JSON.parse(saved); - setColumns(state); + const savedColumns = saved ? JSON.parse(saved) : []; + const currentColumns = updateColumnsWithPreferences(savedColumns); + setColumns(currentColumns); + if (!isEqual(savedColumns, currentColumns)) { + localStorage.setItem( + COLUMN_LOCALSTORAGE_NAME, + JSON.stringify(currentColumns) + ); + } } catch (e) { console.error("Failed to parse stored columns state:", e); localStorage.removeItem(COLUMN_LOCALSTORAGE_NAME); - setColumns(available_columns); // Fall back to defaults on error - } - return; + setColumns(fallbackColumns); } - // Fall back to default columns if no localStorage data - setColumns(available_columns); - // Listen for changes in other tabs const handleStorageChange = (e: StorageEvent) => { if (e.key === COLUMN_LOCALSTORAGE_NAME && e.newValue) { try { - const newState = JSON.parse(e.newValue); - setColumns(newState); + const updatedPreferences = JSON.parse(e.newValue); + const updatedColumns = + updateColumnsWithPreferences(updatedPreferences); + setColumns(updatedColumns); } catch (e) { console.error("Failed to parse columns state from storage event:", e); localStorage.removeItem(COLUMN_LOCALSTORAGE_NAME); - setColumns(available_columns); // Fall back to defaults on error + setColumns(fallbackColumns); } } }; window.addEventListener("storage", handleStorageChange); return () => window.removeEventListener("storage", handleStorageChange); - }, [available_columns]); + }, [updateColumnsWithPreferences]); const toggleColumn = useCallback( (column: TableColumn) => {