umwd-components 0.1.779 → 0.1.781

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 (40) hide show
  1. package/dist/cjs/src/components/common/media/minio/MinioDeleteFormButton.js +7 -0
  2. package/dist/cjs/src/components/common/media/minio/MinioDownloadButton.js +7 -0
  3. package/dist/cjs/src/components/common/media/minio/UploadMinioMediaForm.js +1 -1
  4. package/dist/cjs/src/components/e-commerce/opo/TextualManageOpoForm.js +1 -1
  5. package/dist/cjs/src/components/logistics/ipo/TextualManageIPOForm.js +1 -1
  6. package/dist/cjs/src/data/actions/media/minio/deleteMinioMediaAction.js +6 -0
  7. package/dist/cjs/src/data/actions/media/minio/uploadMinioMediaAction.js +1 -1
  8. package/dist/cjs/src/data/loaders/common/media/minio/downloadMinioItemClient.js +7 -0
  9. package/dist/cjs/src/data/loaders/common/media/minio/getMinioSignedUrl.js +7 -0
  10. package/dist/cjs/src/data/services/common/media/minio/minio-service.js +1 -1
  11. package/dist/cjs/src/data/services/common/media/minio/minioDeleteService.js +7 -0
  12. package/dist/cjs/src/data/services/common/media/minio/minioUploadService.js +7 -0
  13. package/dist/cjs/tsconfig.build.tsbuildinfo +1 -1
  14. package/dist/esm/src/components/common/media/minio/MinioDeleteFormButton.js +41 -0
  15. package/dist/esm/src/components/common/media/minio/MinioDownloadButton.js +23 -0
  16. package/dist/esm/src/components/common/media/minio/UploadMinioMediaForm.js +22 -5
  17. package/dist/esm/src/components/e-commerce/opo/TextualManageOpoForm.js +2 -1
  18. package/dist/esm/src/components/logistics/ipo/TextualManageIPOForm.js +6 -7
  19. package/dist/esm/src/data/actions/media/minio/deleteMinioMediaAction.js +59 -0
  20. package/dist/esm/src/data/actions/media/minio/uploadMinioMediaAction.js +8 -6
  21. package/dist/esm/src/data/loaders/common/media/minio/downloadMinioItemClient.js +39 -0
  22. package/dist/esm/src/data/loaders/common/media/minio/getMinioSignedUrl.js +52 -0
  23. package/dist/esm/src/data/services/common/media/minio/minio-service.js +10 -5
  24. package/dist/esm/src/data/services/common/media/minio/minioDeleteService.js +34 -0
  25. package/dist/esm/src/data/services/common/media/minio/minioUploadService.js +38 -0
  26. package/dist/esm/tsconfig.build.tsbuildinfo +1 -1
  27. package/dist/esm/types/components/common/media/minio/MinioDeleteButton.d.ts +7 -0
  28. package/dist/esm/types/components/common/media/minio/MinioDeleteFormButton.d.ts +7 -0
  29. package/dist/esm/types/components/common/media/minio/MinioDownloadButton.d.ts +6 -0
  30. package/dist/esm/types/components/common/media/minio/UploadMinioMediaForm.d.ts +2 -1
  31. package/dist/esm/types/data/actions/media/minio/deleteMinioMediaAction.d.ts +1 -0
  32. package/dist/esm/types/data/loaders/common/media/minio/downloadMinioItemClient.d.ts +13 -0
  33. package/dist/esm/types/data/loaders/common/media/minio/getAllMinioMedia.d.ts +1 -0
  34. package/dist/esm/types/data/loaders/common/media/minio/getMinioSignedUrl.d.ts +6 -0
  35. package/dist/esm/types/data/services/common/media/minio/minioDeleteService.d.ts +1 -0
  36. package/dist/esm/types/data/services/common/media/minio/minioUploadService.d.ts +1 -0
  37. package/dist/esm/types/types/common/media/types.d.ts +3 -3
  38. package/dist/esm/types/types/data/actions/types.d.ts +7 -0
  39. package/dist/esm/types/types/logistics/Ipo.d.ts +10 -0
  40. package/package.json +1 -1
