@vendure/dashboard 3.3.6-master-202507011151 → 3.3.6-master-202507020234

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/package.json +4 -4
  2. package/src/app/common/delete-bulk-action.tsx +147 -0
  3. package/src/app/common/duplicate-bulk-action.tsx +1 -1
  4. package/src/app/routes/_authenticated/_administrators/administrators.graphql.ts +9 -0
  5. package/src/app/routes/_authenticated/_administrators/administrators.tsx +7 -0
  6. package/src/app/routes/_authenticated/_administrators/components/administrator-bulk-actions.tsx +15 -0
  7. package/src/app/routes/_authenticated/_assets/assets.graphql.ts +11 -0
  8. package/src/app/routes/_authenticated/_assets/assets.tsx +10 -2
  9. package/src/app/routes/_authenticated/_assets/components/asset-bulk-actions.tsx +45 -0
  10. package/src/app/routes/_authenticated/_channels/channels.graphql.ts +9 -0
  11. package/src/app/routes/_authenticated/_channels/channels.tsx +7 -0
  12. package/src/app/routes/_authenticated/_channels/components/channel-bulk-actions.tsx +15 -0
  13. package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +39 -110
  14. package/src/app/routes/_authenticated/_countries/components/country-bulk-actions.tsx +15 -0
  15. package/src/app/routes/_authenticated/_countries/countries.graphql.ts +9 -0
  16. package/src/app/routes/_authenticated/_countries/countries.tsx +7 -0
  17. package/src/app/routes/_authenticated/_customer-groups/components/customer-group-bulk-actions.tsx +15 -0
  18. package/src/app/routes/_authenticated/_customer-groups/customer-groups.graphql.ts +9 -0
  19. package/src/app/routes/_authenticated/_customer-groups/customer-groups.tsx +7 -0
  20. package/src/app/routes/_authenticated/_customers/components/customer-bulk-actions.tsx +15 -0
  21. package/src/app/routes/_authenticated/_customers/customers.graphql.ts +9 -1
  22. package/src/app/routes/_authenticated/_customers/customers.tsx +7 -0
  23. package/src/app/routes/_authenticated/_facets/components/facet-bulk-actions.tsx +104 -0
  24. package/src/app/routes/_authenticated/_facets/facets.graphql.ts +30 -0
  25. package/src/app/routes/_authenticated/_facets/facets.tsx +24 -0
  26. package/src/app/routes/_authenticated/_payment-methods/components/payment-method-bulk-actions.tsx +58 -0
  27. package/src/app/routes/_authenticated/_payment-methods/payment-methods.graphql.ts +27 -0
  28. package/src/app/routes/_authenticated/_payment-methods/payment-methods.tsx +30 -8
  29. package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +4 -1
  30. package/src/app/routes/_authenticated/_product-variants/components/product-variant-bulk-actions.tsx +36 -110
  31. package/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx +36 -105
  32. package/src/app/routes/_authenticated/_promotions/components/promotion-bulk-actions.tsx +82 -0
  33. package/src/app/routes/_authenticated/_promotions/promotions.graphql.ts +25 -0
  34. package/src/app/routes/_authenticated/_promotions/promotions.tsx +24 -0
  35. package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +1 -1
  36. package/src/app/routes/_authenticated/_roles/components/role-bulk-actions.tsx +15 -0
  37. package/src/app/routes/_authenticated/_roles/roles.graphql.ts +9 -0
  38. package/src/app/routes/_authenticated/_roles/roles.tsx +7 -0
  39. package/src/app/routes/_authenticated/_sellers/components/seller-bulk-actions.tsx +15 -0
  40. package/src/app/routes/_authenticated/_sellers/sellers.graphql.ts +9 -0
  41. package/src/app/routes/_authenticated/_sellers/sellers.tsx +7 -0
  42. package/src/app/routes/_authenticated/_sellers/sellers_.$id.tsx +1 -1
  43. package/src/app/routes/_authenticated/_shipping-methods/components/shipping-method-bulk-actions.tsx +61 -0
  44. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.graphql.ts +27 -0
  45. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.tsx +19 -0
  46. package/src/app/routes/_authenticated/_stock-locations/components/stock-location-bulk-actions.tsx +58 -0
  47. package/src/app/routes/_authenticated/_stock-locations/stock-locations.graphql.ts +25 -0
  48. package/src/app/routes/_authenticated/_stock-locations/stock-locations.tsx +19 -0
  49. package/src/app/routes/_authenticated/_tax-categories/components/tax-category-bulk-actions.tsx +15 -0
  50. package/src/app/routes/_authenticated/_tax-categories/tax-categories.graphql.ts +9 -0
  51. package/src/app/routes/_authenticated/_tax-categories/tax-categories.tsx +7 -0
  52. package/src/app/routes/_authenticated/_tax-rates/components/tax-rate-bulk-actions.tsx +15 -0
  53. package/src/app/routes/_authenticated/_tax-rates/tax-rates.graphql.ts +9 -0
  54. package/src/app/routes/_authenticated/_tax-rates/tax-rates.tsx +7 -0
  55. package/src/app/routes/_authenticated/_zones/components/zone-bulk-actions.tsx +15 -0
  56. package/src/app/routes/_authenticated/_zones/zones.graphql.ts +9 -0
  57. package/src/app/routes/_authenticated/_zones/zones.tsx +7 -0
  58. package/src/lib/components/shared/asset/asset-bulk-actions.tsx +90 -0
  59. package/src/lib/components/shared/asset/asset-gallery.tsx +12 -7
  60. package/src/lib/components/shared/assign-to-channel-bulk-action.tsx +70 -0
  61. package/src/{app/routes/_authenticated/_products/components → lib/components/shared}/assign-to-channel-dialog.tsx +48 -30
  62. package/src/lib/components/shared/remove-from-channel-bulk-action.tsx +89 -0
  63. package/src/app/routes/_authenticated/_collections/components/assign-collections-to-channel-dialog.tsx +0 -110
