From b86bb025a23578e4df7d2f3060f93f64c179f0bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chy=C5=82a?= Date: Tue, 11 Jul 2023 13:19:26 +0200 Subject: [PATCH] Introduce new column picker in Categories list (#3876) --- .changeset/fast-rocks-punch.md | 5 ++ .../CategoryListDatagrid.tsx | 80 +++++++++-------- .../CategoryListDatagrid/datagrid.ts | 66 +++++++------- .../CategorySubcategories.tsx | 88 +++++++++++-------- .../CategoryUpdatePage/CategoryUpdatePage.tsx | 12 ++- src/categories/views/CategoryDetails.tsx | 7 ++ src/config.ts | 1 + 7 files changed, 143 insertions(+), 116 deletions(-) create mode 100644 .changeset/fast-rocks-punch.md diff --git a/.changeset/fast-rocks-punch.md b/.changeset/fast-rocks-punch.md new file mode 100644 index 000000000..7908ac8a4 --- /dev/null +++ b/.changeset/fast-rocks-punch.md @@ -0,0 +1,5 @@ +--- +"saleor-dashboard": minor +--- + +Introduce new column picker in Categories list diff --git a/src/categories/components/CategoryListDatagrid/CategoryListDatagrid.tsx b/src/categories/components/CategoryListDatagrid/CategoryListDatagrid.tsx index cbd6e4fcc..96d2d8f4e 100644 --- a/src/categories/components/CategoryListDatagrid/CategoryListDatagrid.tsx +++ b/src/categories/components/CategoryListDatagrid/CategoryListDatagrid.tsx @@ -1,11 +1,10 @@ -// @ts-strict-ignore import { CategoryListUrlSortField, categoryUrl, } from "@dashboard/categories/urls"; -import ColumnPicker from "@dashboard/components/ColumnPicker"; +import { ColumnPicker } from "@dashboard/components/Datagrid/ColumnPicker/ColumnPicker"; +import { useColumns } from "@dashboard/components/Datagrid/ColumnPicker/useColumns"; import Datagrid from "@dashboard/components/Datagrid/Datagrid"; -import { useColumnsDefault } from "@dashboard/components/Datagrid/hooks/useColumnsDefault"; import { DatagridChangeStateContext, useDatagridChangeState, @@ -18,14 +17,16 @@ import { Box } from "@saleor/macaw-ui/next"; import React, { ReactNode, useCallback, useMemo } from "react"; import { useIntl } from "react-intl"; -import { createGetCellContent, getColumns } from "./datagrid"; +import { + categoryListStaticColumnsAdapter, + createGetCellContent, +} from "./datagrid"; import { messages } from "./messages"; interface CategoryListDatagridProps - extends Partial>, - PageListProps { - categories?: CategoryFragment[]; - disabled: boolean; + extends PageListProps, + Partial> { + categories: CategoryFragment[]; onSelectCategoriesIds: (ids: number[], clearSelection: () => void) => void; selectionActionButton?: ReactNode | null; hasRowHover?: boolean; @@ -44,32 +45,40 @@ export const CategoryListDatagrid = ({ }: CategoryListDatagridProps) => { const datagridState = useDatagridChangeState(); const intl = useIntl(); - const availableColumns = useMemo(() => getColumns(intl, sort), [intl, sort]); - const { - availableColumnsChoices, - columnChoices, - columns, - defaultColumns, - onColumnMoved, - onColumnResize, - onColumnsChange, - picker, - } = useColumnsDefault(availableColumns); + const memoizedStaticColumns = useMemo( + () => categoryListStaticColumnsAdapter(intl, sort), + [intl, sort], + ); + + const handleColumnChange = useCallback( + picked => { + if (onUpdateListSettings) { + onUpdateListSettings("columns", picked.filter(Boolean)); + } + }, + [onUpdateListSettings], + ); + + const { handlers, selectedColumns, staticColumns, visibleColumns } = + useColumns({ + staticColumns: memoizedStaticColumns, + selectedColumns: settings?.columns ?? [], + onSave: handleColumnChange, + }); - // eslint-disable-next-line react-hooks/exhaustive-deps const getCellContent = useCallback( - createGetCellContent(categories, columns), - [categories, columns], + createGetCellContent(categories, visibleColumns), + [categories, visibleColumns], ); const handleHeaderClick = useCallback( (col: number) => { - if (sort !== undefined) { - onSort(columns[col].id as CategoryListUrlSortField); + if (sort !== undefined && onSort) { + onSort(visibleColumns[col].id as CategoryListUrlSortField); } }, - [columns, onSort, sort], + [visibleColumns, onSort, sort], ); const handleRowAnchor = useCallback( @@ -86,7 +95,7 @@ export const CategoryListDatagrid = ({ columnSelect={sort !== undefined ? "single" : undefined} verticalBorder={col => col > 0} rowMarkers="checkbox" - availableColumns={columns} + availableColumns={visibleColumns} rows={categories?.length ?? 0} getCellContent={getCellContent} getCellError={() => false} @@ -96,21 +105,14 @@ export const CategoryListDatagrid = ({ menuItems={() => []} actionButtonPosition="right" selectionActions={() => selectionActionButton} - onColumnResize={onColumnResize} - onColumnMoved={onColumnMoved} + onColumnResize={handlers.onResize} + onColumnMoved={handlers.onMove} onRowSelectionChange={onSelectCategoriesIds} - renderColumnPicker={defaultProps => ( + renderColumnPicker={() => ( undefined} - onQueryChange={picker.setQuery} - query={picker.query} + onSave={handlers.onChange} + selectedColumns={selectedColumns} + staticColumns={staticColumns} /> )} /> diff --git a/src/categories/components/CategoryListDatagrid/datagrid.ts b/src/categories/components/CategoryListDatagrid/datagrid.ts index 24aaaa160..f542609e9 100644 --- a/src/categories/components/CategoryListDatagrid/datagrid.ts +++ b/src/categories/components/CategoryListDatagrid/datagrid.ts @@ -1,4 +1,3 @@ -// @ts-strict-ignore import { CategoryListUrlSortField } from "@dashboard/categories/urls"; import { readonlyTextCell } from "@dashboard/components/Datagrid/customCells/cells"; import { AvailableColumn } from "@dashboard/components/Datagrid/types"; @@ -10,57 +9,52 @@ import { IntlShape } from "react-intl"; import { columnsMessages } from "./messages"; -export const getColumns = ( +export const categoryListStaticColumnsAdapter = ( intl: IntlShape, sort?: Sort, -): AvailableColumn[] => [ - { - id: "name", - title: intl.formatMessage(columnsMessages.categoryName), - width: 350, - icon: sort - ? getColumnSortDirectionIcon(sort, CategoryListUrlSortField.name) - : undefined, - }, - { - id: "subcategories", - title: intl.formatMessage(columnsMessages.subcategories), - width: 300, - icon: sort - ? getColumnSortDirectionIcon( - sort, - CategoryListUrlSortField.subcategoryCount, - ) - : undefined, - }, - { - id: "products", - title: intl.formatMessage(columnsMessages.numberOfProducts), - width: 300, - icon: sort - ? getColumnSortDirectionIcon(sort, CategoryListUrlSortField.productCount) - : undefined, - }, -]; +): AvailableColumn[] => + [ + { + id: "name", + title: intl.formatMessage(columnsMessages.categoryName), + width: 350, + }, + { + id: "subcategories", + title: intl.formatMessage(columnsMessages.subcategories), + width: 300, + }, + { + id: "products", + title: intl.formatMessage(columnsMessages.numberOfProducts), + width: 300, + }, + ].map(column => ({ + ...column, + icon: sort ? getColumnSortDirectionIcon(sort, column.id) : undefined, + })); export const createGetCellContent = (categories: CategoryFragment[], columns: AvailableColumn[]) => ([column, row]: Item): GridCell => { const columnId = columns[column]?.id; + const rowData: CategoryFragment | undefined = categories[row]; - if (!columnId) { + if (!columnId || !rowData) { return readonlyTextCell(""); } - const rowData = categories[row]; - switch (columnId) { case "name": return readonlyTextCell(rowData?.name ?? ""); case "subcategories": - return readonlyTextCell(rowData?.children?.totalCount.toString() ?? ""); + return readonlyTextCell( + rowData?.children?.totalCount?.toString() ?? "", + ); case "products": - return readonlyTextCell(rowData?.products?.totalCount.toString() ?? ""); + return readonlyTextCell( + rowData?.products?.totalCount?.toString() ?? "", + ); default: return readonlyTextCell("", false); } diff --git a/src/categories/components/CategorySubcategories/CategorySubcategories.tsx b/src/categories/components/CategorySubcategories/CategorySubcategories.tsx index 41540e507..8894f98cc 100644 --- a/src/categories/components/CategorySubcategories/CategorySubcategories.tsx +++ b/src/categories/components/CategorySubcategories/CategorySubcategories.tsx @@ -3,7 +3,7 @@ import { categoryAddUrl } from "@dashboard/categories/urls"; import { DashboardCard } from "@dashboard/components/Card"; import { InternalLink } from "@dashboard/components/InternalLink"; import { CategoryDetailsQuery } from "@dashboard/graphql"; -import { RelayToFlat } from "@dashboard/types"; +import { ListProps, ListViews, RelayToFlat } from "@dashboard/types"; import { Box, Button } from "@saleor/macaw-ui/next"; import React from "react"; import { FormattedMessage } from "react-intl"; @@ -11,7 +11,11 @@ import { FormattedMessage } from "react-intl"; import { CategoryDeleteButton } from "../CategoryDeleteButton"; import { CategoryListDatagrid } from "../CategoryListDatagrid"; -interface CategorySubcategoriesProps { +interface CategorySubcategoriesProps + extends Pick< + ListProps, + "onUpdateListSettings" | "settings" + > { categoryId: string; disabled: boolean; subcategories: RelayToFlat; @@ -25,41 +29,47 @@ export const CategorySubcategories = ({ disabled, onCategoriesDelete, onSelectCategoriesIds, -}: CategorySubcategoriesProps) => ( - - - - - - - - - - - - - - + settings, + onUpdateListSettings, +}: CategorySubcategoriesProps) => { + return ( + + + + + + + - } - /> - -); + + + + + + + + } + /> + + ); +}; diff --git a/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx b/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx index 9af9e9327..3013cbb63 100644 --- a/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx +++ b/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx @@ -16,7 +16,7 @@ import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; import { maybe } from "../../../misc"; -import { RelayToFlat } from "../../../types"; +import { ListProps, ListViews, RelayToFlat } from "../../../types"; import CategoryDetailsForm from "../../components/CategoryDetailsForm"; import CategoryBackground from "../CategoryBackground"; import { CategoryProducts } from "../CategoryProducts"; @@ -28,7 +28,11 @@ export enum CategoryPageTab { products = "products", } -export interface CategoryUpdatePageProps { +export interface CategoryUpdatePageProps + extends Pick< + ListProps, + "onUpdateListSettings" | "settings" + > { categoryId: string; changeTab: (index: CategoryPageTab) => void; currentTab: CategoryPageTab; @@ -70,6 +74,8 @@ export const CategoryUpdatePage: React.FC = ({ onCategoriesDelete, onProductsDelete, onSelectProductsIds, + settings, + onUpdateListSettings, }: CategoryUpdatePageProps) => { const intl = useIntl(); const navigate = useNavigator(); @@ -161,6 +167,8 @@ export const CategoryUpdatePage: React.FC = ({ {currentTab === CategoryPageTab.categories && ( = ({ setActiveTab(tab); }; + const { settings, updateListSettings } = + useListSettings(ListViews.CATEGORY_LIST); + const { data, loading, refetch } = useCategoryDetailsQuery({ displayLoader: true, variables: { ...paginationState, id }, @@ -274,6 +279,8 @@ export const CategoryDetails: React.FC = ({ data.category.name)} /> data.category)} diff --git a/src/config.ts b/src/config.ts index 29718cf7e..ea02ad4b7 100644 --- a/src/config.ts +++ b/src/config.ts @@ -72,6 +72,7 @@ export const defaultListSettings: AppListViewSettings = { }, [ListViews.CATEGORY_LIST]: { rowNumber: PAGINATE_BY, + columns: ["name", "products", "subcategories"], }, [ListViews.COLLECTION_LIST]: { rowNumber: PAGINATE_BY,