@@ -0,0 +1,41 @@
1
+ "use client";
2
+ /*
3
+ * UMWD-Components
4
+ * @copyright Jelle Paulus
5
+ * @license MIT
6
+ */
7
+
8
+ import { jsx } from 'react/jsx-runtime';
9
+ import { IconButton } from '@mui/material';
10
+ import { useActionState, useEffect } from 'react';
11
+ import DeleteIcon from '@mui/icons-material/Delete';
12
+ import { deleteMinioMediaAction } from '../../../../data/actions/media/minio/deleteMinioMediaAction.js';
13
+ import { useSnackbar } from '../../../../context/common/SnackbarContext.js';
14
+
15
+ const INITIAL_STATE = {
16
+ zodErrors: null,
17
+ strapiErrors: null,
18
+ data: null,
19
+ message: null,
20
+ };
21
+ const MinioDeleteFormButton = ({ bucketName, fileName, revalidateCallback, }) => {
22
+ const boundAction = deleteMinioMediaAction.bind(null, bucketName, fileName);
23
+ const [formState, formAction] = useActionState(boundAction, INITIAL_STATE);
24
+ const { handleAddMessage } = useSnackbar();
25
+ useEffect(() => {
26
+ if (formState.message) {
27
+ handleAddMessage({
28
+ message: formState.message,
29
+ severity: formState.severity || "info",
30
+ });
31
+ }
32
+ }, [formState.message]);
33
+ useEffect(() => {
34
+ if (formState.message && formState.message.type === "success") {
35
+ revalidateCallback?.();
36
+ }
37
+ }, [formState.message]);
38
+ return (jsx("form", { action: formAction, children: jsx(IconButton, { type: "submit", color: "error", size: "small", children: jsx(DeleteIcon, {}) }) }));
39
+ };
40
+
41
+ export { MinioDeleteFormButton };
@@ -0,0 +1,23 @@
1
+ "use client";
2
+ /*
3
+ * UMWD-Components
4
+ * @copyright Jelle Paulus
5
+ * @license MIT
6
+ */
7
+
8
+ import { jsx } from 'react/jsx-runtime';
9
+ import { Button, Typography } from '@mui/material';
10
+ import { getMinioSignedUrl } from '../../../../data/loaders/common/media/minio/getMinioSignedUrl.js';
11
+ import { downloadMinioItemClient } from '../../../../data/loaders/common/media/minio/downloadMinioItemClient.js';
12
+
13
+ const MinioDownloadButton = ({ bucketName, fileName, }) => {
14
+ const handleDownload = async () => {
15
+ const { signedUrl } = await getMinioSignedUrl(bucketName, fileName);
16
+ if (signedUrl) {
17
+ downloadMinioItemClient(signedUrl, fileName);
18
+ }
19
+ };
20
+ return (jsx(Button, { variant: "text", onClick: handleDownload, children: jsx(Typography, { variant: "body1", children: fileName }) }));
21
+ };
22
+
23
+ export { MinioDownloadButton };
@@ -5,7 +5,7 @@
5
5
  * @license MIT
6
6
  */
7
7
 
8
- import { jsx, jsxs } from 'react/jsx-runtime';
8
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
9
9
  import { useState, useActionState, useRef, useEffect } from 'react';
10
10
  import { uploadMinioMediaAction } from '../../../../data/actions/media/minio/uploadMinioMediaAction.js';
11
11
  import { StrapiErrors } from '../../../StrapiErrors.js';