@@ -1,14 +1,15 @@
1
- import { useMutation } from '@tanstack/react-query';
2
- import { LayersIcon, TagIcon, TrashIcon } from 'lucide-react';
1
+ import { TagIcon } from 'lucide-react';
3
2
  import { useState } from 'react';
4
- import { toast } from 'sonner';
5
3
 
6
4
  import { DataTableBulkActionItem } from '@/components/data-table/data-table-bulk-action-item.js';
5
+ import { AssignToChannelBulkAction } from '@/components/shared/assign-to-channel-bulk-action.js';
6
+ import { usePriceFactor } from '@/components/shared/assign-to-channel-dialog.js';
7
+ import { RemoveFromChannelBulkAction } from '@/components/shared/remove-from-channel-bulk-action.js';
7
8
  import { BulkActionComponent } from '@/framework/data-table/data-table-types.js';
8
9
  import { api } from '@/graphql/api.js';
9
- import { ResultOf } from '@/graphql/graphql.js';
10
10
  import { useChannel, usePaginatedList } from '@/index.js';
11
- import { Trans, useLingui } from '@/lib/trans.js';
11
+ import { Trans } from '@/lib/trans.js';
12
+ import { DeleteBulkAction } from '../../../../common/delete-bulk-action.js';
12
13
  import { DuplicateBulkAction } from '../../../../common/duplicate-bulk-action.js';
