Skip to content

Commit 9366c6d

Browse files
feat: order export and upload stream (medusajs#14243)
* feat: order export * Merge branch 'develop' of https://github.com/medusajs/medusa into feat/order-export * normalize status * rm util * serialize totals * test * lock * comments * configurable order list
1 parent e199f1e commit 9366c6d

File tree

31 files changed

+1041
-37
lines changed

31 files changed

+1041
-37
lines changed

packages/admin/dashboard/src/dashboard-app/routes/get-route.map.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,12 @@ export function getRouteMap({
300300
{
301301
path: "",
302302
lazy: () => import("../../routes/orders/order-list"),
303+
children: [
304+
{
305+
path: "export",
306+
lazy: () => import("../../routes/orders/order-export"),
307+
},
308+
],
303309
},
304310
{
305311
path: ":id",

packages/admin/dashboard/src/hooks/api/orders.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import {
1010
import { sdk } from "../../lib/client"
1111
import { queryClient } from "../../lib/query-client"
1212
import { queryKeysFactory, TQueryKey } from "../../lib/query-key-factory"
13-
import { reservationItemsQueryKeys } from "./reservations"
1413
import { inventoryItemsQueryKeys } from "./inventory"
14+
import { reservationItemsQueryKeys } from "./reservations"
1515

1616
const ORDERS_QUERY_KEY = "orders" as const
1717
const _orderKeys = queryKeysFactory(ORDERS_QUERY_KEY) as TQueryKey<"orders"> & {
@@ -438,3 +438,20 @@ export const useUpdateOrderChange = (
438438
...options,
439439
})
440440
}
441+
442+
export const useExportOrders = (
443+
query?: HttpTypes.AdminOrderFilters,
444+
options?: UseMutationOptions<
445+
{ transaction_id: string },
446+
FetchError,
447+
HttpTypes.AdminOrderFilters
448+
>
449+
) => {
450+
return useMutation({
451+
mutationFn: () => sdk.admin.order.export(query),
452+
onSuccess: (data, variables, context) => {
453+
options?.onSuccess?.(data, variables, context)
454+
},
455+
...options,
456+
})
457+
}

packages/admin/dashboard/src/i18n/translations/$schema.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4049,6 +4049,45 @@
40494049
"required": ["noRecordsMessage"],
40504050
"additionalProperties": false
40514051
},
4052+
"export": {
4053+
"type": "object",
4054+
"properties": {
4055+
"header": {
4056+
"type": "string"
4057+
},
4058+
"description": {
4059+
"type": "string"
4060+
},
4061+
"success": {
4062+
"type": "object",
4063+
"properties": {
4064+
"title": {
4065+
"type": "string"
4066+
},
4067+
"description": {
4068+
"type": "string"
4069+
}
4070+
},
4071+
"required": ["title", "description"],
4072+
"additionalProperties": false
4073+
},
4074+
"filters": {
4075+
"type": "object",
4076+
"properties": {
4077+
"title": {
4078+
"type": "string"
4079+
},
4080+
"description": {
4081+
"type": "string"
4082+
}
4083+
},
4084+
"required": ["title", "description"],
4085+
"additionalProperties": false
4086+
}
4087+
},
4088+
"required": ["header", "description", "success", "filters"],
4089+
"additionalProperties": false
4090+
},
40524091
"status": {
40534092
"type": "object",
40544093
"properties": {
@@ -5740,6 +5779,7 @@
57405779
"orderCanceled",
57415780
"onDateFromSalesChannel",
57425781
"list",
5782+
"export",
57435783
"status",
57445784
"summary",
57455785
"transfer",

packages/admin/dashboard/src/i18n/translations/en.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,18 @@
10801080
"list": {
10811081
"noRecordsMessage": "Your orders will show up here."
10821082
},
1083+
"export": {
1084+
"header": "Export Order List",
1085+
"description": "Export the order list to a CSV file.",
1086+
"success": {
1087+
"title": "Export started",
1088+
"description": "You will be notified when the export is ready."
1089+
},
1090+
"filters": {
1091+
"title": "Filters",
1092+
"description": "The following filters will be applied to the export."
1093+
}
1094+
},
10831095
"status": {
10841096
"not_paid": "Not paid",
10851097
"pending": "Pending",
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Heading, Text } from "@medusajs/ui"
2+
import { useTranslation } from "react-i18next"
3+
import { DataTableFilter } from "../../../../components/table/data-table/data-table-filter"
4+
import { useOrderTableFilters } from "../../order-list/components/order-list-table/use-order-table-filters"
5+
6+
export const ExportFilters = () => {
7+
const { t } = useTranslation()
8+
const filters = useOrderTableFilters()
9+
10+
return (
11+
<div>
12+
<Heading level="h2">{t("orders.export.filters.title")}</Heading>
13+
<Text size="small" className="text-ui-fg-subtle">
14+
{t("orders.export.filters.description")}
15+
</Text>
16+
17+
<div className="mt-4">
18+
<DataTableFilter filters={filters} readonly />
19+
</div>
20+
</div>
21+
)
22+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { OrderExport as Component } from "./order-export"
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { Button, Heading, toast } from "@medusajs/ui"
2+
import { useTranslation } from "react-i18next"
3+
import { RouteDrawer, useRouteModal } from "../../../components/modals"
4+
import { useExportOrders } from "../../../hooks/api"
5+
import { useOrderTableQuery } from "../../../hooks/table/query"
6+
import { ExportFilters } from "./components/export-filters"
7+
8+
export const OrderExport = () => {
9+
const { t } = useTranslation()
10+
11+
return (
12+
<RouteDrawer>
13+
<RouteDrawer.Header>
14+
<RouteDrawer.Title asChild>
15+
<Heading>{t("orders.export.header")}</Heading>
16+
</RouteDrawer.Title>
17+
<RouteDrawer.Description className="sr-only">
18+
{t("orders.export.description")}
19+
</RouteDrawer.Description>
20+
</RouteDrawer.Header>
21+
<OrderExportContent />
22+
</RouteDrawer>
23+
)
24+
}
25+
26+
const OrderExportContent = () => {
27+
const { t } = useTranslation()
28+
const { searchParams } = useOrderTableQuery({})
29+
30+
const { mutateAsync } = useExportOrders(searchParams)
31+
const { handleSuccess } = useRouteModal()
32+
33+
const handleExportRequest = async () => {
34+
await mutateAsync(searchParams, {
35+
onSuccess: () => {
36+
toast.info(t("orders.export.success.title"), {
37+
description: t("orders.export.success.description"),
38+
})
39+
handleSuccess()
40+
},
41+
onError: (err) => {
42+
toast.error(err.message)
43+
},
44+
})
45+
}
46+
47+
return (
48+
<>
49+
<RouteDrawer.Body>
50+
<ExportFilters />
51+
</RouteDrawer.Body>
52+
<RouteDrawer.Footer>
53+
<div className="flex items-center gap-x-2">
54+
<RouteDrawer.Close asChild>
55+
<Button size="small" variant="secondary">
56+
{t("actions.cancel")}
57+
</Button>
58+
</RouteDrawer.Close>
59+
<Button onClick={handleExportRequest} size="small">
60+
{t("actions.export")}
61+
</Button>
62+
</div>
63+
</RouteDrawer.Footer>
64+
</>
65+
)
66+
}
Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
import { useTranslation } from "react-i18next"
2+
import { Outlet, useLocation } from "react-router-dom"
3+
24
import { ConfigurableDataTable } from "../../../../../components/table/configurable-data-table"
35
import { useOrderTableAdapter } from "./order-table-adapter"
46

57
export const ConfigurableOrderListTable = () => {
68
const { t } = useTranslation()
7-
const orderAdapter = useOrderTableAdapter()
9+
const location = useLocation()
10+
const adapter = useOrderTableAdapter()
811

912
return (
10-
<ConfigurableDataTable
11-
adapter={orderAdapter}
12-
heading={t("orders.domain")}
13-
layout="fill"
14-
/>
13+
<>
14+
<ConfigurableDataTable
15+
adapter={adapter}
16+
heading={t("orders.domain")}
17+
actions={[
18+
{ label: t("actions.export"), to: `export${location.search}` },
19+
]}
20+
/>
21+
<Outlet />
22+
</>
1523
)
1624
}

packages/admin/dashboard/src/routes/orders/order-list/components/order-list-table/order-list-table.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
1-
import { Container, Heading } from "@medusajs/ui"
1+
import { Button, Container, Heading } from "@medusajs/ui"
22
import { keepPreviousData } from "@tanstack/react-query"
33
import { useTranslation } from "react-i18next"
4+
import { Link, Outlet, useLocation } from "react-router-dom"
45

56
import { _DataTable } from "../../../../../components/table/data-table/data-table"
67
import { useOrders } from "../../../../../hooks/api/orders"
78
import { useOrderTableColumns } from "../../../../../hooks/table/columns/use-order-table-columns"
8-
import { useOrderTableFilters } from "./use-order-table-filters"
99
import { useOrderTableQuery } from "../../../../../hooks/table/query/use-order-table-query"
1010
import { useDataTable } from "../../../../../hooks/use-data-table"
1111
import { useFeatureFlag } from "../../../../../providers/feature-flag-provider"
1212
import { ConfigurableOrderListTable } from "./configurable-order-list-table"
13+
import { useOrderTableFilters } from "./use-order-table-filters"
1314

1415
import { DEFAULT_FIELDS } from "../../const"
1516

1617
const PAGE_SIZE = 20
1718

1819
export const OrderListTable = () => {
1920
const { t } = useTranslation()
21+
const location = useLocation()
2022
const isViewConfigEnabled = useFeatureFlag("view_configurations")
2123

2224
// If feature flag is enabled, use the new configurable table
@@ -57,6 +59,9 @@ export const OrderListTable = () => {
5759
<Container className="divide-y p-0">
5860
<div className="flex items-center justify-between px-6 py-4">
5961
<Heading>{t("orders.domain")}</Heading>
62+
<Button size="small" variant="secondary" asChild>
63+
<Link to={`export${location.search}`}>{t("actions.export")}</Link>
64+
</Button>
6065
</div>
6166
<_DataTable
6267
columns={columns}
@@ -78,6 +83,7 @@ export const OrderListTable = () => {
7883
message: t("orders.list.noRecordsMessage"),
7984
}}
8085
/>
86+
<Outlet />
8187
</Container>
8288
)
8389
}

0 commit comments

Comments
 (0)