@@ -31,17 +31,30 @@ function UploadMinioMediaForm({
31
31
  * refID,
32
32
  * field,
33
33
  */
34
- bucketName = "umwd", fileName = Date.now().toString(), multiple = false, accept = "image/*", revalidateCallback, }) {
34
+ bucketName = "umwd", fileName = Date.now().toString(), multiple = false, accept = "image/*", // should be dependent on config files
35
+ reference, refID, field, revalidateCallback, }) {
35
36
  const [filePreviews, setFilePreviews] = useState(null);
36
37
  const [fileList, setFileList] = useState(null);
38
+ const [selectedFileName, setSelectedFileName] = useState(null);
39
+ /* const formAction = uploadMinioMediaAction;
40
+
41
+ if (reference && refID && field) {
42
+ // Attach the media information to the entity
43
+ const boundAction = uploadMinioMediaAction.bind(null, {
44
+ reference,
45
+ refID,
46
+ field,
47
+ });
48
+ formAction = boundAction;
49
+ } */
37
50
  const [formState, formAction] = useActionState(uploadMinioMediaAction, INITIAL_STATE);
38
51
  const fileInput = useRef(null);
39
52
  useEffect(() => {
40
- if (formState.data) {
53
+ if (formState.message && formState.message.type === "success") {
41
54
  revalidateCallback?.();
42
55
  }
43
- }, [formState.data]);
44
- return (jsx("form", { action: formAction, children: jsxs(Stack, { spacing: 1, sx: { flex: 1 }, children: [bucketName && (jsx("input", { type: "text", name: "bucketName", value: bucketName, style: { display: "none" }, readOnly: true })), fileName && (jsx("input", { type: "text", name: "fileName", value: fileName, style: { display: "none" }, readOnly: true })), filePreviews !== null ? (jsx(Box, { onClick: () => fileInput.current?.click(), sx: {
56
+ }, [formState.message]);
57
+ return (jsx("form", { action: formAction, children: jsxs(Stack, { spacing: 1, sx: { flex: 1 }, children: [reference && refID && field && (jsxs(Fragment, { children: [jsx("input", { type: "text", name: "ref", value: reference, style: { display: "none" }, readOnly: true }), jsx("input", { type: "text", name: "refId", value: refID, style: { display: "none" }, readOnly: true }), jsx("input", { type: "text", name: "field", value: field, style: { display: "none" }, readOnly: true })] })), bucketName && (jsx("input", { type: "text", name: "bucketName", value: bucketName, style: { display: "none" }, readOnly: true })), selectedFileName && (jsx("input", { type: "text", name: "fileName", value: selectedFileName, style: { display: "none" }, readOnly: true })), filePreviews !== null ? (jsx(Box, { onClick: () => fileInput.current?.click(), sx: {
45
58
  p: 2,
46
59
  width: "100%",
47
60
  border: "1px dashed white",
@@ -71,6 +84,10 @@ bucketName = "umwd", fileName = Date.now().toString(), multiple = false, accept
71
84
  if (selectedFiles === null) {
72
85
  return;
73
86
  }
87
+ // Use the first file's name for single file uploads
88
+ if (selectedFiles.length > 0) {
89
+ setSelectedFileName(selectedFiles[0].name);
90
+ }
74
91
  const filePreviews = Object.keys(selectedFiles).map((item, index) => {
75
92
  return {
76
93
  url: URL.createObjectURL(selectedFiles[index]),
@@ -36,6 +36,7 @@ import UpdateIcon from '@mui/icons-material/Update';
36
36
  import { OpoStatusIndicator } from './OpoStatusIndicator.js';
37
37
  import { useSnackbar } from '../../../context/common/SnackbarContext.js';
38
38
  import { SubmitButton } from '../../SubmitButton.js';
39
+ import { UploadMinioMediaForm } from '../../common/media/minio/UploadMinioMediaForm.js';
39
40
 
40
41
  const INITIAL_STATE = {
41
42
  zodErrors: null,
@@ -172,7 +173,7 @@ function TextualManageOPOForm({ opo, sx, revalidateCallback, handleClose, role,
172
173
  opo.internal_status === "external_shipping_process") && (jsxs(Fragment, { children: [jsx(Button, { variant: "contained", color: "primary", onClick: () => setConfirmDialogOpen(true), children: "Confirm order" }), jsx(Alert, { severity: "warning", children: "Please confirm the order as soon as possible, only upon confirmation this order will be available to the dispatcher" }), jsx(ConfirmFormDialog, { open: confirmDialogOpen, handleClose: () => setConfirmDialogOpen(false), orderID: opo.documentId, currentStatus: opo.internal_status, revalidateCallback: revalidateCallback })] })), (opo.internal_status === "placed" ||
173
174
  opo.internal_status === "ordered") && (jsxs(Fragment, { children: [jsx(Button, { variant: "contained", color: "error", onClick: () => setCancelDialogOpen(true), children: "Cancel order" }), jsx(CancelOpoDialog, { open: cancelDialogOpen, handleClose: () => setCancelDialogOpen(false), orderID: opo.documentId, revalidateCallback: revalidateCallback })] }))] }) }) })), jsx(Grid, { size: 12, children: jsxs(Stack, { spacing: 2, children: [jsx(Typography, { variant: "h5", children: "Documents" }), jsx(Paper, { sx: { p: 2 }, children: jsx(Stack, { spacing: 1, children: opo.delivery_note ? (jsxs(Fragment, { children: [jsx(Typography, { variant: "h6", children: "Delivery Note" }), jsx(Typography, { children: opo.delivery_note?.name }), jsx(Button, { variant: "contained", onClick: () => {
174
175
  downloadBase64File(`api/opos/${opo.documentId}`, "delivery_note");
175
- }, children: "Download" })] })) : (jsxs(Fragment, { children: [jsx(Typography, { variant: "h5", children: "Delivery Note" }), jsx(Typography, { variant: "body1", children: "Here you can upload the the delivery note for this order" }), jsx(Divider, {}), jsx(UploadBase64MediaForm, { reference: "api::e-commerce.opo", refID: opo.documentId, field: "delivery_note", multiple: false, accept: "text/*,application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document", path: "api/ipos", componentName: "delivery_note", componentReference: "common.base64-encoded-media", revalidateCallback: revalidateCallback })] })) }) })] }) }), opo?.notes?.length > 0 && (jsx(Grid, { size: 12, children: jsxs(Stack, { spacing: 2, children: [jsx(Typography, { variant: "h5", children: "Notes" }), jsx(NotesDisplay, { notes: opo.notes }), jsx(Divider, {})] }) })), jsx(Grid, { size: 12, children: jsxs(Stack, { spacing: 1, children: [jsx(Typography, { variant: "h5", children: "Items" }), jsxs(Stack, { direction: "row", alignItems: "center", justifyContent: "flex-end", spacing: 2, component: Paper, p: 1, children: [jsx(Typography, { variant: "body1", children: "Show:" }), options.map((option) => (jsx(FormControlLabel, { control: jsx(Checkbox, { checked: showing.includes(option), onChange: (e) => {
176
+ }, children: "Download" })] })) : (jsxs(Fragment, { children: [jsx(Typography, { variant: "h5", children: "Delivery Note" }), jsx(Typography, { variant: "body1", children: "Here you can upload the the delivery note for this order" }), jsx(Divider, {}), jsx(UploadBase64MediaForm, { reference: "api::e-commerce.opo", refID: opo.documentId, field: "delivery_note", multiple: false, accept: "text/*,application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document", path: "api/ipos", componentName: "delivery_note", componentReference: "common.base64-encoded-media", revalidateCallback: revalidateCallback })] })) }) })] }) }), jsx(Grid, { size: 12, children: jsxs(Stack, { spacing: 2, children: [jsx(Typography, { variant: "h5", children: "Minio Documents" }), jsx(Paper, { sx: { p: 2 }, children: jsx(UploadMinioMediaForm, { reference: "api::e-commerce.opo", refID: opo.documentId, field: "minio", multiple: false, revalidateCallback: revalidateCallback }) })] }) }), opo?.notes?.length > 0 && (jsx(Grid, { size: 12, children: jsxs(Stack, { spacing: 2, children: [jsx(Typography, { variant: "h5", children: "Notes" }), jsx(NotesDisplay, { notes: opo.notes }), jsx(Divider, {})] }) })), jsx(Grid, { size: 12, children: jsxs(Stack, { spacing: 1, children: [jsx(Typography, { variant: "h5", children: "Items" }), jsxs(Stack, { direction: "row", alignItems: "center", justifyContent: "flex-end", spacing: 2, component: Paper, p: 1, children: [jsx(Typography, { variant: "body1", children: "Show:" }), options.map((option) => (jsx(FormControlLabel, { control: jsx(Checkbox, { checked: showing.includes(option), onChange: (e) => {
176
177
  if (e.target.checked) {
177
178
  setShowing([...showing, option]);
178
179
  }
@@ -10,8 +10,9 @@ import { useSnackbar } from '../../../context/common/SnackbarContext.js';
10
10
  import { updateIpoAction } from '../../../data/actions/logistics/ipo/updateIpoAction.js';
11
11
  import { confirmationService } from '../../../data/services/common/confirmation-service.js';
12
12
  import { cancellationService } from '../../../data/services/common/cancellation-service.js';
13
- import downloadBase64File from '../../../data/loaders/common/media/downloadBase64File.js';
14
- import { UploadBase64MediaForm } from '../../common/media/UploadBase64MediaForm.js';
13
+ import { UploadMinioMediaForm } from '../../common/media/minio/UploadMinioMediaForm.js';
14
+ import { MinioDeleteFormButton } from '../../common/media/minio/MinioDeleteFormButton.js';
15
+ import { MinioDownloadButton } from '../../common/media/minio/MinioDownloadButton.js';
15
16
  import NoteTakingComponent from '../note/NoteTakingComponent.js';
16
17
  import NotesDisplay from '../note/NotesDisplay.js';
17
18
  import ItemDisplay from './ItemDisplay.js';
@@ -210,11 +211,9 @@ function TextualManageIPOForm({ data, sx, revalidateCallback, handleClose, role,
210
211
  { id: data.documentId, __type: "api::logistics.ipo" },
211
212
  ], revalidateCallback: revalidateCallback })] }), jsx(Divider, {})] }) }), jsx(Grid, { size: 12, children: jsx(Typography, { variant: "h5", sx: { py: 1 }, children: "Details" }) }), jsx(Grid, { size: 6, children: jsx(Paper, { elevation: 2, sx: { p: 2, height: "100%" }, children: jsxs(Stack, { spacing: 2, children: [jsxs(Stack, { direction: "row", spacing: 2, alignItems: "center", children: [jsx(NumbersIcon, { color: "primary" }), jsx(Typography, { variant: "subtitle1", color: "text.secondary", width: "200px", children: "Purchase Order Number" }), jsx(Typography, { variant: "body1", fontWeight: "medium", children: data.ipo_number })] }), jsxs(Stack, { direction: "row", spacing: 2, alignItems: "center", children: [jsx(DescriptionIcon, { color: "primary" }), jsx(Typography, { variant: "subtitle1", color: "text.secondary", width: "200px", children: "Custom Reference" }), jsx(Typography, { variant: "body1", fontWeight: "medium", children: data.customer_reference })] }), jsxs(Stack, { direction: "row", spacing: 2, alignItems: "center", children: [jsx(CalendarTodayIcon, { color: "primary" }), jsx(Typography, { variant: "subtitle1", color: "text.secondary", width: "200px", children: "Order Date" }), jsx(Typography, { variant: "body1", fontWeight: "medium", children: data.order_date })] }), jsxs(Stack, { direction: "row", spacing: 2, alignItems: "center", children: [jsx(BusinessIcon, { color: "primary" }), jsx(Typography, { variant: "subtitle1", color: "text.secondary", width: "200px", children: "Supplier" }), jsx(Typography, { variant: "body1", fontWeight: "medium", children: data.vendor_profile?.business_credentials?.company_name })] }), jsxs(Stack, { direction: "row", spacing: 2, alignItems: "center", children: [jsx(UpdateIcon, { color: "primary" }), jsx(Typography, { variant: "subtitle1", color: "text.secondary", width: "200px", children: "Order Status" }), jsx(IpoStatusIndicator, { status: data.internal_status })] })] }) }) }), role === "enduser" && (jsx(Grid, { size: 6, children: jsx(Paper, { elevation: 2, sx: { p: 2, height: "100%" }, children: jsxs(Stack, { spacing: 2, children: [(data.internal_status === "placed" ||
212
213
  data.internal_status === "released_on_stock") && (jsxs(Fragment, { children: [jsx(Button, { variant: "contained", color: "primary", onClick: () => setConfirmDialogOpen(true), children: "Confirm order" }), jsx(Alert, { severity: "warning", children: "Please confirm the order as soon as possible, only upon confirmation this order will be available to the dispatcher" }), jsx(ConfirmFormDialog, { open: confirmDialogOpen, handleClose: () => setConfirmDialogOpen(false), orderID: data.documentId, currentStatus: data.internal_status, revalidateCallback: revalidateCallback })] })), (data.internal_status === "placed" ||
213
- data.internal_status === "ordered") && (jsxs(Fragment, { children: [jsx(Button, { variant: "contained", color: "error", onClick: () => setCancelDialogOpen(true), children: "Cancel order" }), jsx(CancelIpoDialog, { open: cancelDialogOpen, handleClose: () => setCancelDialogOpen(false), orderID: data.documentId, revalidateCallback: revalidateCallback })] }))] }) }) })), jsx(Grid, { size: 12, children: jsxs(Stack, { spacing: 2, children: [jsx(Typography, { variant: "h5", children: "Documents" }), jsx(Paper, { sx: { p: 2 }, children: jsxs(Stack, { spacing: 1, children: [role === "enduser" && (jsx(Fragment, { children: data.order_confirmation ? (jsxs(Fragment, { children: [jsx(Typography, { variant: "h6", children: "Order Confirmation" }), jsx(Typography, { children: data.order_confirmation?.name }), jsx(Button, { variant: "contained", onClick: () => {
214
- downloadBase64File(`api/ipos/${data.documentId}`, "order_confirmation");
215
- }, children: "Download" })] })) : (jsxs(Fragment, { children: [jsx(Typography, { variant: "h5", children: "Order Confirmation" }), jsx(Typography, { variant: "body1", children: "Here you can upload the the order confirmation for this order" }), jsx(Typography, { variant: "body1", children: "FileUpload" }), jsx(Divider, {}), jsx(UploadBase64MediaForm /* This form manages it's own state internally */, { reference: "api::logistics.ipo", refID: data.documentId, field: "order_confirmation", multiple: false, accept: "text/*,application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document", path: "api/ipos", componentName: "order_confirmation", componentReference: "common.base64-encoded-media", revalidateCallback: revalidateCallback })] })) })), data.delivery_note ? (jsxs(Fragment, { children: [jsx(Typography, { variant: "h6", children: "Delivery Note" }), jsx(Typography, { children: data.delivery_note?.name }), jsx(Button, { variant: "contained", onClick: () => {
216
- downloadBase64File(`api/ipos/${data.documentId}`, "delivery_note");
217
- }, children: "Download" })] })) : (jsxs(Fragment, { children: [jsx(Typography, { variant: "h5", children: "Delivery Note" }), jsx(Typography, { variant: "body1", children: "Here you can upload the the delivery note for this order" }), jsx(Divider, {}), jsx(UploadBase64MediaForm, { reference: "api::logistics.ipo", refID: data.documentId, field: "delivery_note", multiple: false, accept: "text/*,application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document", path: "api/ipos", componentName: "delivery_note", componentReference: "common.base64-encoded-media", revalidateCallback: revalidateCallback })] }))] }) })] }) }), data?.notes?.length > 0 && (jsx(Grid, { size: 12, children: jsxs(Stack, { spacing: 2, children: [jsx(Typography, { variant: "h5", children: "Notes" }), jsx(NotesDisplay, { notes: data.notes }), jsx(Divider, {})] }) })), jsx(Grid, { size: 12, children: jsxs(Stack, { spacing: 1, children: [jsx(Typography, { variant: "h5", children: "Items" }), jsxs(Stack, { direction: "row", alignItems: "center", justifyContent: "flex-end", spacing: 2, component: Paper, p: 1, sx: {
214
+ data.internal_status === "ordered") && (jsxs(Fragment, { children: [jsx(Button, { variant: "contained", color: "error", onClick: () => setCancelDialogOpen(true), children: "Cancel order" }), jsx(CancelIpoDialog, { open: cancelDialogOpen, handleClose: () => setCancelDialogOpen(false), orderID: data.documentId, revalidateCallback: revalidateCallback })] }))] }) }) })), jsx(Grid, { size: 12, children: jsxs(Stack, { spacing: 2, children: [jsx(Typography, { variant: "h5", children: "Documents" }), jsx(Paper, { sx: { p: 2 }, children: jsxs(Stack, { spacing: 4, children: [role === "enduser" && (jsx(Fragment, { children: data.minio_order_confirmation ? (jsx(Fragment, { children: jsxs(Stack, { spacing: 2, children: [jsx(Typography, { variant: "h6", children: "Order Confirmation" }), jsxs(Typography, { children: ["File: ", data.minio_order_confirmation?.fileName] }), jsxs(Typography, { variant: "body2", color: "text.secondary", children: ["Size: ", data.minio_order_confirmation?.fileSize, " ", "bytes"] }), jsxs(Typography, { variant: "body2", color: "text.secondary", children: ["Type: ", data.minio_order_confirmation?.mimeType] }), jsxs(Stack, { direction: "row", spacing: 2, alignItems: "center", children: [jsx(MinioDownloadButton, { bucketName: data.minio_order_confirmation?.bucketName ||
215
+ "umwd", fileName: data.minio_order_confirmation?.fileName || "" }), jsx(MinioDeleteFormButton, { bucketName: data.minio_order_confirmation?.bucketName ||
216
+ "umwd", fileName: data.minio_order_confirmation?.fileName || "", revalidateCallback: revalidateCallback })] })] }) })) : (jsx(Fragment, { children: jsxs(Stack, { spacing: 2, children: [jsx(Typography, { variant: "h6", children: "Order Confirmation" }), jsx(Typography, { variant: "body2", children: "Upload the order confirmation document for this purchase order" }), jsx(UploadMinioMediaForm, { reference: "api::logistics.ipo", refID: data.documentId, field: "minio_order_confirmation", bucketName: "umwd", multiple: false, accept: "application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,text/*", revalidateCallback: revalidateCallback })] }) })) })), data.minio_delivery_note ? (jsx(Fragment, { children: jsxs(Stack, { spacing: 2, children: [jsx(Typography, { variant: "h6", children: "Delivery Note" }), jsxs(Typography, { children: ["File: ", data.minio_delivery_note?.fileName] }), jsxs(Typography, { variant: "body2", color: "text.secondary", children: ["Size: ", data.minio_delivery_note?.fileSize, " bytes"] }), jsxs(Typography, { variant: "body2", color: "text.secondary", children: ["Type: ", data.minio_delivery_note?.mimeType] }), jsxs(Stack, { direction: "row", spacing: 2, alignItems: "center", children: [jsx(MinioDownloadButton, { bucketName: data.minio_delivery_note?.bucketName || "umwd", fileName: data.minio_delivery_note?.fileName || "" }), jsx(MinioDeleteFormButton, { bucketName: data.minio_delivery_note?.bucketName || "umwd", fileName: data.minio_delivery_note?.fileName || "", revalidateCallback: revalidateCallback })] })] }) })) : (jsx(Fragment, { children: jsxs(Stack, { spacing: 2, children: [jsx(Typography, { variant: "h6", children: "Delivery Note" }), jsx(Typography, { variant: "body2", children: "Upload the delivery note document for this purchase order" }), jsx(UploadMinioMediaForm, { reference: "api::logistics.ipo", refID: data.documentId, field: "minio_delivery_note", bucketName: "umwd", multiple: false, accept: "application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,text/*", revalidateCallback: revalidateCallback })] }) }))] }) })] }) }), data?.notes?.length > 0 && (jsx(Grid, { size: 12, children: jsxs(Stack, { spacing: 2, children: [jsx(Typography, { variant: "h5", children: "Notes" }), jsx(NotesDisplay, { notes: data.notes }), jsx(Divider, {})] }) })), jsx(Grid, { size: 12, children: jsxs(Stack, { spacing: 1, children: [jsx(Typography, { variant: "h5", children: "Items" }), jsxs(Stack, { direction: "row", alignItems: "center", justifyContent: "flex-end", spacing: 2, component: Paper, p: 1, sx: {
218
217
  bgcolor: "background.default",
219
218
  border: "1px solid",
220
219
  borderColor: "divider",
@@ -0,0 +1,59 @@
1
+ /*
2
+ * UMWD-Components
3
+ * @copyright Jelle Paulus
4
+ * @license MIT
5
+ */
6
+
7
+ import { minioDeleteService } from '../../../services/common/media/minio/minioDeleteService.js';
8
+ import { flattenAttributes } from '../../../../lib/utils.js';
9
+
10
+ /*
11
+ TODO
12
+
13
+ const MAX_FILE_SIZE = 5000000;
14
+
15
+ const ACCEPTED_IMAGE_TYPES = [
16
+ "image/jpeg",
17
+ "image/jpg",
18
+ "image/png",
19
+ "image/webp",
20
+ ]; */
21
+ async function deleteMinioMediaAction(bucketName, fileName, prevState) {
22
+ console.log("bucketName:", bucketName, " fileName:", fileName, "prevState:", prevState);
23
+ if (!bucketName || !fileName) {
24
+ return {
25
+ ...prevState,
26
+ strapiErrors: null,
27
+ data: null,
28
+ message: "Invalid Image",
29
+ };
30
+ }
31
+ // DELETE IMAGE FROM MINIO
32
+ const fileDeleteResponse = await minioDeleteService(bucketName, fileName);
33
+ if (!fileDeleteResponse) {
34
+ return {
35
+ ...prevState,
36
+ strapiErrors: null,
37
+ zodErrors: null,
38
+ message: "Ops! Something went wrong. Please try again.",
39
+ };
40
+ }
41
+ if (fileDeleteResponse.error) {
42
+ return {
43
+ ...prevState,
44
+ strapiErrors: fileDeleteResponse.error,
45
+ zodErrors: null,
46
+ message: "Failed to Delete File.",
47
+ };
48
+ }
49
+ const flattenedData = flattenAttributes(fileDeleteResponse);
50
+ return {
51
+ ...prevState,
52
+ data: flattenedData,
53
+ zodErrors: null,
54
+ strapiErrors: null,
55
+ message: "Image Deleted Successfully",
56
+ };
57
+ }
58
+
59
+ export { deleteMinioMediaAction };
@@ -4,7 +4,7 @@
4
4
  * @license MIT
5
5
  */
6
6
 
7
- import { minioUploadService } from '../../../services/common/media/minio/minio-service.js';
7
+ import { minioUploadService } from '../../../services/common/media/minio/minioUploadService.js';
8
8
  import { flattenAttributes } from '../../../../lib/utils.js';
9
9
 
10
10
  // VALIDATE IMAGE WITH ZOD
@@ -23,15 +23,17 @@ import { flattenAttributes } from '../../../../lib/utils.js';
23
23
  .refine((file) => file.size <= MAX_FILE_SIZE, `Max file size is 5MB.`),
24
24
  }); */
25
25
  async function uploadMinioMediaAction(prevState, formData) {
26
- // CONVERT FORM DATA TO OBJECT
26
+ // CONVERT FORM DATA TO OBJEC
27
27
  const rawFormData = Object.fromEntries(formData);
28
- console.log(rawFormData.bucketName);
29
- console.log(rawFormData.fileName);
30
- console.log(rawFormData.files);
31
28
  const bucketName = rawFormData.bucketName;
32
29
  const fileName = rawFormData.fileName;
33
30
  const files = rawFormData.files;
34
- const fileContent = files instanceof File ? files : Buffer.from(files, "base64");
31
+ console.log("files:", files);
32
+ // Convert file to ArrayBuffer first, then to Buffer, then to base64 string
33
+ const arrayBuffer = await files.arrayBuffer();
34
+ const fileContent = Buffer.from(arrayBuffer).toString("base64");
35
+ console.log("fileContent length:", fileContent.length);
36
+ console.log(bucketName, fileName, fileContent);
35
37
  // UPLOAD NEW IMAGE TO MINIO
36
38
  const fileUploadResponse = await minioUploadService(bucketName, fileName, fileContent);
37
39
  if (!fileUploadResponse) {
@@ -0,0 +1,39 @@
1
+ "use client";
2
+ /*
3
+ * UMWD-Components
4
+ * @copyright Jelle Paulus
5
+ * @license MIT
6
+ */
7
+
8
+ /**
9
+ * Client-side utility to handle file downloads from a signed URL
10
+ * This function should be called from client components after getting the signed URL from downloadMinioItem
11
+ */
12
+ async function downloadMinioItemClient(signedUrl, fileName) {
13
+ try {
14
+ // Fetch the file from the signed URL
15
+ const fileResponse = await fetch(signedUrl);
16
+ if (!fileResponse.ok) {
17
+ throw new Error(`Failed to download file: ${fileResponse.statusText}`);
18
+ }
19
+ // Create blob and trigger download
20
+ const fileBlob = await fileResponse.blob();
21
+ const fileUrl = URL.createObjectURL(fileBlob);
22
+ // Create temporary anchor element to trigger download
23
+ const link = document.createElement("a");
24
+ link.href = fileUrl;
25
+ link.setAttribute("download", fileName);
26
+ document.body.appendChild(link);
27
+ link.click();
28
+ // Clean up
29
+ document.body.removeChild(link);
30
+ URL.revokeObjectURL(fileUrl);
31
+ return { success: true, fileName };
32
+ }
33
+ catch (error) {
34
+ console.error("Error downloading file:", error);
35
+ throw error;
36
+ }
37
+ }
38
+
39
+ export { downloadMinioItemClient };
@@ -0,0 +1,52 @@
1
+ "use server";
2
+ /*
3
+ * UMWD-Components
4
+ * @copyright Jelle Paulus
5
+ * @license MIT
6
+ */
7
+
8
+ import { getStrapiURL } from '../../../../../lib/utils.js';
9
+ import { getAuthToken } from '../../../../services/get-token.js';
10
+
11
+ const baseUrl = getStrapiURL();
12
+ async function getMinioSignedUrl(bucketName, fileName) {
13
+ console.log("minio bucket:", bucketName);
14
+ console.log("minio fileName:", fileName);
15
+ if (!bucketName || !fileName) {
16
+ throw new Error("Bucket name and file name are required");
17
+ }
18
+ const authToken = await getAuthToken();
19
+ const headers = {
20
+ method: "POST",
21
+ headers: {
22
+ "Content-Type": "application/json",
23
+ Authorization: `Bearer ${authToken}`,
24
+ },
25
+ body: JSON.stringify({
26
+ bucketName: bucketName,
27
+ fileName: fileName,
28
+ }),
29
+ };
30
+ const url = new URL("/api/minio-plugin/minio/signed-url", baseUrl);
31
+ try {
32
+ // Step 1: Get the signed URL
33
+ const signedUrlResponse = await fetch(url, authToken ? headers : {});
34
+ if (!signedUrlResponse.ok) {
35
+ throw new Error(`Failed to fetch signed URL: ${signedUrlResponse.statusText}`);
36
+ }
37
+ const signedUrlData = await signedUrlResponse.json();
38
+ // Return the signed URL for client-side download handling
39
+ return {
40
+ success: true,
41
+ signedUrl: signedUrlData.url,
42
+ fileName,
43
+ bucketName,
44
+ };
45
+ }
46
+ catch (error) {
47
+ console.error("Error downloading file:", error);
48
+ throw error;
49
+ }
50
+ }
51
+
52
+ export { getMinioSignedUrl };
@@ -22,16 +22,21 @@ async function minioUploadService(bucketName, fileName, fileContent) {
22
22
  throw new Error("No auth token found");
23
23
  const baseUrl = getStrapiURL();
24
24
  const url = new URL("/api/minio-plugin/minio/upload", baseUrl);
25
- // const formData = new FormData();
26
- // formData.append("files", image, image.name);
25
+ console.log("Sending to strapi minio-plugin:", {
26
+ bucketName,
27
+ fileName,
28
+ fileContent,
29
+ });
27
30
  try {
28
31
  const response = await fetch(url, {
29
32
  headers: { Authorization: `Bearer ${authToken}` },
30
33
  method: "POST",
31
34
  body: JSON.stringify({
32
- bucketName,
33
- fileName,
34
- fileContent,
35
+ data: {
36
+ bucketName,
37
+ fileName,
38
+ fileContent,
39
+ },
35
40
  }),
36
41
  });
37
42
  const dataResponse = await response.json();
@@ -0,0 +1,34 @@
1
+ "use server";
2
+ /*
3
+ * UMWD-Components
4
+ * @copyright Jelle Paulus
5
+ * @license MIT
6
+ */
7
+
8
+ import { getAuthToken } from '../../../get-token.js';
9
+ import { getStrapiURL } from '../../../../../lib/utils.js';
10
+
11
+ async function minioDeleteService(bucketName, fileName) {
12
+ console.log(bucketName, fileName);
13
+ const authToken = await getAuthToken();
14
+ if (!authToken)
15
+ throw new Error("No auth token found");
16
+ const baseUrl = getStrapiURL();
17
+ const url = new URL(`/api/minio-plugin/minio/delete/${bucketName}/${fileName}`, baseUrl);
18
+ console.log(url.toString());
19
+ try {
20
+ const response = await fetch(url, {
21
+ headers: { Authorization: `Bearer ${authToken}` },
22
+ method: "DELETE",
23
+ });
24
+ //console.log(response);
25
+ const dataResponse = await response.json();
26
+ return dataResponse;
27
+ }
28
+ catch (error) {
29
+ console.error("Error deleting file:", error);
30
+ throw new Error("Failed to delete file");
31
+ }
32
+ }
33
+
34
+ export { minioDeleteService };
@@ -0,0 +1,38 @@
1
+ "use server";
2
+ /*
3
+ * UMWD-Components
4
+ * @copyright Jelle Paulus
5
+ * @license MIT
6
+ */
7
+
8
+ import { getAuthToken } from '../../../get-token.js';
9
+ import { getStrapiURL } from '../../../../../lib/utils.js';
10
+
11
+ async function minioUploadService(bucketName, fileName, fileContent) {
12
+ const authToken = await getAuthToken();
13
+ if (!authToken)
14
+ throw new Error("No auth token found");
15
+ const baseUrl = getStrapiURL();
16
+ const url = new URL("/api/minio-plugin/minio/upload", baseUrl);
17
+ try {
18
+ const response = await fetch(url, {
19
+ headers: { Authorization: `Bearer ${authToken}` },
20
+ method: "POST",
21
+ body: JSON.stringify({
22
+ data: {
23
+ bucketName,
24
+ fileName,
25
+ fileContent,
26
+ },
27
+ }),
28
+ });
29
+ const dataResponse = await response.json();
30
+ return dataResponse;
31
+ }
32
+ catch (error) {
33
+ console.error("Error uploading image:", error);
34
+ throw error;
35
+ }
36
+ }
37
+
38
+ export { minioUploadService };