13
14
  import {
14
15
  assignProductsToChannelDocument,
@@ -19,123 +20,53 @@ import {
19
20
  updateProductsDocument,
20
21
  } from '../products.graphql.js';
21
22
  import { AssignFacetValuesDialog } from './assign-facet-values-dialog.js';
22
- import { AssignToChannelDialog } from './assign-to-channel-dialog.js';
23
23
 
24
24
  export const DeleteProductsBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
25
- const { refetchPaginatedList } = usePaginatedList();
26
- const { i18n } = useLingui();
27
- const { mutate } = useMutation({
28
- mutationFn: api.mutate(deleteProductsDocument),
29
- onSuccess: (result: ResultOf<typeof deleteProductsDocument>) => {
30
- let deleted = 0;
31
- const errors: string[] = [];
32
- for (const item of result.deleteProducts) {
33
- if (item.result === 'DELETED') {
34
- deleted++;
35
- } else if (item.message) {
36
- errors.push(item.message);
37
- }
38
- }
39
- if (0 < deleted) {
40
- toast.success(i18n.t(`Deleted ${deleted} products`));
41
- }
42
- if (0 < errors.length) {
43
- toast.error(i18n.t(`Failed to delete ${errors.length} products`));
44
- }
45
- refetchPaginatedList();
46
- table.resetRowSelection();
47
- },
48
- onError: () => {
49
- toast.error(`Failed to delete ${selection.length} products`);
50
- },
51
- });
52
25
  return (
53
- <DataTableBulkActionItem
54
- requiresPermission={['DeleteCatalog', 'DeleteProduct']}
55
- onClick={() => mutate({ ids: selection.map(s => s.id) })}
56
- label={<Trans>Delete</Trans>}
57
- confirmationText={<Trans>Are you sure you want to delete {selection.length} products?</Trans>}
58
- icon={TrashIcon}
59
- className="text-destructive"
26
+ <DeleteBulkAction
27
+ mutationDocument={deleteProductsDocument}
28
+ entityName="products"
29
+ requiredPermissions={['DeleteCatalog', 'DeleteProduct']}
30
+ selection={selection}
31
+ table={table}
60
32
  />
61
33
  );
62
34
  };
63
35
 
64
36
  export const AssignProductsToChannelBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
65
- const { refetchPaginatedList } = usePaginatedList();
66
- const { channels } = useChannel();
67
- const [dialogOpen, setDialogOpen] = useState(false);
68
-
69
- if (channels.length < 2) {
70
- return null;
71
- }
72
-
73
- const handleSuccess = () => {
74
- refetchPaginatedList();
75
- table.resetRowSelection();
76
- };
37
+ const { priceFactor, priceFactorField } = usePriceFactor();
77
38
 
78
39
  return (
79
- <>
80
- <DataTableBulkActionItem
81
- requiresPermission={['UpdateCatalog', 'UpdateProduct']}
82
- onClick={() => setDialogOpen(true)}
83
- label={<Trans>Assign to channel</Trans>}
84
- icon={LayersIcon}
85
- />
86
- <AssignToChannelDialog
87
- open={dialogOpen}
88
- onOpenChange={setDialogOpen}
89
- entityIds={selection.map(s => s.id)}
90
- entityType="products"
91
- mutationFn={api.mutate(assignProductsToChannelDocument)}
92
- onSuccess={handleSuccess}
93
- />
94
- </>
40
+ <AssignToChannelBulkAction
41
+ selection={selection}
42
+ table={table}
43
+ entityType="products"
44
+ mutationFn={api.mutate(assignProductsToChannelDocument)}
45
+ requiredPermissions={['UpdateCatalog', 'UpdateProduct']}
46
+ buildInput={(channelId: string) => ({
47
+ productIds: selection.map(s => s.id),
48
+ channelId,
49
+ priceFactor,
50
+ })}
51
+ additionalFields={priceFactorField}
52
+ />
95
53
  );
96
54
  };
97
55
 
98
56
  export const RemoveProductsFromChannelBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
99
- const { refetchPaginatedList } = usePaginatedList();
100
57
  const { selectedChannel } = useChannel();
101
- const { i18n } = useLingui();
102
- const { mutate } = useMutation({
103
- mutationFn: api.mutate(removeProductsFromChannelDocument),
104
- onSuccess: () => {
105
- toast.success(i18n.t(`Successfully removed ${selection.length} products from channel`));
106
- refetchPaginatedList();
107
- table.resetRowSelection();
108
- },
109
- onError: error => {
110
- toast.error(`Failed to remove ${selection.length} products from channel: ${error.message}`);
111
- },
112
- });
113
-
114
- if (!selectedChannel) {
115
- return null;
116
- }
117
-
118
- const handleRemove = () => {
119
- mutate({
120
- input: {
121
- productIds: selection.map(s => s.id),
122
- channelId: selectedChannel.id,
123
- },
124
- });
125
- };
126
58
 
