@bindu-dashing/dam-solution-v2 5.9.256 → 5.9.257
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.
|
@@ -12,6 +12,7 @@ import { useState } from "react";
|
|
|
12
12
|
import { useDamConfig } from "../hocs/DamConfigContext";
|
|
13
13
|
import EditImageModal from "./ImageEditor/EditImageModal";
|
|
14
14
|
import EditPdfModal from "./PdfEditor/EditPdfModal";
|
|
15
|
+
import RefreshableImage from "../common/RefreshableImage";
|
|
15
16
|
const IconInprogress = GrInProgress;
|
|
16
17
|
const AiOutlineEditIcon = AiOutlineEdit;
|
|
17
18
|
const AiOutlineCheckCircleIcon = AiOutlineCheckCircle;
|
|
@@ -51,7 +52,7 @@ const FilesGridView = ({ files, handleClick, selectedFileIds, isImagePicker, sel
|
|
|
51
52
|
openEditor(file);
|
|
52
53
|
}, children: _jsx(AiOutlineEditIcon, { className: "md-lib-text-[18px] md-lib-text-textColor dark:md-lib-text-darkTextColor hover:md-lib-text-primary md-lib-cursor-pointer" }) }) }))] }), _jsx("div", { className: "md-lib-mt-2 md-lib-h-28 md-lib-mx-2.5 md-lib-bg-white dark:md-lib-bg-darkPrimaryHoverColor md-lib-rounded-md md-lib-flex md-lib-justify-center", children: get(file, "fileUploadStatus") === ThumbnailStatus.PENDING ? (
|
|
53
54
|
// <IconInprogress className="mt-10 text-[40px] text-imagesColor" />
|
|
54
|
-
_jsx(Image, { src: UPLOAD_FILE_IN_PROGRESS_WHITE_IMAGE, width: 100, height: 100 })) : (_jsx(
|
|
55
|
+
_jsx(Image, { src: UPLOAD_FILE_IN_PROGRESS_WHITE_IMAGE, width: 100, height: 100 })) : (_jsx(RefreshableImage, { src: get(file, "thumbnailUrl", ""), version: get(file, "updatedAt"), alt: get(file, "name", "N/A"), className: "md-lib-w-full md-lib-h-full md-lib-object-contain md-lib-p-1" })) }), _jsx("div", { children: _jsx("p", { className: "md-lib-text-xs md-lib-text-textColor dark:md-lib-text-darkTextColor md-lib-px-5 md-lib-pt-2.5 md-lib-truncate md-lib-max-w-40", title: get(file, "name", "N/A"), children: get(file, "assetName", "N/A") }) })] }, get(file, "_id")));
|
|
55
56
|
}) }), showEditModal && editFile && getEditorType(editFile) === "image" && (_jsx(EditImageModal, { open: showEditModal, handleClose: closeEditor, file: editFile })), showEditModal && editFile && getEditorType(editFile) === "pdf" && (_jsx(EditPdfModal, { open: showEditModal, handleClose: closeEditor, file: editFile }))] }));
|
|
56
57
|
};
|
|
57
58
|
export default FilesGridView;
|
|
@@ -19,7 +19,7 @@ import { get } from "lodash";
|
|
|
19
19
|
import CustomButton from "../../common/Button";
|
|
20
20
|
import { showNotification } from "../../common/notifications";
|
|
21
21
|
import { FILE_UPLOAD_ERROR, SOMETHING_WENT_WRONG, UPDATE_SUCCESS, } from "../../utilities/constants/messages";
|
|
22
|
-
import { FILE_UPLOAD_URL, SAVE_EDITED_FILE_THUMBNAIL_URL, SAVE_EDITED_FILE_URL, } from "../../utilities/constants/apiUrls";
|
|
22
|
+
import { CREATE_FILE_URL, FILE_UPLOAD_URL, SAVE_EDITED_FILE_THUMBNAIL_URL, SAVE_EDITED_FILE_URL, } from "../../utilities/constants/apiUrls";
|
|
23
23
|
import { generateFoldersQueryKey, invalidateData, QueryKeys, } from "../../utilities/constants/queryKeys";
|
|
24
24
|
import { useQueryClient } from "react-query";
|
|
25
25
|
import { useDamConfig } from "../../hocs/DamConfigContext";
|
|
@@ -106,30 +106,48 @@ const ImageEditorComponent = ({ file, handleClose, }) => {
|
|
|
106
106
|
const newName = buildEditedName(get(file, "name", "edited.png"));
|
|
107
107
|
const mimetype = editedFile.type || get(file, "mimetype") || "image/png";
|
|
108
108
|
try {
|
|
109
|
+
// 1) ask backend for a presigned S3 upload URL
|
|
109
110
|
const presigned = yield api.post(FILE_UPLOAD_URL, {
|
|
110
111
|
brandId,
|
|
111
112
|
folderId: currentFolderId,
|
|
112
113
|
files: [{ name: newName, size: editedFile.size }],
|
|
113
114
|
});
|
|
114
|
-
const
|
|
115
|
+
const uploadEntry = get(presigned, ["data", 0]);
|
|
116
|
+
const uploadUrl = get(uploadEntry, "url");
|
|
117
|
+
const filePath = get(uploadEntry, "filePath");
|
|
115
118
|
if (!uploadUrl) {
|
|
116
119
|
showNotification(FILE_UPLOAD_ERROR, NotificationStatus.ERROR);
|
|
117
120
|
setState((prev) => (Object.assign(Object.assign({}, prev), { loading: false })));
|
|
118
121
|
return;
|
|
119
122
|
}
|
|
123
|
+
// 2) PUT the edited binary to S3
|
|
120
124
|
const s3Resp = yield fetch(uploadUrl, {
|
|
121
125
|
method: "PUT",
|
|
122
126
|
headers: { "Content-Type": mimetype },
|
|
123
127
|
body: editedFile,
|
|
124
128
|
});
|
|
125
|
-
if (s3Resp.ok) {
|
|
126
|
-
invalidateAfterChange();
|
|
127
|
-
showNotification(UPDATE_SUCCESS, NotificationStatus.SUCCESS);
|
|
128
|
-
handleClose();
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
129
|
+
if (!s3Resp.ok) {
|
|
131
130
|
showNotification(FILE_UPLOAD_ERROR, NotificationStatus.ERROR);
|
|
131
|
+
setState((prev) => (Object.assign(Object.assign({}, prev), { loading: false })));
|
|
132
|
+
return;
|
|
132
133
|
}
|
|
134
|
+
// 3) register the file in the DB so it shows up in the folder grid
|
|
135
|
+
yield api.post(CREATE_FILE_URL, {
|
|
136
|
+
folderId: currentFolderId,
|
|
137
|
+
files: [
|
|
138
|
+
{
|
|
139
|
+
name: newName,
|
|
140
|
+
path: filePath,
|
|
141
|
+
size: editedFile.size,
|
|
142
|
+
mimetype,
|
|
143
|
+
metadata: {},
|
|
144
|
+
teamIds: get(file, "teamIds") || [],
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
});
|
|
148
|
+
invalidateAfterChange();
|
|
149
|
+
showNotification(UPDATE_SUCCESS, NotificationStatus.SUCCESS);
|
|
150
|
+
handleClose();
|
|
133
151
|
}
|
|
134
152
|
catch (error) {
|
|
135
153
|
showNotification(get(error, "message", SOMETHING_WENT_WRONG), NotificationStatus.ERROR);
|
|
@@ -4,6 +4,7 @@ import ImageOptions from "./ImageOptions";
|
|
|
4
4
|
import { useState } from "react";
|
|
5
5
|
import { SAMPLE_IMAGE_URL } from "../../utilities/constants/imageUrls";
|
|
6
6
|
import { useDamConfig } from "../../hocs/DamConfigContext";
|
|
7
|
+
import RefreshableImage from "../../common/RefreshableImage";
|
|
7
8
|
const ImageViewer = ({ file, showFilePreview }) => {
|
|
8
9
|
const damConfig = useDamConfig();
|
|
9
10
|
const { isAdmin } = damConfig;
|
|
@@ -11,6 +12,6 @@ const ImageViewer = ({ file, showFilePreview }) => {
|
|
|
11
12
|
const zoomOptions = ["10", "25", "50", "75", "100"];
|
|
12
13
|
const imgWidth = 750 * (parseInt(zoom) / 100);
|
|
13
14
|
// const imgHeight = 333 * (parseInt(zoom) / 100);
|
|
14
|
-
return (_jsxs("div", { className: "md-lib-relative md-lib-flex md-lib-flex-col md-lib-h-[calc(100vh-65px)] md-lib-w-full md-lib-overflow-hidden", children: [_jsx("div", { className: "md-lib-flex-1 md-lib-flex md-lib-justify-center md-lib-items-center md-lib-w-full md-lib-overflow-auto md-lib-min-h-0", children: _jsx(
|
|
15
|
+
return (_jsxs("div", { className: "md-lib-relative md-lib-flex md-lib-flex-col md-lib-h-[calc(100vh-65px)] md-lib-w-full md-lib-overflow-hidden", children: [_jsx("div", { className: "md-lib-flex-1 md-lib-flex md-lib-justify-center md-lib-items-center md-lib-w-full md-lib-overflow-auto md-lib-min-h-0", children: _jsx(RefreshableImage, { src: get(file, "s3Url") || get(file, "downloadUrl") || get(file, "thumbnailUrl", SAMPLE_IMAGE_URL), version: get(file, "updatedAt"), alt: get(file, "name", ""), width: imgWidth, height: "auto", className: "md-lib-max-w-full md-lib-max-h-full md-lib-object-contain" }) }), showFilePreview && (_jsx("div", { className: "md-lib-flex md-lib-justify-center md-lib-items-center md-lib-py-4 md-lib-shrink-0", children: _jsx(ImageOptions, { zoom: zoom, setZoom: setZoom, zoomOptions: zoomOptions, file: file }) }))] }));
|
|
15
16
|
};
|
|
16
17
|
export default ImageViewer;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* <img> wrapper that bypasses the browser HTTP cache when `version` changes.
|
|
4
|
+
*
|
|
5
|
+
* Why: S3 presigned URLs don't change after a file is overwritten in place
|
|
6
|
+
* (same key → same signed URL). The browser's HTTP cache then serves the
|
|
7
|
+
* old binary even when react-query refetches the file list. Appending
|
|
8
|
+
* query params would break the S3 signature, so instead we re-fetch the URL
|
|
9
|
+
* with `cache: 'reload'` and display the result via an object URL — the
|
|
10
|
+
* blob URL is unique so the browser must paint the fresh bytes.
|
|
11
|
+
*/
|
|
12
|
+
type Props = Omit<React.ImgHTMLAttributes<HTMLImageElement>, "src"> & {
|
|
13
|
+
src: string;
|
|
14
|
+
version?: string | number | null;
|
|
15
|
+
};
|
|
16
|
+
declare const RefreshableImage: React.FC<Props>;
|
|
17
|
+
export default RefreshableImage;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
|
+
import { useEffect, useRef, useState } from "react";
|
|
14
|
+
const RefreshableImage = (_a) => {
|
|
15
|
+
var { src, version } = _a, imgProps = __rest(_a, ["src", "version"]);
|
|
16
|
+
const [blobSrc, setBlobSrc] = useState(null);
|
|
17
|
+
const initialVersion = useRef(version);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (!version || version === initialVersion.current)
|
|
20
|
+
return;
|
|
21
|
+
let canceled = false;
|
|
22
|
+
fetch(src, { cache: "reload" })
|
|
23
|
+
.then((r) => r.blob())
|
|
24
|
+
.then((blob) => {
|
|
25
|
+
if (canceled)
|
|
26
|
+
return;
|
|
27
|
+
setBlobSrc((prev) => {
|
|
28
|
+
if (prev)
|
|
29
|
+
URL.revokeObjectURL(prev);
|
|
30
|
+
return URL.createObjectURL(blob);
|
|
31
|
+
});
|
|
32
|
+
})
|
|
33
|
+
.catch(() => {
|
|
34
|
+
/* fall through to original src */
|
|
35
|
+
});
|
|
36
|
+
return () => {
|
|
37
|
+
canceled = true;
|
|
38
|
+
};
|
|
39
|
+
}, [version, src]);
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
return () => {
|
|
42
|
+
if (blobSrc)
|
|
43
|
+
URL.revokeObjectURL(blobSrc);
|
|
44
|
+
};
|
|
45
|
+
}, [blobSrc]);
|
|
46
|
+
return _jsx("img", Object.assign({ src: blobSrc !== null && blobSrc !== void 0 ? blobSrc : src }, imgProps));
|
|
47
|
+
};
|
|
48
|
+
export default RefreshableImage;
|