Introduce new column picker in Order Draft list (#3869)
This commit is contained in:
parent
0ea8f32378
commit
391b429fce
6 changed files with 93 additions and 84 deletions
5
.changeset/moody-queens-end.md
Normal file
5
.changeset/moody-queens-end.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"saleor-dashboard": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Introduce new column picker in Order Draft list datagrid
|
|
@ -81,6 +81,7 @@ export const defaultListSettings: AppListViewSettings = {
|
||||||
},
|
},
|
||||||
[ListViews.DRAFT_LIST]: {
|
[ListViews.DRAFT_LIST]: {
|
||||||
rowNumber: PAGINATE_BY,
|
rowNumber: PAGINATE_BY,
|
||||||
|
columns: ["number", "date", "customer", "total"],
|
||||||
},
|
},
|
||||||
[ListViews.NAVIGATION_LIST]: {
|
[ListViews.NAVIGATION_LIST]: {
|
||||||
rowNumber: PAGINATE_BY,
|
rowNumber: PAGINATE_BY,
|
||||||
|
|
|
@ -1,32 +1,34 @@
|
||||||
// @ts-strict-ignore
|
import { ColumnPicker } from "@dashboard/components/Datagrid/ColumnPicker/ColumnPicker";
|
||||||
import ColumnPicker from "@dashboard/components/ColumnPicker/ColumnPicker";
|
import { useColumns } from "@dashboard/components/Datagrid/ColumnPicker/useColumns";
|
||||||
import Datagrid from "@dashboard/components/Datagrid/Datagrid";
|
import Datagrid from "@dashboard/components/Datagrid/Datagrid";
|
||||||
import { useColumnsDefault } from "@dashboard/components/Datagrid/hooks/useColumnsDefault";
|
|
||||||
import {
|
import {
|
||||||
DatagridChangeStateContext,
|
DatagridChangeStateContext,
|
||||||
useDatagridChangeState,
|
useDatagridChangeState,
|
||||||
} from "@dashboard/components/Datagrid/hooks/useDatagridChange";
|
} from "@dashboard/components/Datagrid/hooks/useDatagridChange";
|
||||||
import { TablePaginationWithContext } from "@dashboard/components/TablePagination";
|
import { TablePaginationWithContext } from "@dashboard/components/TablePagination";
|
||||||
import { OrderDraftListQuery } from "@dashboard/graphql";
|
|
||||||
import useLocale from "@dashboard/hooks/useLocale";
|
import useLocale from "@dashboard/hooks/useLocale";
|
||||||
|
import { OrderDraft } from "@dashboard/orders/types";
|
||||||
import { OrderDraftListUrlSortField, orderUrl } from "@dashboard/orders/urls";
|
import { OrderDraftListUrlSortField, orderUrl } from "@dashboard/orders/urls";
|
||||||
import { ListProps, RelayToFlat, SortPage } from "@dashboard/types";
|
import { ListProps, SortPage } from "@dashboard/types";
|
||||||
import { Item } from "@glideapps/glide-data-grid";
|
import { Item } from "@glideapps/glide-data-grid";
|
||||||
import { Box } from "@saleor/macaw-ui/next";
|
import { Box } from "@saleor/macaw-ui/next";
|
||||||
import React, { useCallback, useMemo } from "react";
|
import React, { useCallback, useMemo } from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
import { createGetCellContent, getColumns } from "./datagrid";
|
import {
|
||||||
|
createGetCellContent,
|
||||||
|
orderDraftListStaticColumnsAdapter,
|
||||||
|
} from "./datagrid";
|
||||||
import { messages } from "./messages";
|
import { messages } from "./messages";
|
||||||
import { canBeSorted } from "./utils";
|
import { canBeSorted } from "./utils";
|
||||||
|
|
||||||
interface OrderDraftListDatagridProps
|
interface OrderDraftListDatagridProps
|
||||||
extends ListProps,
|
extends ListProps,
|
||||||
SortPage<OrderDraftListUrlSortField> {
|
SortPage<OrderDraftListUrlSortField> {
|
||||||
orders: RelayToFlat<OrderDraftListQuery["draftOrders"]>;
|
orders: OrderDraft[];
|
||||||
hasRowHover?: boolean;
|
hasRowHover?: boolean;
|
||||||
onRowClick?: (id: string) => void;
|
onRowClick?: (id: string) => void;
|
||||||
onSelectOrderDraftIds;
|
onSelectOrderDraftIds: (ids: number[], clearSelection: () => void) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const OrderDraftListDatagrid = ({
|
export const OrderDraftListDatagrid = ({
|
||||||
|
@ -44,33 +46,40 @@ export const OrderDraftListDatagrid = ({
|
||||||
const { locale } = useLocale();
|
const { locale } = useLocale();
|
||||||
const datagridState = useDatagridChangeState();
|
const datagridState = useDatagridChangeState();
|
||||||
|
|
||||||
const availableColumns = useMemo(() => getColumns(intl, sort), [intl, sort]);
|
const handleColumnChange = useCallback(
|
||||||
|
picked => {
|
||||||
|
if (onUpdateListSettings) {
|
||||||
|
onUpdateListSettings("columns", picked.filter(Boolean));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[onUpdateListSettings],
|
||||||
|
);
|
||||||
|
|
||||||
const {
|
const memoizedStaticColumns = useMemo(
|
||||||
columns,
|
() => orderDraftListStaticColumnsAdapter(intl, sort),
|
||||||
availableColumnsChoices,
|
[intl, sort],
|
||||||
columnChoices,
|
);
|
||||||
defaultColumns,
|
|
||||||
onColumnMoved,
|
const { handlers, staticColumns, visibleColumns, selectedColumns } =
|
||||||
onColumnResize,
|
useColumns({
|
||||||
onColumnsChange,
|
staticColumns: memoizedStaticColumns,
|
||||||
picker,
|
selectedColumns: settings?.columns ?? [],
|
||||||
} = useColumnsDefault(availableColumns);
|
onSave: handleColumnChange,
|
||||||
|
});
|
||||||
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
const getCellContent = useCallback(
|
const getCellContent = useCallback(
|
||||||
createGetCellContent({ orders, columns, locale }),
|
createGetCellContent({ orders, columns: visibleColumns, locale }),
|
||||||
[columns, locale, orders],
|
[visibleColumns, locale, orders],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleHeaderClick = useCallback(
|
const handleHeaderClick = useCallback(
|
||||||
(col: number) => {
|
(col: number) => {
|
||||||
const columnName = columns[col].id as OrderDraftListUrlSortField;
|
const columnName = visibleColumns[col].id as OrderDraftListUrlSortField;
|
||||||
if (canBeSorted(columnName)) {
|
if (canBeSorted(columnName)) {
|
||||||
onSort(columnName);
|
onSort(columnName);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[columns, onSort],
|
[visibleColumns, onSort],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleRowClick = useCallback(
|
const handleRowClick = useCallback(
|
||||||
|
@ -102,7 +111,7 @@ export const OrderDraftListDatagrid = ({
|
||||||
freezeColumns={1}
|
freezeColumns={1}
|
||||||
hasRowHover={hasRowHover}
|
hasRowHover={hasRowHover}
|
||||||
loading={disabled}
|
loading={disabled}
|
||||||
availableColumns={columns}
|
availableColumns={visibleColumns}
|
||||||
verticalBorder={col => col > 0}
|
verticalBorder={col => col > 0}
|
||||||
getCellContent={getCellContent}
|
getCellContent={getCellContent}
|
||||||
getCellError={() => false}
|
getCellError={() => false}
|
||||||
|
@ -111,27 +120,16 @@ export const OrderDraftListDatagrid = ({
|
||||||
rows={orders?.length ?? 0}
|
rows={orders?.length ?? 0}
|
||||||
selectionActions={() => null}
|
selectionActions={() => null}
|
||||||
onRowSelectionChange={onSelectOrderDraftIds}
|
onRowSelectionChange={onSelectOrderDraftIds}
|
||||||
onColumnMoved={onColumnMoved}
|
onColumnResize={handlers.onResize}
|
||||||
onColumnResize={onColumnResize}
|
onColumnMoved={handlers.onMove}
|
||||||
onHeaderClicked={handleHeaderClick}
|
onHeaderClicked={handleHeaderClick}
|
||||||
onRowClick={handleRowClick}
|
onRowClick={handleRowClick}
|
||||||
rowAnchor={handleRowAnchor}
|
rowAnchor={handleRowAnchor}
|
||||||
renderColumnPicker={defaultProps => (
|
renderColumnPicker={() => (
|
||||||
<ColumnPicker
|
<ColumnPicker
|
||||||
{...defaultProps}
|
staticColumns={staticColumns}
|
||||||
IconButtonProps={{
|
selectedColumns={selectedColumns}
|
||||||
...defaultProps.IconButtonProps,
|
onSave={handlers.onChange}
|
||||||
disabled: orders.length === 0,
|
|
||||||
}}
|
|
||||||
availableColumns={availableColumnsChoices}
|
|
||||||
initialColumns={columnChoices}
|
|
||||||
defaultColumns={defaultColumns}
|
|
||||||
onSave={onColumnsChange}
|
|
||||||
hasMore={false}
|
|
||||||
loading={false}
|
|
||||||
onFetchMore={() => undefined}
|
|
||||||
onQueryChange={picker.setQuery}
|
|
||||||
query={picker.query}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { OrderDraftListQuery } from "@dashboard/graphql";
|
import { OrderDraft } from "@dashboard/orders/types";
|
||||||
import { RelayToFlat } from "@dashboard/types";
|
|
||||||
|
|
||||||
import { getCustomerName } from "./datagrid";
|
import { getCustomerName } from "./datagrid";
|
||||||
|
|
||||||
|
@ -11,7 +10,7 @@ describe("getCustomerName", () => {
|
||||||
firstName: "John",
|
firstName: "John",
|
||||||
lastName: "Doe",
|
lastName: "Doe",
|
||||||
},
|
},
|
||||||
} as RelayToFlat<NonNullable<OrderDraftListQuery["draftOrders"]>>[number];
|
} as OrderDraft;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = getCustomerName(data);
|
const result = getCustomerName(data);
|
||||||
|
@ -27,7 +26,7 @@ describe("getCustomerName", () => {
|
||||||
city: "New York",
|
city: "New York",
|
||||||
},
|
},
|
||||||
userEmail: "john@doe.com",
|
userEmail: "john@doe.com",
|
||||||
} as RelayToFlat<NonNullable<OrderDraftListQuery["draftOrders"]>>[number];
|
} as OrderDraft;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = getCustomerName(data);
|
const result = getCustomerName(data);
|
||||||
|
@ -38,9 +37,7 @@ describe("getCustomerName", () => {
|
||||||
|
|
||||||
it("should return - when no user email and billing address", () => {
|
it("should return - when no user email and billing address", () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const data = {} as RelayToFlat<
|
const data = {} as OrderDraft;
|
||||||
NonNullable<OrderDraftListQuery["draftOrders"]>
|
|
||||||
>[number];
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = getCustomerName(data);
|
const result = getCustomerName(data);
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
// @ts-strict-ignore
|
|
||||||
import {
|
import {
|
||||||
moneyCell,
|
moneyCell,
|
||||||
readonlyTextCell,
|
readonlyTextCell,
|
||||||
} from "@dashboard/components/Datagrid/customCells/cells";
|
} from "@dashboard/components/Datagrid/customCells/cells";
|
||||||
import { AvailableColumn } from "@dashboard/components/Datagrid/types";
|
import { AvailableColumn } from "@dashboard/components/Datagrid/types";
|
||||||
import { Locale } from "@dashboard/components/Locale";
|
import { Locale } from "@dashboard/components/Locale";
|
||||||
import { OrderDraftListQuery } from "@dashboard/graphql";
|
import { OrderDraft } from "@dashboard/orders/types";
|
||||||
import { RelayToFlat, Sort } from "@dashboard/types";
|
import { Sort } from "@dashboard/types";
|
||||||
import { getColumnSortDirectionIcon } from "@dashboard/utils/columns/getColumnSortDirectionIcon";
|
import { getColumnSortDirectionIcon } from "@dashboard/utils/columns/getColumnSortDirectionIcon";
|
||||||
import { GridCell, Item } from "@glideapps/glide-data-grid";
|
import { GridCell, Item } from "@glideapps/glide-data-grid";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
@ -14,32 +13,35 @@ import { IntlShape } from "react-intl";
|
||||||
|
|
||||||
import { columnsMessages } from "./messages";
|
import { columnsMessages } from "./messages";
|
||||||
|
|
||||||
export const getColumns = (intl: IntlShape, sort: Sort): AvailableColumn[] => [
|
export const orderDraftListStaticColumnsAdapter = (
|
||||||
{
|
intl: IntlShape,
|
||||||
id: "number",
|
sort: Sort,
|
||||||
title: intl.formatMessage(columnsMessages.number),
|
): AvailableColumn[] =>
|
||||||
width: 100,
|
[
|
||||||
icon: getColumnSortDirectionIcon(sort, "number"),
|
{
|
||||||
},
|
id: "number",
|
||||||
{
|
title: intl.formatMessage(columnsMessages.number),
|
||||||
id: "date",
|
width: 100,
|
||||||
title: intl.formatMessage(columnsMessages.date),
|
},
|
||||||
width: 200,
|
{
|
||||||
icon: getColumnSortDirectionIcon(sort, "date"),
|
id: "date",
|
||||||
},
|
title: intl.formatMessage(columnsMessages.date),
|
||||||
{
|
width: 200,
|
||||||
id: "customer",
|
},
|
||||||
title: intl.formatMessage(columnsMessages.customer),
|
{
|
||||||
width: 200,
|
id: "customer",
|
||||||
icon: getColumnSortDirectionIcon(sort, "customer"),
|
title: intl.formatMessage(columnsMessages.customer),
|
||||||
},
|
width: 200,
|
||||||
{
|
},
|
||||||
id: "total",
|
{
|
||||||
title: intl.formatMessage(columnsMessages.total),
|
id: "total",
|
||||||
width: 200,
|
title: intl.formatMessage(columnsMessages.total),
|
||||||
icon: getColumnSortDirectionIcon(sort, "total"),
|
width: 200,
|
||||||
},
|
},
|
||||||
];
|
].map(column => ({
|
||||||
|
...column,
|
||||||
|
icon: getColumnSortDirectionIcon(sort, column.id),
|
||||||
|
}));
|
||||||
|
|
||||||
export const createGetCellContent =
|
export const createGetCellContent =
|
||||||
({
|
({
|
||||||
|
@ -47,15 +49,15 @@ export const createGetCellContent =
|
||||||
locale,
|
locale,
|
||||||
columns,
|
columns,
|
||||||
}: {
|
}: {
|
||||||
orders: RelayToFlat<OrderDraftListQuery["draftOrders"]>;
|
orders: OrderDraft[];
|
||||||
columns: AvailableColumn[];
|
columns: AvailableColumn[];
|
||||||
locale: Locale;
|
locale: Locale;
|
||||||
}) =>
|
}) =>
|
||||||
([column, row]: Item): GridCell => {
|
([column, row]: Item): GridCell => {
|
||||||
const rowData = orders[row];
|
const rowData: OrderDraft | undefined = orders[row];
|
||||||
const columnId = columns[column]?.id;
|
const columnId = columns[column]?.id;
|
||||||
|
|
||||||
if (!columnId) {
|
if (!columnId || !rowData) {
|
||||||
return readonlyTextCell("");
|
return readonlyTextCell("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,12 +78,12 @@ export const createGetCellContent =
|
||||||
readonly: true,
|
readonly: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
default:
|
||||||
|
return readonlyTextCell("");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getCustomerName(
|
export function getCustomerName(rowData: OrderDraft) {
|
||||||
rowData: RelayToFlat<OrderDraftListQuery["draftOrders"]>[number],
|
|
||||||
) {
|
|
||||||
if (rowData?.billingAddress?.firstName && rowData?.billingAddress?.lastName) {
|
if (rowData?.billingAddress?.firstName && rowData?.billingAddress?.lastName) {
|
||||||
return `${rowData.billingAddress.firstName} ${rowData.billingAddress.lastName}`;
|
return `${rowData.billingAddress.firstName} ${rowData.billingAddress.lastName}`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import {
|
import {
|
||||||
MarkAsPaidStrategyEnum,
|
MarkAsPaidStrategyEnum,
|
||||||
OrderDetailsFragment,
|
OrderDetailsFragment,
|
||||||
|
OrderDraftListQuery,
|
||||||
OrderRefundDataQuery,
|
OrderRefundDataQuery,
|
||||||
TransactionEventFragment,
|
TransactionEventFragment,
|
||||||
TransactionItemFragment,
|
TransactionItemFragment,
|
||||||
} from "@dashboard/graphql";
|
} from "@dashboard/graphql";
|
||||||
|
import { RelayToFlat } from "@dashboard/types";
|
||||||
|
|
||||||
/** Check if order has transactions & feature flag enabled */
|
/** Check if order has transactions & feature flag enabled */
|
||||||
export const orderHasTransactions = (order: OrderDetailsFragment): boolean =>
|
export const orderHasTransactions = (order: OrderDetailsFragment): boolean =>
|
||||||
|
@ -38,6 +40,10 @@ export type OrderRefundSharedType = Pick<
|
||||||
keyof OrderRefundData
|
keyof OrderRefundData
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
export type OrderDraft = RelayToFlat<
|
||||||
|
NonNullable<OrderDraftListQuery["draftOrders"]>
|
||||||
|
>[number];
|
||||||
|
|
||||||
/** Type of the trasaction event (e.g. CHARGE_SUCCESS -> CHARGE) */
|
/** Type of the trasaction event (e.g. CHARGE_SUCCESS -> CHARGE) */
|
||||||
export type TransactionEventType =
|
export type TransactionEventType =
|
||||||
| "REFUND"
|
| "REFUND"
|
||||||
|
|
Loading…
Reference in a new issue