127
59
  return (
128
- <DataTableBulkActionItem
129
- requiresPermission={['UpdateCatalog', 'UpdateProduct']}
130
- onClick={handleRemove}
131
- label={<Trans>Remove from current channel</Trans>}
132
- confirmationText={
133
- <Trans>
134
- Are you sure you want to remove {selection.length} products from the current channel?
135
- </Trans>
136
- }
137
- icon={LayersIcon}
138
- className="text-warning"
60
+ <RemoveFromChannelBulkAction
61
+ selection={selection}
62
+ table={table}
63
+ entityType="products"
64
+ mutationFn={api.mutate(removeProductsFromChannelDocument)}
65
+ requiredPermissions={['UpdateCatalog', 'UpdateProduct']}
66
+ buildInput={() => ({
67
+ productIds: selection.map(s => s.id),
68
+ channelId: selectedChannel?.id,
69
+ })}
139
70
  />
140
71
  );
141
72
  };
@@ -0,0 +1,82 @@
1
+ import { AssignToChannelBulkAction } from '@/components/shared/assign-to-channel-bulk-action.js';
2
+ import { RemoveFromChannelBulkAction } from '@/components/shared/remove-from-channel-bulk-action.js';
3
+ import { BulkActionComponent } from '@/framework/data-table/data-table-types.js';
4
+ import { api } from '@/graphql/api.js';
5
+ import { useChannel } from '@/index.js';
6
+ import { DeleteBulkAction } from '../../../../common/delete-bulk-action.js';
7
+ import { DuplicateBulkAction } from '../../../../common/duplicate-bulk-action.js';
8
+
9
+ import {
10
+ assignPromotionsToChannelDocument,
11
+ deletePromotionsDocument,
12
+ removePromotionsFromChannelDocument,
13
+ } from '../promotions.graphql.js';
14
+
15
+ export const DeletePromotionsBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
16
+ return (
17
+ <DeleteBulkAction
18
+ mutationDocument={deletePromotionsDocument}
19
+ entityName="promotions"
20
+ requiredPermissions={['DeletePromotion']}
21
+ selection={selection}
22
+ table={table}
23
+ />
24
+ );
25
+ };
26
+
27
+ export const AssignPromotionsToChannelBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
28
+ return (
29
+ <AssignToChannelBulkAction
30
+ selection={selection}
31
+ table={table}
32
+ entityType="promotions"
33
+ mutationFn={api.mutate(assignPromotionsToChannelDocument)}
34
+ requiredPermissions={['UpdatePromotion']}
35
+ buildInput={(channelId: string) => ({
36
+ promotionIds: selection.map(s => s.id),
37
+ channelId,
38
+ })}
39
+ />
40
+ );
41
+ };
42
+
43
+ export const RemovePromotionsFromChannelBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
44
+ const { selectedChannel } = useChannel();
45
+
46
+ return (
47
+ <RemoveFromChannelBulkAction
48
+ selection={selection}
49
+ table={table}
50
+ entityType="promotions"
51
+ mutationFn={api.mutate(removePromotionsFromChannelDocument)}
52
+ requiredPermissions={['UpdatePromotion']}
53
+ buildInput={() => ({
54
+ promotionIds: selection.map(s => s.id),
55
+ channelId: selectedChannel?.id,
56
+ })}
57
+ />
58
+ );
59
+ };
60
+
61
+ export const DuplicatePromotionsBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
62
+ return (
63
+ <DuplicateBulkAction
64
+ entityType="Promotion"
65
+ duplicatorCode="promotion-duplicator"
66
+ duplicatorArguments={[
67
+ {
68
+ name: 'includeConditions',
69
+ value: 'true',
70
+ },
71
+ {
72
+ name: 'includeActions',
73
+ value: 'true',
74
+ },
75
+ ]}
76
+ requiredPermissions={['CreatePromotion']}
77
+ entityName="Promotion"
78
+ selection={selection}
79
+ table={table}
80
+ />
81
+ );
82
+ };
@@ -94,3 +94,28 @@ export const deletePromotionDocument = graphql(`
94
94
  }
95
95
  }
96
96
  `);
