diff --git a/mephisto/review_app/client/src/consts/review.ts b/mephisto/review_app/client/src/consts/review.ts index 85b79e5d6..4b2569cb5 100644 --- a/mephisto/review_app/client/src/consts/review.ts +++ b/mephisto/review_app/client/src/consts/review.ts @@ -9,3 +9,46 @@ export const ReviewType = { REJECT: "reject", SOFT_REJECT: "softReject", }; + +export const MESSAGES_IFRAME_DATA_KEY = "IFRAME_DATA"; + +export const MESSAGES_IN_REVIEW_FILE_DATA_KEY = "IN_REVIEW_FILE_DATA"; + +export const FileType = { + AUDIO: "audio", + IMAGE: "image", + PDF: "pdf", + VIDEO: "video", +}; + +export const FILE_TYPE_BY_EXT = { + "png": FileType.IMAGE, + "jpg": FileType.IMAGE, + "jpeg": FileType.IMAGE, + "gif": FileType.IMAGE, + "heic": FileType.IMAGE, + "heif": FileType.IMAGE, + "webp": FileType.IMAGE, + "bmp": FileType.IMAGE, + "mkv": FileType.VIDEO, + "mp4": FileType.VIDEO, + "webm": FileType.VIDEO, + "mp3": FileType.AUDIO, + "ogg": FileType.AUDIO, + "wav": FileType.AUDIO, + "pdf": FileType.PDF, +}; + +export const AUDIO_TYPES_BY_EXT = { + "mp3": "audio/mpeg", + "ogg": "audio/ogg", + "wav": "audio/wav", +}; + +export const VIDEO_TYPES_BY_EXT = { + "mkv": "video/x-matroska", + "mp4": "video/mp4", + "webm": "video/webm", + "mov": "video/quicktime", + "avi": "video/x-msvideo", +}; diff --git a/mephisto/review_app/client/src/pages/TaskPage/InReviewFileModal/InReviewFileModal.css b/mephisto/review_app/client/src/pages/TaskPage/InReviewFileModal/InReviewFileModal.css new file mode 100644 index 000000000..9fd9dd35e --- /dev/null +++ b/mephisto/review_app/client/src/pages/TaskPage/InReviewFileModal/InReviewFileModal.css @@ -0,0 +1,120 @@ +/* + * Copyright (c) Meta Platforms and its affiliates. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +.in-review-file-modal .modal-dialog { + max-width: 98vw; + min-width: 500px; + width: fit-content; +} + +.in-review-file-modal .modal-dialog .modal-header { + background-color: #ecdadf; + display: flex; + justify-content: space-between; + padding: 15px; + border-radius: 0; +} + +.in-review-file-modal .modal-dialog .modal-header .button-close { + height: 38px; + width: 38px; + display: flex; + justify-content: center; + align-items: center; + background-color: transparent; + border: none; + font-size: 28px; + line-height: 1; + cursor: pointer; +} + +.in-review-file-modal .modal-dialog .modal-header .button-download-file { + height: 38px; + width: 38px; + display: flex; + justify-content: center; + align-items: center; + background-color: transparent; + border: none; + font-size: 26px; + line-height: 1; + cursor: pointer; + text-decoration: none; + color: black; +} + +.in-review-file-modal .modal-dialog .modal-header .button-close:hover, +.in-review-file-modal .modal-dialog .modal-header .button-download-file:hover { + opacity: 0.7; + background-color: #ddb6c1; +} + +.in-review-file-modal .modal-dialog .modal-header .modal-title { + font-size: 26px; + padding: 0 15px; +} + +/* Body */ +.in-review-file-modal .modal-dialog .modal-content { + border-radius: initial; + width: fit-content; + min-width: 500px; +} + +.in-review-file-modal .modal-dialog .modal-content.file-type-audio { + min-width: 700px; +} + +.in-review-file-modal .modal-dialog .modal-content .modal-body { + display: flex; + flex-direction: row; + justify-content: center; + padding: 0; +} + +.in-review-file-modal .modal-dialog .modal-content .modal-body img, +.in-review-file-modal .modal-dialog .modal-content .modal-body video { + width: fit-content; + max-width: 100%; +} + +.in-review-file-modal .modal-dialog .modal-content .modal-body .pdf-wrapper { + position: relative; + width: 100%; + padding-top: calc(129% + 2%); +} +.in-review-file-modal .modal-dialog .modal-content .modal-body iframe { + position: absolute; + top: 0; + width: 100%; + height: 100%; + background-color: #f2f2f2; + border: 1px solid #cccccc; +} + +.in-review-file-modal .modal-dialog .modal-content .modal-body .audio-wrapper { + width: 100%; + padding: 25px; +} +.in-review-file-modal .modal-dialog .modal-content .modal-body .audio-wrapper audio { + width: 100%; +} + +.in-review-file-modal .modal-dialog .modal-content .modal-body .other-type-wrapper { + padding: 25px; +} + +/* Footer */ +.in-review-file-modal .modal-dialog .modal-content .modal-footer { + justify-content: center; +} +.in-review-file-modal .modal-dialog .modal-content .modal-footer .file-path { + margin: 0; + padding: 0; + color: grey; + font-size: 14px; + font-style: italic; +} diff --git a/mephisto/review_app/client/src/pages/TaskPage/InReviewFileModal/InReviewFileModal.tsx b/mephisto/review_app/client/src/pages/TaskPage/InReviewFileModal/InReviewFileModal.tsx new file mode 100644 index 000000000..39f85aefa --- /dev/null +++ b/mephisto/review_app/client/src/pages/TaskPage/InReviewFileModal/InReviewFileModal.tsx @@ -0,0 +1,123 @@ +/* + * Copyright (c) Meta Platforms and its affiliates. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { AUDIO_TYPES_BY_EXT, FILE_TYPE_BY_EXT, FileType, VIDEO_TYPES_BY_EXT } from "consts/review"; +import * as React from "react"; +import { useEffect } from "react"; +import { Modal } from "react-bootstrap"; +import urls from "urls"; +import "./InReviewFileModal.css"; + + +type InReviewFileModalProps = { + data: InReviewFileModalDataType; + setData: React.Dispatch>; + show: boolean; + setShow: React.Dispatch>; +}; + +function InReviewFileModal(props: InReviewFileModalProps) { + const { data, show, setShow } = props; + + const [fileUrl, setFileUrl] = React.useState(null); + const [fileExt, setFileExt] = React.useState(null); + + const fileType = FILE_TYPE_BY_EXT[fileExt]; + + function onModalClose() { + setShow(!show); + } + + function truncateFilename(filename: string, n: number): string { + const ext = data.filename.split(".").pop(); + const _filename = (filename.length > n) + ? (filename.slice(0, (n - 1 - ext.length)) + "…" + "." + ext) + : filename; + return _filename; + } + + useEffect(() => { + setFileUrl(null); + setFileExt(null); + + if (data.filename) { + setFileUrl(urls.server.unitsOutputsFile(data.unitId, data.filename)); + setFileExt(data.filename.split(".").pop().toLowerCase()); + } + }, [data]); + + return ( + show && ( + + + + + {truncateFilename(data.title, 50)} + + + ⤓ + + + + + {fileType ? (<> + {fileType === FileType.IMAGE && ( + {`image + )} + {fileType === FileType.VIDEO && ( + + )} + {fileType === FileType.AUDIO && ( +
+ +
+ )} + {fileType === FileType.PDF && ( +
+