Introduce datagrid on voucher list view (#4036)
This commit is contained in:
parent
dac77169ae
commit
41fde64fc8
13 changed files with 588 additions and 147 deletions
5
.changeset/soft-buses-roll.md
Normal file
5
.changeset/soft-buses-roll.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"saleor-dashboard": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Introduce datagrid on voucher list view
|
|
@ -997,9 +997,6 @@
|
||||||
"50lR2F": {
|
"50lR2F": {
|
||||||
"string": "- used by Payment Plugins"
|
"string": "- used by Payment Plugins"
|
||||||
},
|
},
|
||||||
"51HE+Q": {
|
|
||||||
"string": "No sales found"
|
|
||||||
},
|
|
||||||
"54KYgS": {
|
"54KYgS": {
|
||||||
"context": "months after label",
|
"context": "months after label",
|
||||||
"string": "months after issue"
|
"string": "months after issue"
|
||||||
|
@ -2921,9 +2918,6 @@
|
||||||
"context": "window title",
|
"context": "window title",
|
||||||
"string": "Create category"
|
"string": "Create category"
|
||||||
},
|
},
|
||||||
"IruP2T": {
|
|
||||||
"string": "Search Voucher"
|
|
||||||
},
|
|
||||||
"IwEQvz": {
|
"IwEQvz": {
|
||||||
"context": "success activate alert message",
|
"context": "success activate alert message",
|
||||||
"string": "Successfully activated gift {count,plural,one{card} other{cards}}"
|
"string": "Successfully activated gift {count,plural,one{card} other{cards}}"
|
||||||
|
@ -5551,6 +5545,9 @@
|
||||||
"context": "product type",
|
"context": "product type",
|
||||||
"string": "Product Type"
|
"string": "Product Type"
|
||||||
},
|
},
|
||||||
|
"bPshhv": {
|
||||||
|
"string": "Search vouchers..."
|
||||||
|
},
|
||||||
"bRJD/v": {
|
"bRJD/v": {
|
||||||
"context": "button",
|
"context": "button",
|
||||||
"string": "Create permission group"
|
"string": "Create permission group"
|
||||||
|
@ -6925,6 +6922,9 @@
|
||||||
"context": "section header",
|
"context": "section header",
|
||||||
"string": "Eligible Variants"
|
"string": "Eligible Variants"
|
||||||
},
|
},
|
||||||
|
"lfXze9": {
|
||||||
|
"string": "Delete vouchers"
|
||||||
|
},
|
||||||
"li1BBk": {
|
"li1BBk": {
|
||||||
"context": "export items as csv file",
|
"context": "export items as csv file",
|
||||||
"string": "Plain CSV file"
|
"string": "Plain CSV file"
|
||||||
|
@ -7394,9 +7394,9 @@
|
||||||
"context": "status",
|
"context": "status",
|
||||||
"string": "Deactivated"
|
"string": "Deactivated"
|
||||||
},
|
},
|
||||||
"pNrF72": {
|
"pOUOnw": {
|
||||||
"context": "tab name",
|
"context": "tab name",
|
||||||
"string": "All Vouchers"
|
"string": "All vouchers"
|
||||||
},
|
},
|
||||||
"pPef6L": {
|
"pPef6L": {
|
||||||
"context": "order payment",
|
"context": "order payment",
|
||||||
|
|
|
@ -127,6 +127,7 @@ export const defaultListSettings: AppListViewSettings = {
|
||||||
},
|
},
|
||||||
[ListViews.VOUCHER_LIST]: {
|
[ListViews.VOUCHER_LIST]: {
|
||||||
rowNumber: PAGINATE_BY,
|
rowNumber: PAGINATE_BY,
|
||||||
|
columns: ["code", "min-spent", "start-date", "end-date", "value", "limit"],
|
||||||
},
|
},
|
||||||
[ListViews.WAREHOUSE_LIST]: {
|
[ListViews.WAREHOUSE_LIST]: {
|
||||||
rowNumber: PAGINATE_BY,
|
rowNumber: PAGINATE_BY,
|
||||||
|
|
|
@ -25,7 +25,7 @@ export const columnsMessages = defineMessages({
|
||||||
|
|
||||||
export const messages = defineMessages({
|
export const messages = defineMessages({
|
||||||
empty: {
|
empty: {
|
||||||
id: "51HE+Q",
|
id: "U2mOqA",
|
||||||
defaultMessage: "No sales found",
|
defaultMessage: "No vouchers found",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,176 @@
|
||||||
|
import { ColumnPicker } from "@dashboard/components/Datagrid/ColumnPicker/ColumnPicker";
|
||||||
|
import { useColumns } from "@dashboard/components/Datagrid/ColumnPicker/useColumns";
|
||||||
|
import Datagrid from "@dashboard/components/Datagrid/Datagrid";
|
||||||
|
import {
|
||||||
|
DatagridChangeStateContext,
|
||||||
|
useDatagridChangeState,
|
||||||
|
} from "@dashboard/components/Datagrid/hooks/useDatagridChange";
|
||||||
|
import { TablePaginationWithContext } from "@dashboard/components/TablePagination";
|
||||||
|
import { commonTooltipMessages } from "@dashboard/components/TooltipTableCellHeader/messages";
|
||||||
|
import { VoucherListUrlSortField, voucherUrl } from "@dashboard/discounts/urls";
|
||||||
|
import { canBeSorted } from "@dashboard/discounts/views/VoucherList/sort";
|
||||||
|
import { VoucherFragment } from "@dashboard/graphql";
|
||||||
|
import useLocale from "@dashboard/hooks/useLocale";
|
||||||
|
import useNavigator from "@dashboard/hooks/useNavigator";
|
||||||
|
import { ChannelProps, ListProps, SortPage } from "@dashboard/types";
|
||||||
|
import { Item } from "@glideapps/glide-data-grid";
|
||||||
|
import { Box } from "@saleor/macaw-ui/next";
|
||||||
|
import React, { useCallback, useMemo } from "react";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import {
|
||||||
|
createGetCellContent,
|
||||||
|
vouchersListStaticColumnsAdapter,
|
||||||
|
} from "./datagrid";
|
||||||
|
import { messages } from "./messages";
|
||||||
|
|
||||||
|
interface VoucherListDatagridProps
|
||||||
|
extends ListProps,
|
||||||
|
SortPage<VoucherListUrlSortField>,
|
||||||
|
ChannelProps {
|
||||||
|
vouchers: VoucherFragment[];
|
||||||
|
onSelectVouchersIds: (
|
||||||
|
rowsIndex: number[],
|
||||||
|
clearSelection: () => void,
|
||||||
|
) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const VoucherListDatagrid = ({
|
||||||
|
vouchers,
|
||||||
|
settings,
|
||||||
|
sort,
|
||||||
|
selectedChannelId,
|
||||||
|
disabled,
|
||||||
|
filterDependency,
|
||||||
|
onSort,
|
||||||
|
onSelectVouchersIds,
|
||||||
|
onUpdateListSettings,
|
||||||
|
}: VoucherListDatagridProps) => {
|
||||||
|
const datagridState = useDatagridChangeState();
|
||||||
|
const navigate = useNavigator();
|
||||||
|
const { locale } = useLocale();
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const vouchersListStaticColumns = useMemo(
|
||||||
|
() => vouchersListStaticColumnsAdapter(intl, sort),
|
||||||
|
[intl, sort],
|
||||||
|
);
|
||||||
|
|
||||||
|
const onColumnChange = useCallback(
|
||||||
|
(picked: string[]) => {
|
||||||
|
if (onUpdateListSettings) {
|
||||||
|
onUpdateListSettings("columns", picked.filter(Boolean));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[onUpdateListSettings],
|
||||||
|
);
|
||||||
|
|
||||||
|
const {
|
||||||
|
handlers,
|
||||||
|
visibleColumns,
|
||||||
|
recentlyAddedColumn,
|
||||||
|
staticColumns,
|
||||||
|
selectedColumns,
|
||||||
|
} = useColumns({
|
||||||
|
selectedColumns: settings?.columns ?? [],
|
||||||
|
staticColumns: vouchersListStaticColumns,
|
||||||
|
onSave: onColumnChange,
|
||||||
|
});
|
||||||
|
|
||||||
|
const getCellContent = useCallback(
|
||||||
|
createGetCellContent({
|
||||||
|
vouchers,
|
||||||
|
columns: visibleColumns,
|
||||||
|
locale,
|
||||||
|
selectedChannelId,
|
||||||
|
}),
|
||||||
|
[vouchers, selectedChannelId, locale, visibleColumns],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleRowClick = useCallback(
|
||||||
|
([_, row]: Item) => {
|
||||||
|
const rowData: VoucherFragment = vouchers[row];
|
||||||
|
|
||||||
|
if (rowData) {
|
||||||
|
navigate(voucherUrl(rowData.id));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[vouchers],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleRowAnchor = useCallback(
|
||||||
|
([, row]: Item) => voucherUrl(vouchers[row].id),
|
||||||
|
[vouchers],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleGetColumnTooltipContent = useCallback(
|
||||||
|
(col: number): string => {
|
||||||
|
const columnName = visibleColumns[col].id as VoucherListUrlSortField;
|
||||||
|
|
||||||
|
if (canBeSorted(columnName, !!selectedChannelId)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sortable but requrie selected channel
|
||||||
|
return intl.formatMessage(commonTooltipMessages.noFilterSelected, {
|
||||||
|
filterName: filterDependency?.label ?? "",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[filterDependency, intl, selectedChannelId, visibleColumns],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleHeaderClick = useCallback(
|
||||||
|
(col: number) => {
|
||||||
|
const columnName = visibleColumns[col].id as VoucherListUrlSortField;
|
||||||
|
|
||||||
|
if (canBeSorted(columnName, !!selectedChannelId)) {
|
||||||
|
onSort(columnName);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[visibleColumns, onSort],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DatagridChangeStateContext.Provider value={datagridState}>
|
||||||
|
<Datagrid
|
||||||
|
readonly
|
||||||
|
loading={disabled}
|
||||||
|
rowMarkers="checkbox"
|
||||||
|
columnSelect="single"
|
||||||
|
hasRowHover={true}
|
||||||
|
onColumnMoved={handlers.onMove}
|
||||||
|
onColumnResize={handlers.onResize}
|
||||||
|
verticalBorder={col => col > 0}
|
||||||
|
rows={vouchers?.length ?? 0}
|
||||||
|
availableColumns={visibleColumns}
|
||||||
|
emptyText={intl.formatMessage(messages.empty)}
|
||||||
|
onRowSelectionChange={onSelectVouchersIds}
|
||||||
|
getCellContent={getCellContent}
|
||||||
|
getCellError={() => false}
|
||||||
|
selectionActions={() => null}
|
||||||
|
menuItems={() => []}
|
||||||
|
onRowClick={handleRowClick}
|
||||||
|
onHeaderClicked={handleHeaderClick}
|
||||||
|
rowAnchor={handleRowAnchor}
|
||||||
|
getColumnTooltipContent={handleGetColumnTooltipContent}
|
||||||
|
recentlyAddedColumn={recentlyAddedColumn}
|
||||||
|
renderColumnPicker={() => (
|
||||||
|
<ColumnPicker
|
||||||
|
staticColumns={staticColumns}
|
||||||
|
selectedColumns={selectedColumns}
|
||||||
|
onToggle={handlers.onToggle}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Box paddingX={6}>
|
||||||
|
<TablePaginationWithContext
|
||||||
|
component="div"
|
||||||
|
settings={settings}
|
||||||
|
disabled={disabled}
|
||||||
|
onUpdateListSettings={onUpdateListSettings}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</DatagridChangeStateContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
143
src/discounts/components/VoucherListDatagrid/datagrid.ts
Normal file
143
src/discounts/components/VoucherListDatagrid/datagrid.ts
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
import { PLACEHOLDER } from "@dashboard/components/Datagrid/const";
|
||||||
|
import {
|
||||||
|
moneyCell,
|
||||||
|
readonlyTextCell,
|
||||||
|
} from "@dashboard/components/Datagrid/customCells/cells";
|
||||||
|
import { AvailableColumn } from "@dashboard/components/Datagrid/types";
|
||||||
|
import { Locale } from "@dashboard/components/Locale";
|
||||||
|
import { VoucherListUrlSortField } from "@dashboard/discounts/urls";
|
||||||
|
import { VoucherFragment } from "@dashboard/graphql";
|
||||||
|
import { Sort } from "@dashboard/types";
|
||||||
|
import { getColumnSortDirectionIcon } from "@dashboard/utils/columns/getColumnSortDirectionIcon";
|
||||||
|
import { GridCell, Item } from "@glideapps/glide-data-grid";
|
||||||
|
import moment from "moment";
|
||||||
|
import { IntlShape } from "react-intl";
|
||||||
|
|
||||||
|
import { columnsMessages } from "./messages";
|
||||||
|
|
||||||
|
export const vouchersListStaticColumnsAdapter = (
|
||||||
|
intl: IntlShape,
|
||||||
|
sort: Sort<VoucherListUrlSortField>,
|
||||||
|
) =>
|
||||||
|
[
|
||||||
|
{
|
||||||
|
id: "code",
|
||||||
|
title: intl.formatMessage(columnsMessages.code),
|
||||||
|
width: 350,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "min-spent",
|
||||||
|
title: intl.formatMessage(columnsMessages.minSpent),
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "start-date",
|
||||||
|
title: intl.formatMessage(columnsMessages.starts),
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "end-date",
|
||||||
|
title: intl.formatMessage(columnsMessages.ends),
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "value",
|
||||||
|
title: intl.formatMessage(columnsMessages.value),
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "limit",
|
||||||
|
title: intl.formatMessage(columnsMessages.uses),
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
].map(column => ({
|
||||||
|
...column,
|
||||||
|
icon: getColumnSortDirectionIcon(sort, column.id),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const createGetCellContent =
|
||||||
|
({
|
||||||
|
vouchers,
|
||||||
|
columns,
|
||||||
|
locale,
|
||||||
|
selectedChannelId,
|
||||||
|
}: {
|
||||||
|
vouchers: VoucherFragment[];
|
||||||
|
columns: AvailableColumn[];
|
||||||
|
locale: Locale;
|
||||||
|
selectedChannelId?: string;
|
||||||
|
}) =>
|
||||||
|
([column, row]: Item): GridCell => {
|
||||||
|
const rowData: VoucherFragment | undefined = vouchers[row];
|
||||||
|
const columnId = columns[column]?.id;
|
||||||
|
|
||||||
|
if (!columnId || !rowData) {
|
||||||
|
return readonlyTextCell("");
|
||||||
|
}
|
||||||
|
|
||||||
|
const channel = rowData?.channelListings?.find(
|
||||||
|
lisiting => lisiting.channel.id === selectedChannelId,
|
||||||
|
);
|
||||||
|
const hasChannelsLoaded = rowData?.channelListings?.length;
|
||||||
|
|
||||||
|
switch (columnId) {
|
||||||
|
case "code":
|
||||||
|
return readonlyTextCell(rowData?.code ?? PLACEHOLDER);
|
||||||
|
case "min-spent":
|
||||||
|
return rowData?.code && hasChannelsLoaded
|
||||||
|
? moneyCell(
|
||||||
|
channel?.minSpent?.amount ?? "",
|
||||||
|
channel?.minSpent?.currency ?? "",
|
||||||
|
{
|
||||||
|
readonly: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
: readonlyTextCell(PLACEHOLDER);
|
||||||
|
case "start-date":
|
||||||
|
return readonlyTextCell(
|
||||||
|
rowData.startDate
|
||||||
|
? moment(rowData.startDate).locale(locale).format("lll")
|
||||||
|
: PLACEHOLDER,
|
||||||
|
);
|
||||||
|
case "end-date":
|
||||||
|
return readonlyTextCell(
|
||||||
|
rowData.endDate
|
||||||
|
? moment(rowData.endDate).locale(locale).format("lll")
|
||||||
|
: PLACEHOLDER,
|
||||||
|
);
|
||||||
|
|
||||||
|
case "value":
|
||||||
|
return getVoucherValueCell(rowData, channel);
|
||||||
|
|
||||||
|
case "limit":
|
||||||
|
return readonlyTextCell(
|
||||||
|
rowData.usageLimit === null
|
||||||
|
? PLACEHOLDER
|
||||||
|
: rowData.usageLimit.toString(),
|
||||||
|
);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return readonlyTextCell("");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function getVoucherValueCell(
|
||||||
|
voucher: VoucherFragment,
|
||||||
|
channel: NonNullable<VoucherFragment["channelListings"]>[number] | undefined,
|
||||||
|
) {
|
||||||
|
const hasChannelsLoaded = voucher?.channelListings?.length;
|
||||||
|
|
||||||
|
if (!hasChannelsLoaded) {
|
||||||
|
return readonlyTextCell(PLACEHOLDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (voucher?.discountValueType === "FIXED") {
|
||||||
|
return moneyCell(channel?.discountValue ?? "", channel?.currency ?? "", {
|
||||||
|
readonly: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return moneyCell(channel?.discountValue ?? "", "%", {
|
||||||
|
readonly: true,
|
||||||
|
});
|
||||||
|
}
|
1
src/discounts/components/VoucherListDatagrid/index.ts
Normal file
1
src/discounts/components/VoucherListDatagrid/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from "./VoucherListDatagrid";
|
41
src/discounts/components/VoucherListDatagrid/messages.ts
Normal file
41
src/discounts/components/VoucherListDatagrid/messages.ts
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import { defineMessages } from "react-intl";
|
||||||
|
|
||||||
|
export const columnsMessages = defineMessages({
|
||||||
|
code: {
|
||||||
|
id: "JsPIOX",
|
||||||
|
defaultMessage: "Code",
|
||||||
|
description: "voucher code",
|
||||||
|
},
|
||||||
|
minSpent: {
|
||||||
|
id: "tuYPlG",
|
||||||
|
defaultMessage: "Min. Spent",
|
||||||
|
description: "minimum amount of spent money to activate voucher",
|
||||||
|
},
|
||||||
|
starts: {
|
||||||
|
id: "5u7b3V",
|
||||||
|
defaultMessage: "Starts",
|
||||||
|
description: "voucher is active from date",
|
||||||
|
},
|
||||||
|
ends: {
|
||||||
|
id: "b6L9n7",
|
||||||
|
defaultMessage: "Ends",
|
||||||
|
description: "voucher is active until date",
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
id: "JV+EiM",
|
||||||
|
defaultMessage: "Value",
|
||||||
|
description: "voucher value",
|
||||||
|
},
|
||||||
|
uses: {
|
||||||
|
id: "yHwvLL",
|
||||||
|
defaultMessage: "Uses",
|
||||||
|
description: "voucher uses",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const messages = defineMessages({
|
||||||
|
empty: {
|
||||||
|
id: "U2mOqA",
|
||||||
|
defaultMessage: "No vouchers found",
|
||||||
|
},
|
||||||
|
});
|
|
@ -2,12 +2,11 @@
|
||||||
import { voucherList } from "@dashboard/discounts/fixtures";
|
import { voucherList } from "@dashboard/discounts/fixtures";
|
||||||
import { VoucherListUrlSortField } from "@dashboard/discounts/urls";
|
import { VoucherListUrlSortField } from "@dashboard/discounts/urls";
|
||||||
import {
|
import {
|
||||||
filterPageProps,
|
filterPresetsProps,
|
||||||
listActionsProps,
|
listActionsProps,
|
||||||
pageListProps,
|
pageListProps,
|
||||||
searchPageProps,
|
searchPageProps,
|
||||||
sortPageProps,
|
sortPageProps,
|
||||||
tabPageProps,
|
|
||||||
} from "@dashboard/fixtures";
|
} from "@dashboard/fixtures";
|
||||||
import { DiscountStatusEnum, VoucherDiscountType } from "@dashboard/graphql";
|
import { DiscountStatusEnum, VoucherDiscountType } from "@dashboard/graphql";
|
||||||
import { Meta, StoryObj } from "@storybook/react";
|
import { Meta, StoryObj } from "@storybook/react";
|
||||||
|
@ -20,8 +19,11 @@ const props: VoucherListPageProps = {
|
||||||
...pageListProps.default,
|
...pageListProps.default,
|
||||||
...searchPageProps,
|
...searchPageProps,
|
||||||
...sortPageProps,
|
...sortPageProps,
|
||||||
...tabPageProps,
|
...filterPresetsProps,
|
||||||
...filterPageProps,
|
onSelectVouchersIds: () => undefined,
|
||||||
|
selectedVouchersIds: [],
|
||||||
|
onVoucherDelete: () => undefined,
|
||||||
|
onFilterChange: () => undefined,
|
||||||
filterOpts: {
|
filterOpts: {
|
||||||
channel: {
|
channel: {
|
||||||
active: false,
|
active: false,
|
||||||
|
@ -62,6 +64,10 @@ const props: VoucherListPageProps = {
|
||||||
sort: VoucherListUrlSortField.code,
|
sort: VoucherListUrlSortField.code,
|
||||||
},
|
},
|
||||||
vouchers: voucherList,
|
vouchers: voucherList,
|
||||||
|
settings: {
|
||||||
|
rowNumber: 20,
|
||||||
|
columns: ["code", "min-spent", "start-date", "end-date", "value", "limit"],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const meta: Meta<typeof VoucherListPage> = {
|
const meta: Meta<typeof VoucherListPage> = {
|
||||||
|
@ -85,6 +91,7 @@ export const Loading: Story = {
|
||||||
args: {
|
args: {
|
||||||
...props,
|
...props,
|
||||||
vouchers: undefined,
|
vouchers: undefined,
|
||||||
|
disabled: true,
|
||||||
},
|
},
|
||||||
parameters: {
|
parameters: {
|
||||||
chromatic: { diffThreshold: 0.85 },
|
chromatic: { diffThreshold: 0.85 },
|
||||||
|
|
|
@ -1,28 +1,29 @@
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
|
import { ListFilters } from "@dashboard/components/AppLayout/ListFilters";
|
||||||
import { TopNav } from "@dashboard/components/AppLayout/TopNav";
|
import { TopNav } from "@dashboard/components/AppLayout/TopNav";
|
||||||
import { Button } from "@dashboard/components/Button";
|
import { BulkDeleteButton } from "@dashboard/components/BulkDeleteButton";
|
||||||
import { getByName } from "@dashboard/components/Filter/utils";
|
import { getByName } from "@dashboard/components/Filter/utils";
|
||||||
import FilterBar from "@dashboard/components/FilterBar";
|
import { FilterPresetsSelect } from "@dashboard/components/FilterPresetsSelect";
|
||||||
import { ListPageLayout } from "@dashboard/components/Layouts";
|
import { ListPageLayout } from "@dashboard/components/Layouts";
|
||||||
import {
|
import {
|
||||||
voucherAddUrl,
|
voucherAddUrl,
|
||||||
VoucherListUrlSortField,
|
VoucherListUrlSortField,
|
||||||
} from "@dashboard/discounts/urls";
|
} from "@dashboard/discounts/urls";
|
||||||
import { VoucherFragment } from "@dashboard/graphql";
|
import { VoucherFragment } from "@dashboard/graphql";
|
||||||
|
import useNavigator from "@dashboard/hooks/useNavigator";
|
||||||
import { sectionNames } from "@dashboard/intl";
|
import { sectionNames } from "@dashboard/intl";
|
||||||
import {
|
import {
|
||||||
ChannelProps,
|
ChannelProps,
|
||||||
FilterPageProps,
|
FilterPagePropsWithPresets,
|
||||||
ListActions,
|
|
||||||
PageListProps,
|
PageListProps,
|
||||||
SortPage,
|
SortPage,
|
||||||
TabPageProps,
|
|
||||||
} from "@dashboard/types";
|
} from "@dashboard/types";
|
||||||
import { Card } from "@material-ui/core";
|
import { Card } from "@material-ui/core";
|
||||||
import React from "react";
|
import { Box, Button, ChevronRightIcon } from "@saleor/macaw-ui/next";
|
||||||
|
import React, { useState } from "react";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
import VoucherList from "../VoucherList";
|
import { VoucherListDatagrid } from "../VoucherListDatagrid";
|
||||||
import {
|
import {
|
||||||
createFilterStructure,
|
createFilterStructure,
|
||||||
VoucherFilterKeys,
|
VoucherFilterKeys,
|
||||||
|
@ -31,69 +32,119 @@ import {
|
||||||
|
|
||||||
export interface VoucherListPageProps
|
export interface VoucherListPageProps
|
||||||
extends PageListProps,
|
extends PageListProps,
|
||||||
ListActions,
|
FilterPagePropsWithPresets<VoucherFilterKeys, VoucherListFilterOpts>,
|
||||||
FilterPageProps<VoucherFilterKeys, VoucherListFilterOpts>,
|
|
||||||
SortPage<VoucherListUrlSortField>,
|
SortPage<VoucherListUrlSortField>,
|
||||||
TabPageProps,
|
|
||||||
ChannelProps {
|
ChannelProps {
|
||||||
vouchers: VoucherFragment[];
|
vouchers: VoucherFragment[];
|
||||||
|
selectedVouchersIds: string[];
|
||||||
|
onVoucherDelete: () => void;
|
||||||
|
onSelectVouchersIds: (rows: number[], clearSelection: () => void) => void;
|
||||||
}
|
}
|
||||||
const VoucherListPage: React.FC<VoucherListPageProps> = ({
|
const VoucherListPage: React.FC<VoucherListPageProps> = ({
|
||||||
currentTab,
|
|
||||||
filterOpts,
|
filterOpts,
|
||||||
initialSearch,
|
initialSearch,
|
||||||
onAll,
|
|
||||||
onFilterChange,
|
onFilterChange,
|
||||||
onSearchChange,
|
onSearchChange,
|
||||||
onTabChange,
|
hasPresetsChanged,
|
||||||
onTabDelete,
|
onFilterPresetChange,
|
||||||
onTabSave,
|
onFilterPresetDelete,
|
||||||
tabs,
|
onFilterPresetPresetSave,
|
||||||
|
onFilterPresetUpdate,
|
||||||
|
onFilterPresetsAll,
|
||||||
|
filterPresets,
|
||||||
|
selectedFilterPreset,
|
||||||
|
onVoucherDelete,
|
||||||
|
selectedVouchersIds,
|
||||||
|
currencySymbol,
|
||||||
...listProps
|
...listProps
|
||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const navigate = useNavigator();
|
||||||
const structure = createFilterStructure(intl, filterOpts);
|
const structure = createFilterStructure(intl, filterOpts);
|
||||||
|
const [isFilterPresetOpen, setFilterPresetOpen] = useState(false);
|
||||||
|
|
||||||
const filterDependency = structure.find(getByName("channel"));
|
const filterDependency = structure.find(getByName("channel"));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ListPageLayout>
|
<ListPageLayout>
|
||||||
<TopNav title={intl.formatMessage(sectionNames.vouchers)}>
|
<TopNav
|
||||||
<Button
|
title={intl.formatMessage(sectionNames.vouchers)}
|
||||||
href={voucherAddUrl()}
|
withoutBorder
|
||||||
variant="primary"
|
isAlignToRight={false}
|
||||||
data-test-id="create-voucher"
|
>
|
||||||
|
<Box
|
||||||
|
__flex={1}
|
||||||
|
display="flex"
|
||||||
|
justifyContent="space-between"
|
||||||
|
alignItems="center"
|
||||||
>
|
>
|
||||||
<FormattedMessage
|
<Box display="flex">
|
||||||
id="GbhZJ4"
|
<Box marginX={3} display="flex" alignItems="center">
|
||||||
defaultMessage="Create voucher"
|
<ChevronRightIcon />
|
||||||
description="button"
|
</Box>
|
||||||
/>
|
|
||||||
</Button>
|
<FilterPresetsSelect
|
||||||
|
presetsChanged={hasPresetsChanged()}
|
||||||
|
onSelect={onFilterPresetChange}
|
||||||
|
onRemove={onFilterPresetDelete}
|
||||||
|
onUpdate={onFilterPresetUpdate}
|
||||||
|
savedPresets={filterPresets}
|
||||||
|
activePreset={selectedFilterPreset}
|
||||||
|
onSelectAll={onFilterPresetsAll}
|
||||||
|
onSave={onFilterPresetPresetSave}
|
||||||
|
isOpen={isFilterPresetOpen}
|
||||||
|
onOpenChange={setFilterPresetOpen}
|
||||||
|
selectAllLabel={intl.formatMessage({
|
||||||
|
id: "pOUOnw",
|
||||||
|
defaultMessage: "All vouchers",
|
||||||
|
description: "tab name",
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<Button
|
||||||
|
onClick={() => navigate(voucherAddUrl())}
|
||||||
|
variant="primary"
|
||||||
|
data-test-id="create-voucher"
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id="GbhZJ4"
|
||||||
|
defaultMessage="Create voucher"
|
||||||
|
description="button"
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
</TopNav>
|
</TopNav>
|
||||||
<Card>
|
<Card>
|
||||||
<FilterBar
|
<ListFilters<VoucherFilterKeys>
|
||||||
allTabLabel={intl.formatMessage({
|
currencySymbol={currencySymbol}
|
||||||
id: "pNrF72",
|
|
||||||
defaultMessage: "All Vouchers",
|
|
||||||
description: "tab name",
|
|
||||||
})}
|
|
||||||
currentTab={currentTab}
|
|
||||||
filterStructure={structure}
|
|
||||||
initialSearch={initialSearch}
|
initialSearch={initialSearch}
|
||||||
searchPlaceholder={intl.formatMessage({
|
|
||||||
id: "IruP2T",
|
|
||||||
defaultMessage: "Search Voucher",
|
|
||||||
})}
|
|
||||||
tabs={tabs}
|
|
||||||
onAll={onAll}
|
|
||||||
onFilterChange={onFilterChange}
|
onFilterChange={onFilterChange}
|
||||||
onSearchChange={onSearchChange}
|
onSearchChange={onSearchChange}
|
||||||
onTabChange={onTabChange}
|
filterStructure={structure}
|
||||||
onTabDelete={onTabDelete}
|
searchPlaceholder={intl.formatMessage({
|
||||||
onTabSave={onTabSave}
|
id: "bPshhv",
|
||||||
|
defaultMessage: "Search vouchers...",
|
||||||
|
})}
|
||||||
|
actions={
|
||||||
|
<Box display="flex" gap={4}>
|
||||||
|
{selectedVouchersIds.length > 0 && (
|
||||||
|
<BulkDeleteButton onClick={onVoucherDelete}>
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="Delete vouchers"
|
||||||
|
id="lfXze9"
|
||||||
|
/>
|
||||||
|
</BulkDeleteButton>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<VoucherListDatagrid
|
||||||
|
filterDependency={filterDependency}
|
||||||
|
{...listProps}
|
||||||
/>
|
/>
|
||||||
<VoucherList filterDependency={filterDependency} {...listProps} />
|
|
||||||
</Card>
|
</Card>
|
||||||
</ListPageLayout>
|
</ListPageLayout>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,15 +2,13 @@
|
||||||
import ActionDialog from "@dashboard/components/ActionDialog";
|
import ActionDialog from "@dashboard/components/ActionDialog";
|
||||||
import useAppChannel from "@dashboard/components/AppLayout/AppChannelContext";
|
import useAppChannel from "@dashboard/components/AppLayout/AppChannelContext";
|
||||||
import DeleteFilterTabDialog from "@dashboard/components/DeleteFilterTabDialog";
|
import DeleteFilterTabDialog from "@dashboard/components/DeleteFilterTabDialog";
|
||||||
import SaveFilterTabDialog, {
|
import SaveFilterTabDialog from "@dashboard/components/SaveFilterTabDialog";
|
||||||
SaveFilterTabDialogFormData,
|
|
||||||
} from "@dashboard/components/SaveFilterTabDialog";
|
|
||||||
import { WindowTitle } from "@dashboard/components/WindowTitle";
|
import { WindowTitle } from "@dashboard/components/WindowTitle";
|
||||||
import {
|
import {
|
||||||
useVoucherBulkDeleteMutation,
|
useVoucherBulkDeleteMutation,
|
||||||
useVoucherListQuery,
|
useVoucherListQuery,
|
||||||
} from "@dashboard/graphql";
|
} from "@dashboard/graphql";
|
||||||
import useBulkActions from "@dashboard/hooks/useBulkActions";
|
import { useFilterPresets } from "@dashboard/hooks/useFilterPresets";
|
||||||
import useListSettings from "@dashboard/hooks/useListSettings";
|
import useListSettings from "@dashboard/hooks/useListSettings";
|
||||||
import useNavigator from "@dashboard/hooks/useNavigator";
|
import useNavigator from "@dashboard/hooks/useNavigator";
|
||||||
import useNotifier from "@dashboard/hooks/useNotifier";
|
import useNotifier from "@dashboard/hooks/useNotifier";
|
||||||
|
@ -19,8 +17,8 @@ import usePaginator, {
|
||||||
createPaginationState,
|
createPaginationState,
|
||||||
PaginatorContext,
|
PaginatorContext,
|
||||||
} from "@dashboard/hooks/usePaginator";
|
} from "@dashboard/hooks/usePaginator";
|
||||||
|
import { useRowSelection } from "@dashboard/hooks/useRowSelection";
|
||||||
import { commonMessages, sectionNames } from "@dashboard/intl";
|
import { commonMessages, sectionNames } from "@dashboard/intl";
|
||||||
import { maybe } from "@dashboard/misc";
|
|
||||||
import { ListViews } from "@dashboard/types";
|
import { ListViews } from "@dashboard/types";
|
||||||
import createDialogActionHandlers from "@dashboard/utils/handlers/dialogActionHandlers";
|
import createDialogActionHandlers from "@dashboard/utils/handlers/dialogActionHandlers";
|
||||||
import createFilterHandlers from "@dashboard/utils/handlers/filterHandlers";
|
import createFilterHandlers from "@dashboard/utils/handlers/filterHandlers";
|
||||||
|
@ -28,8 +26,8 @@ import createSortHandler from "@dashboard/utils/handlers/sortHandler";
|
||||||
import { mapEdgesToItems, mapNodeToChoice } from "@dashboard/utils/maps";
|
import { mapEdgesToItems, mapNodeToChoice } from "@dashboard/utils/maps";
|
||||||
import { getSortParams } from "@dashboard/utils/sort";
|
import { getSortParams } from "@dashboard/utils/sort";
|
||||||
import { DialogContentText } from "@material-ui/core";
|
import { DialogContentText } from "@material-ui/core";
|
||||||
import { DeleteIcon, IconButton } from "@saleor/macaw-ui";
|
import isEqual from "lodash/isEqual";
|
||||||
import React, { useEffect } from "react";
|
import React, { useCallback, useEffect } from "react";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
import VoucherListPage from "../../components/VoucherListPage";
|
import VoucherListPage from "../../components/VoucherListPage";
|
||||||
|
@ -39,14 +37,10 @@ import {
|
||||||
VoucherListUrlQueryParams,
|
VoucherListUrlQueryParams,
|
||||||
} from "../../urls";
|
} from "../../urls";
|
||||||
import {
|
import {
|
||||||
deleteFilterTab,
|
|
||||||
getActiveFilters,
|
|
||||||
getFilterOpts,
|
getFilterOpts,
|
||||||
getFilterQueryParam,
|
getFilterQueryParam,
|
||||||
getFiltersCurrentTab,
|
|
||||||
getFilterTabs,
|
|
||||||
getFilterVariables,
|
getFilterVariables,
|
||||||
saveFilterTab,
|
storageUtils,
|
||||||
} from "./filters";
|
} from "./filters";
|
||||||
import { canBeSorted, DEFAULT_SORT_KEY, getSortQueryVariables } from "./sort";
|
import { canBeSorted, DEFAULT_SORT_KEY, getSortQueryVariables } from "./sort";
|
||||||
|
|
||||||
|
@ -57,9 +51,7 @@ interface VoucherListProps {
|
||||||
export const VoucherList: React.FC<VoucherListProps> = ({ params }) => {
|
export const VoucherList: React.FC<VoucherListProps> = ({ params }) => {
|
||||||
const navigate = useNavigator();
|
const navigate = useNavigator();
|
||||||
const notify = useNotifier();
|
const notify = useNotifier();
|
||||||
const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions(
|
|
||||||
params.ids,
|
|
||||||
);
|
|
||||||
const { updateListSettings, settings } = useListSettings(
|
const { updateListSettings, settings } = useListSettings(
|
||||||
ListViews.VOUCHER_LIST,
|
ListViews.VOUCHER_LIST,
|
||||||
);
|
);
|
||||||
|
@ -96,17 +88,38 @@ export const VoucherList: React.FC<VoucherListProps> = ({ params }) => {
|
||||||
variables: queryVariables,
|
variables: queryVariables,
|
||||||
});
|
});
|
||||||
|
|
||||||
const tabs = getFilterTabs();
|
const {
|
||||||
|
clearRowSelection,
|
||||||
|
selectedRowIds,
|
||||||
|
setSelectedRowIds,
|
||||||
|
setClearDatagridRowSelectionCallback,
|
||||||
|
} = useRowSelection(params);
|
||||||
|
|
||||||
const currentTab = getFiltersCurrentTab(params, tabs);
|
const {
|
||||||
|
hasPresetsChanged,
|
||||||
|
onPresetChange,
|
||||||
|
onPresetDelete,
|
||||||
|
onPresetSave,
|
||||||
|
onPresetUpdate,
|
||||||
|
selectedPreset,
|
||||||
|
presets,
|
||||||
|
getPresetNameToDelete,
|
||||||
|
setPresetIdToDelete,
|
||||||
|
} = useFilterPresets({
|
||||||
|
getUrl: voucherListUrl,
|
||||||
|
params,
|
||||||
|
storageUtils,
|
||||||
|
reset: clearRowSelection,
|
||||||
|
});
|
||||||
|
|
||||||
const [changeFilters, resetFilters, handleSearchChange] =
|
const [changeFilters, resetFilters, handleSearchChange] =
|
||||||
createFilterHandlers({
|
createFilterHandlers({
|
||||||
cleanupFn: reset,
|
cleanupFn: clearRowSelection,
|
||||||
createUrl: voucherListUrl,
|
createUrl: voucherListUrl,
|
||||||
getFilterQueryParam,
|
getFilterQueryParam,
|
||||||
navigate,
|
navigate,
|
||||||
params,
|
params,
|
||||||
|
keepActiveTab: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -120,29 +133,6 @@ export const VoucherList: React.FC<VoucherListProps> = ({ params }) => {
|
||||||
}
|
}
|
||||||
}, [params]);
|
}, [params]);
|
||||||
|
|
||||||
const handleTabChange = (tab: number) => {
|
|
||||||
reset();
|
|
||||||
navigate(
|
|
||||||
voucherListUrl({
|
|
||||||
activeTab: tab.toString(),
|
|
||||||
...getFilterTabs()[tab - 1].data,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleTabDelete = () => {
|
|
||||||
deleteFilterTab(currentTab);
|
|
||||||
reset();
|
|
||||||
navigate(voucherListUrl());
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleTabSave = (data: SaveFilterTabDialogFormData) => {
|
|
||||||
saveFilterTab(data.name, getActiveFilters(params));
|
|
||||||
handleTabChange(tabs.length + 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
const canOpenBulkActionDialog = maybe(() => params.ids.length > 0);
|
|
||||||
|
|
||||||
const paginationValues = usePaginator({
|
const paginationValues = usePaginator({
|
||||||
pageInfo: data?.vouchers?.pageInfo,
|
pageInfo: data?.vouchers?.pageInfo,
|
||||||
paginationState,
|
paginationState,
|
||||||
|
@ -157,66 +147,85 @@ export const VoucherList: React.FC<VoucherListProps> = ({ params }) => {
|
||||||
status: "success",
|
status: "success",
|
||||||
text: intl.formatMessage(commonMessages.savedChanges),
|
text: intl.formatMessage(commonMessages.savedChanges),
|
||||||
});
|
});
|
||||||
reset();
|
clearRowSelection();
|
||||||
closeModal();
|
closeModal();
|
||||||
refetch();
|
refetch();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const onVoucherBulkDelete = () =>
|
const onVoucherBulkDelete = async () => {
|
||||||
voucherBulkDelete({
|
await voucherBulkDelete({
|
||||||
variables: {
|
variables: {
|
||||||
ids: params.ids,
|
ids: selectedRowIds,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
clearRowSelection();
|
||||||
|
};
|
||||||
|
|
||||||
const handleSort = createSortHandler(navigate, voucherListUrl, params);
|
const handleSort = createSortHandler(navigate, voucherListUrl, params);
|
||||||
|
|
||||||
|
const vouchers = mapEdgesToItems(data?.vouchers) ?? [];
|
||||||
|
|
||||||
|
const handleSelectVouchersIds = useCallback(
|
||||||
|
(rows: number[], clearSelection: () => void) => {
|
||||||
|
if (!vouchers) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rowsIds = rows.map(row => vouchers[row]?.id);
|
||||||
|
const haveSaveValues = isEqual(rowsIds, selectedRowIds);
|
||||||
|
|
||||||
|
if (!haveSaveValues) {
|
||||||
|
setSelectedRowIds(rowsIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
setClearDatagridRowSelectionCallback(clearSelection);
|
||||||
|
},
|
||||||
|
[
|
||||||
|
vouchers,
|
||||||
|
selectedRowIds,
|
||||||
|
setClearDatagridRowSelectionCallback,
|
||||||
|
setSelectedRowIds,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PaginatorContext.Provider value={paginationValues}>
|
<PaginatorContext.Provider value={paginationValues}>
|
||||||
<WindowTitle title={intl.formatMessage(sectionNames.vouchers)} />
|
<WindowTitle title={intl.formatMessage(sectionNames.vouchers)} />
|
||||||
<VoucherListPage
|
<VoucherListPage
|
||||||
currentTab={currentTab}
|
onSelectVouchersIds={handleSelectVouchersIds}
|
||||||
filterOpts={getFilterOpts(params, channelOpts)}
|
filterOpts={getFilterOpts(params, channelOpts)}
|
||||||
initialSearch={params.query || ""}
|
initialSearch={params.query || ""}
|
||||||
onSearchChange={handleSearchChange}
|
onSearchChange={handleSearchChange}
|
||||||
onFilterChange={filter => changeFilters(filter)}
|
onFilterChange={filter => changeFilters(filter)}
|
||||||
onAll={resetFilters}
|
onFilterPresetsAll={resetFilters}
|
||||||
onTabChange={handleTabChange}
|
onFilterPresetDelete={(id: number) => {
|
||||||
onTabDelete={() => openModal("delete-search")}
|
setPresetIdToDelete(id);
|
||||||
onTabSave={() => openModal("save-search")}
|
openModal("delete-search");
|
||||||
tabs={tabs.map(tab => tab.name)}
|
}}
|
||||||
|
onFilterPresetPresetSave={() => openModal("save-search")}
|
||||||
|
onFilterPresetChange={onPresetChange}
|
||||||
|
onFilterPresetUpdate={onPresetUpdate}
|
||||||
|
hasPresetsChanged={hasPresetsChanged}
|
||||||
|
onVoucherDelete={() => openModal("remove")}
|
||||||
|
selectedFilterPreset={selectedPreset}
|
||||||
|
selectedVouchersIds={selectedRowIds}
|
||||||
|
currencySymbol={selectedChannel?.currencyCode}
|
||||||
|
filterPresets={presets.map(tab => tab.name)}
|
||||||
settings={settings}
|
settings={settings}
|
||||||
vouchers={mapEdgesToItems(data?.vouchers)}
|
vouchers={vouchers}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
onUpdateListSettings={updateListSettings}
|
onUpdateListSettings={updateListSettings}
|
||||||
onSort={handleSort}
|
onSort={handleSort}
|
||||||
isChecked={isSelected}
|
|
||||||
selected={listElements.length}
|
|
||||||
sort={getSortParams(params)}
|
sort={getSortParams(params)}
|
||||||
toggle={toggle}
|
|
||||||
toggleAll={toggleAll}
|
|
||||||
toolbar={
|
|
||||||
<IconButton
|
|
||||||
variant="secondary"
|
|
||||||
color="primary"
|
|
||||||
onClick={() =>
|
|
||||||
openModal("remove", {
|
|
||||||
ids: listElements,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<DeleteIcon />
|
|
||||||
</IconButton>
|
|
||||||
}
|
|
||||||
selectedChannelId={selectedChannel?.id}
|
selectedChannelId={selectedChannel?.id}
|
||||||
/>
|
/>
|
||||||
<ActionDialog
|
<ActionDialog
|
||||||
confirmButtonState={voucherBulkDeleteOpts.status}
|
confirmButtonState={voucherBulkDeleteOpts.status}
|
||||||
onClose={closeModal}
|
onClose={closeModal}
|
||||||
onConfirm={onVoucherBulkDelete}
|
onConfirm={onVoucherBulkDelete}
|
||||||
open={params.action === "remove" && canOpenBulkActionDialog}
|
open={params.action === "remove" && selectedRowIds.length > 0}
|
||||||
title={intl.formatMessage({
|
title={intl.formatMessage({
|
||||||
id: "Q0JJ4F",
|
id: "Q0JJ4F",
|
||||||
defaultMessage: "Delete Vouchers",
|
defaultMessage: "Delete Vouchers",
|
||||||
|
@ -224,32 +233,30 @@ export const VoucherList: React.FC<VoucherListProps> = ({ params }) => {
|
||||||
})}
|
})}
|
||||||
variant="delete"
|
variant="delete"
|
||||||
>
|
>
|
||||||
{canOpenBulkActionDialog && (
|
<DialogContentText>
|
||||||
<DialogContentText>
|
<FormattedMessage
|
||||||
<FormattedMessage
|
id="O9QPe1"
|
||||||
id="O9QPe1"
|
defaultMessage="{counter,plural,one{Are you sure you want to delete this voucher?} other{Are you sure you want to delete {displayQuantity} vouchers?}}"
|
||||||
defaultMessage="{counter,plural,one{Are you sure you want to delete this voucher?} other{Are you sure you want to delete {displayQuantity} vouchers?}}"
|
description="dialog content"
|
||||||
description="dialog content"
|
values={{
|
||||||
values={{
|
counter: selectedRowIds.length,
|
||||||
counter: params.ids.length,
|
displayQuantity: <strong>{selectedRowIds.length}</strong>,
|
||||||
displayQuantity: <strong>{params.ids.length}</strong>,
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
</DialogContentText>
|
||||||
</DialogContentText>
|
|
||||||
)}
|
|
||||||
</ActionDialog>
|
</ActionDialog>
|
||||||
<SaveFilterTabDialog
|
<SaveFilterTabDialog
|
||||||
open={params.action === "save-search"}
|
open={params.action === "save-search"}
|
||||||
confirmButtonState="default"
|
confirmButtonState="default"
|
||||||
onClose={closeModal}
|
onClose={closeModal}
|
||||||
onSubmit={handleTabSave}
|
onSubmit={onPresetSave}
|
||||||
/>
|
/>
|
||||||
<DeleteFilterTabDialog
|
<DeleteFilterTabDialog
|
||||||
open={params.action === "delete-search"}
|
open={params.action === "delete-search"}
|
||||||
confirmButtonState="default"
|
confirmButtonState="default"
|
||||||
onClose={closeModal}
|
onClose={closeModal}
|
||||||
onSubmit={handleTabDelete}
|
onSubmit={onPresetDelete}
|
||||||
tabName={maybe(() => tabs[currentTab - 1].name, "...")}
|
tabName={getPresetNameToDelete()}
|
||||||
/>
|
/>
|
||||||
</PaginatorContext.Provider>
|
</PaginatorContext.Provider>
|
||||||
);
|
);
|
||||||
|
|
|
@ -151,8 +151,7 @@ export function getFilterQueryParam(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const { deleteFilterTab, getFilterTabs, saveFilterTab } =
|
export const storageUtils = createFilterTabUtils<string>(VOUCHER_FILTERS_KEY);
|
||||||
createFilterTabUtils<VoucherListUrlFilters>(VOUCHER_FILTERS_KEY);
|
|
||||||
|
|
||||||
export const { areFiltersApplied, getActiveFilters, getFiltersCurrentTab } =
|
export const { areFiltersApplied, getActiveFilters, getFiltersCurrentTab } =
|
||||||
createFilterUtils<VoucherListUrlQueryParams, VoucherListUrlFilters>({
|
createFilterUtils<VoucherListUrlQueryParams, VoucherListUrlFilters>({
|
||||||
|
|
|
@ -18,6 +18,7 @@ export interface UseFilterPresets {
|
||||||
onPresetDelete: () => void;
|
onPresetDelete: () => void;
|
||||||
onPresetSave: (data: SaveFilterTabDialogFormData) => void;
|
onPresetSave: (data: SaveFilterTabDialogFormData) => void;
|
||||||
onPresetUpdate: (tabName: string) => void;
|
onPresetUpdate: (tabName: string) => void;
|
||||||
|
getPresetNameToDelete: () => string;
|
||||||
hasPresetsChanged: () => boolean;
|
hasPresetsChanged: () => boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,9 +123,18 @@ export const useFilterPresets = <
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getPresetNameToDelete = (): string => {
|
||||||
|
const presetIndex = presetIdToDelete ? presetIdToDelete - 1 : 0;
|
||||||
|
const preset = presets?.[presetIndex];
|
||||||
|
const tabName = preset?.name ?? "...";
|
||||||
|
|
||||||
|
return tabName;
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
presetIdToDelete,
|
presetIdToDelete,
|
||||||
setPresetIdToDelete,
|
setPresetIdToDelete,
|
||||||
|
getPresetNameToDelete,
|
||||||
presets,
|
presets,
|
||||||
selectedPreset,
|
selectedPreset,
|
||||||
onPresetChange,
|
onPresetChange,
|
||||||
|
|
Loading…
Reference in a new issue