97
+
98
+ export const assignPromotionsToChannelDocument = graphql(`
99
+ mutation AssignPromotionsToChannel($input: AssignPromotionsToChannelInput!) {
100
+ assignPromotionsToChannel(input: $input) {
101
+ id
102
+ }
103
+ }
104
+ `);
105
+
106
+ export const removePromotionsFromChannelDocument = graphql(`
107
+ mutation RemovePromotionsFromChannel($input: RemovePromotionsFromChannelInput!) {
108
+ removePromotionsFromChannel(input: $input) {
109
+ id
110
+ }
111
+ }
112
+ `);
113
+
114
+ export const deletePromotionsDocument = graphql(`
115
+ mutation DeletePromotions($ids: [ID!]!) {
116
+ deletePromotions(ids: $ids) {
117
+ result
118
+ message
119
+ }
120
+ }
121
+ `);
@@ -7,6 +7,12 @@ import { ListPage } from '@/framework/page/list-page.js';
7
7
  import { Trans } from '@/lib/trans.js';
8
8
  import { createFileRoute, Link } from '@tanstack/react-router';
9
9
  import { PlusIcon } from 'lucide-react';
10
+ import {
11
+ AssignPromotionsToChannelBulkAction,
12
+ DeletePromotionsBulkAction,
13
+ DuplicatePromotionsBulkAction,
14
+ RemovePromotionsFromChannelBulkAction,
15
+ } from './components/promotion-bulk-actions.js';
10
16
  import { deletePromotionDocument, promotionListDocument } from './promotions.graphql.js';
11
17
 
12
18
  export const Route = createFileRoute('/_authenticated/_promotions/promotions')({
@@ -45,6 +51,24 @@ function PromotionListPage() {
45
51
  cell: ({ row }) => <BooleanDisplayBadge value={row.original.enabled} />,
46
52
  },
47
53
  }}
54
+ bulkActions={[
55
+ {
56
+ order: 100,
57
+ component: AssignPromotionsToChannelBulkAction,
58
+ },
59
+ {
60
+ order: 200,
61
+ component: RemovePromotionsFromChannelBulkAction,
62
+ },
63
+ {
64
+ order: 300,
65
+ component: DuplicatePromotionsBulkAction,
66
+ },
67
+ {
68
+ order: 400,
69
+ component: DeletePromotionsBulkAction,
70
+ },
71
+ ]}
48
72
  >
49
73
  <PageActionBarRight>
50
74
  <PermissionGuard requires={['CreatePromotion']}>
@@ -102,7 +102,7 @@ function PromotionDetailPage() {
102
102
  toast.success(i18n.t('Successfully updated promotion'));
103
103
  resetForm();
104
104
  if (creatingNewEntity) {
105
- await navigate({ to: `../${data.id}`, from: Route.id });
105
+ await navigate({ to: `../$id`, params: { id: data.id } });
106
106
  }
107
107
  } else {
108
108
  toast.error(i18n.t('Failed to update promotion'), {
@@ -0,0 +1,15 @@
1
+ import { BulkActionComponent } from '@/framework/data-table/data-table-types.js';
2
+ import { DeleteBulkAction } from '../../../../common/delete-bulk-action.js';
3
+ import { deleteRolesDocument } from '../roles.graphql.js';
4
+
5
+ export const DeleteRolesBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
6
+ return (
7
+ <DeleteBulkAction
8
+ mutationDocument={deleteRolesDocument}
9
+ entityName="roles"
10
+ requiredPermissions={['DeleteAdministrator']}
11
+ selection={selection}
12
+ table={table}
13
+ />
14
+ );
15
+ };
@@ -65,3 +65,12 @@ export const deleteRoleDocument = graphql(`
65
65
  }
66
66
  }
67
67
  `);
68
+
69
+ export const deleteRolesDocument = graphql(`
70
+ mutation DeleteRoles($ids: [ID!]!) {
71
+ deleteRoles(ids: $ids) {
72
+ result
73
+ message
74
+ }
75
+ }
76
+ `);
@@ -11,6 +11,7 @@ import { Trans } from '@/lib/trans.js';
11
11
  import { createFileRoute, Link } from '@tanstack/react-router';
12
12
  import { LayersIcon, PlusIcon } from 'lucide-react';
13
13
  import { ExpandablePermissions } from './components/expandable-permissions.js';
14
+ import { DeleteRolesBulkAction } from './components/role-bulk-actions.js';
14
15
  import { deleteRoleDocument, roleListQuery } from './roles.graphql.js';
15
16
 
16
17
  export const Route = createFileRoute('/_authenticated/_roles/roles')({
@@ -80,6 +81,12 @@ function RoleListPage() {
80
81
  },
81
82
  },
82
83
  }}
84
+ bulkActions={[
85
+ {
86
+ component: DeleteRolesBulkAction,
87
+ order: 500,
88
+ },
89
+ ]}
83
90
  >
84
91
  <PageActionBarRight>
85
92
  <PermissionGuard requires={['CreateAdministrator']}>
@@ -0,0 +1,15 @@
1
+ import { BulkActionComponent } from '@/framework/data-table/data-table-types.js';
2
+ import { DeleteBulkAction } from '../../../../common/delete-bulk-action.js';
3
+ import { deleteSellersDocument } from '../sellers.graphql.js';
4
+
5
+ export const DeleteSellersBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
6
+ return (
7
+ <DeleteBulkAction
8
+ mutationDocument={deleteSellersDocument}
9
+ entityName="sellers"
10
+ requiredPermissions={['DeleteSeller']}
11
+ selection={selection}
12
+ table={table}
13
+ />
14
+ );
15
+ };
@@ -59,3 +59,12 @@ export const deleteSellerDocument = graphql(`
59
59
  }
60
60
  }
61
61
  `);
62
+
63
+ export const deleteSellersDocument = graphql(`
64
+ mutation DeleteSellers($ids: [ID!]!) {
65
+ deleteSellers(ids: $ids) {
66
+ result
67
+ message
68
+ }
69
+ }
70
+ `);
@@ -7,6 +7,7 @@ import { Trans } from '@/lib/trans.js';
7
7
  import { createFileRoute, Link } from '@tanstack/react-router';
8
8
  import { PlusIcon } from 'lucide-react';
9
9
  import { deleteSellerDocument, sellerListQuery } from './sellers.graphql.js';
10
+ import { DeleteSellersBulkAction } from './components/seller-bulk-actions.js';
10
11
 
11
12
  export const Route = createFileRoute('/_authenticated/_sellers/sellers')({
12
13
  component: SellerListPage,
@@ -35,6 +36,12 @@ function SellerListPage() {
35
36
  cell: ({ row }) => <DetailPageButton id={row.original.id} label={row.original.name} />,
36
37
  },
37
38
  }}
39
+ bulkActions={[
40
+ {
41
+ component: DeleteSellersBulkAction,
42
+ order: 500,
43
+ },
44
+ ]}
38
45
  >
39
46
  <PageActionBarRight>
40
47
  <PermissionGuard requires={['CreateSeller']}>
@@ -58,7 +58,7 @@ function SellerDetailPage() {
58
58
  toast(i18n.t('Successfully updated seller'));
59
59
  form.reset(form.getValues());
60
60
  if (creatingNewEntity) {
61
- await navigate({ to: `../${data?.id}`, from: Route.id });
61
+ await navigate({ to: `../$id`, params: { id: data.id } });
62
62
  }
63
63
  },
64
64
  onError: err => {
@@ -0,0 +1,61 @@
1
+ import { AssignToChannelBulkAction } from '@/components/shared/assign-to-channel-bulk-action.js';
2
+ import { RemoveFromChannelBulkAction } from '@/components/shared/remove-from-channel-bulk-action.js';
3
+ import { BulkActionComponent } from '@/framework/data-table/data-table-types.js';
4
+ import { api } from '@/graphql/api.js';
5
+ import { useChannel } from '@/index.js';
6
+ import { DeleteBulkAction } from '../../../../common/delete-bulk-action.js';
7
+
8
+ import {
9
+ assignShippingMethodsToChannelDocument,
10
+ deleteShippingMethodsDocument,
11
+ removeShippingMethodsFromChannelDocument,
12
+ } from '../shipping-methods.graphql.js';
13
+
14
+ export const DeleteShippingMethodsBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
15
+ return (
16
+ <DeleteBulkAction
17
+ mutationDocument={deleteShippingMethodsDocument}
18
+ entityName="shipping methods"
19
+ requiredPermissions={['DeleteShippingMethod']}
20
+ selection={selection}
21
+ table={table}
22
+ />
23
+ );
24
+ };
25
+
26
+ export const AssignShippingMethodsToChannelBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
27
+ return (
28
+ <AssignToChannelBulkAction
29
+ selection={selection}
30
+ table={table}
31
+ entityType="shipping methods"
32
+ mutationFn={api.mutate(assignShippingMethodsToChannelDocument)}
33
+ requiredPermissions={['UpdateShippingMethod']}
34
+ buildInput={(channelId: string) => ({
35
+ shippingMethodIds: selection.map(s => s.id),
36
+ channelId,
37
+ })}
38
+ />
39
+ );
40
+ };
41
+
42
+ export const RemoveShippingMethodsFromChannelBulkAction: BulkActionComponent<any> = ({
43
+ selection,
44
+ table,
45
+ }) => {
46
+ const { selectedChannel } = useChannel();
47
+
48
+ return (
49
+ <RemoveFromChannelBulkAction
50
+ selection={selection}
51
+ table={table}
52
+ entityType="shipping methods"
53
+ mutationFn={api.mutate(removeShippingMethodsFromChannelDocument)}
54
+ requiredPermissions={['UpdateShippingMethod']}
55
+ buildInput={() => ({
56
+ shippingMethodIds: selection.map(s => s.id),
57
+ channelId: selectedChannel?.id,
58
+ })}
59
+ />
60
+ );
61
+ };
@@ -81,3 +81,30 @@ export const deleteShippingMethodDocument = graphql(`
81
81
  }
82
82
  }
83
83
  `);
84
+
85
+ export const deleteShippingMethodsDocument = graphql(`
86
+ mutation DeleteShippingMethods($ids: [ID!]!) {
87
+ deleteShippingMethods(ids: $ids) {
88
+ result
89
+ message
90
+ }
91
+ }
92
+ `);
93
+
94
+ export const assignShippingMethodsToChannelDocument = graphql(`
95
+ mutation AssignShippingMethodsToChannel($input: AssignShippingMethodsToChannelInput!) {
96
+ assignShippingMethodsToChannel(input: $input) {
97
+ id
98
+ name
99
+ }
100
+ }
101
+ `);
102
+
103
+ export const removeShippingMethodsFromChannelDocument = graphql(`
104
+ mutation RemoveShippingMethodsFromChannel($input: RemoveShippingMethodsFromChannelInput!) {
105
+ removeShippingMethodsFromChannel(input: $input) {
106
+ id
107
+ name
108
+ }
109
+ }
110
+ `);
@@ -6,6 +6,11 @@ import { ListPage } from '@/framework/page/list-page.js';
6
6
  import { Trans } from '@/lib/trans.js';
7
7
  import { createFileRoute, Link } from '@tanstack/react-router';
8
8
  import { PlusIcon } from 'lucide-react';
9
+ import {
10
+ AssignShippingMethodsToChannelBulkAction,
11
+ DeleteShippingMethodsBulkAction,
12
+ RemoveShippingMethodsFromChannelBulkAction,
13
+ } from './components/shipping-method-bulk-actions.js';
9
14
  import { TestShippingMethodDialog } from './components/test-shipping-method-dialog.js';
10
15
  import { deleteShippingMethodDocument, shippingMethodListQuery } from './shipping-methods.graphql.js';
11
16
 
@@ -38,6 +43,20 @@ function ShippingMethodListPage() {
38
43
  name: { contains: searchTerm },
39
44
  };
40
45
  }}
46
+ bulkActions={[
47
+ {
48
+ component: AssignShippingMethodsToChannelBulkAction,
49
+ order: 100,
50
+ },
51
+ {
52
+ component: RemoveShippingMethodsFromChannelBulkAction,
53
+ order: 200,
54
+ },
55
+ {
56
+ component: DeleteShippingMethodsBulkAction,
57
+ order: 500,
58
+ },
59
+ ]}
41
60
  >
42
61
  <PageActionBarRight>
43
62
  <PermissionGuard requires={['CreateShippingMethod']}>
@@ -0,0 +1,58 @@
1
+ import { AssignToChannelBulkAction } from '@/components/shared/assign-to-channel-bulk-action.js';
2
+ import { RemoveFromChannelBulkAction } from '@/components/shared/remove-from-channel-bulk-action.js';
3
+ import { BulkActionComponent } from '@/framework/data-table/data-table-types.js';
4
+ import { api } from '@/graphql/api.js';
5
+ import { useChannel } from '@/index.js';
6
+ import { DeleteBulkAction } from '../../../../common/delete-bulk-action.js';
7
+
8
+ import {
9
+ assignStockLocationsToChannelDocument,
10
+ deleteStockLocationsDocument,
11
+ removeStockLocationsFromChannelDocument,
12
+ } from '../stock-locations.graphql.js';
13
+
14
+ export const DeleteStockLocationsBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
15
+ return (
16
+ <DeleteBulkAction
17
+ mutationDocument={deleteStockLocationsDocument}
18
+ entityName="stock locations"
19
+ requiredPermissions={['DeleteStockLocation']}
20
+ selection={selection}
21
+ table={table}
22
+ />
23
+ );
24
+ };
25
+
26
+ export const AssignStockLocationsToChannelBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
27
+ return (
28
+ <AssignToChannelBulkAction
29
+ selection={selection}
30
+ table={table}
31
+ entityType="stock locations"
32
+ mutationFn={api.mutate(assignStockLocationsToChannelDocument)}
33
+ requiredPermissions={['UpdateStockLocation']}
34
+ buildInput={(channelId: string) => ({
35
+ stockLocationIds: selection.map(s => s.id),
36
+ channelId,
37
+ })}
38
+ />
39
+ );
40
+ };
41
+
42
+ export const RemoveStockLocationsFromChannelBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
43
+ const { selectedChannel } = useChannel();
44
+
45
+ return (
46
+ <RemoveFromChannelBulkAction
47
+ selection={selection}
48
+ table={table}
49
+ entityType="stock locations"
50
+ mutationFn={api.mutate(removeStockLocationsFromChannelDocument)}
51
+ requiredPermissions={['UpdateStockLocation']}
52
+ buildInput={() => ({
53
+ stockLocationIds: selection.map(s => s.id),
54
+ channelId: selectedChannel?.id,
55
+ })}
56
+ />
57
+ );
58
+ };
@@ -60,3 +60,28 @@ export const deleteStockLocationDocument = graphql(`
60
60
  }
61
61
  }
62
62
  `);
63
+
64
+ export const deleteStockLocationsDocument = graphql(`
65
+ mutation DeleteStockLocations($input: [DeleteStockLocationInput!]!) {
66
+ deleteStockLocations(input: $input) {
67
+ result
68
+ message
69
+ }
70
+ }
71
+ `);
72
+
73
+ export const assignStockLocationsToChannelDocument = graphql(`
74
+ mutation AssignStockLocationsToChannel($input: AssignStockLocationsToChannelInput!) {
75
+ assignStockLocationsToChannel(input: $input) {
76
+ id
77
+ }
78
+ }
79
+ `);
80
+
81
+ export const removeStockLocationsFromChannelDocument = graphql(`
82
+ mutation RemoveStockLocationsFromChannel($input: RemoveStockLocationsFromChannelInput!) {
83
+ removeStockLocationsFromChannel(input: $input) {
84
+ id
85
+ }
86
+ }
87
+ `);