Skip to content

Commit

Permalink
[Form Builder] Added file review modal in TaskReview
Browse files Browse the repository at this point in the history
  • Loading branch information
meta-paul committed Feb 20, 2024
1 parent 8b2072c commit 2477316
Show file tree
Hide file tree
Showing 19 changed files with 964 additions and 38 deletions.
43 changes: 43 additions & 0 deletions mephisto/review_app/client/src/consts/review.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
};
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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<React.SetStateAction<InReviewFileModalDataType>>;
show: boolean;
setShow: React.Dispatch<React.SetStateAction<boolean>>;
};

function InReviewFileModal(props: InReviewFileModalProps) {
const { data, show, setShow } = props;

const [fileUrl, setFileUrl] = React.useState<string>(null);
const [fileExt, setFileExt] = React.useState<string>(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 && (
<Modal
className={"in-review-file-modal"}
contentClassName={`file-type-${fileType}`}
show={show}
onHide={onModalClose}
>
<Modal.Header closeButton={false}>
<button
className={"button-close"}
title={"Close file preview"}
onClick={() => setShow(false)}
>
</button>
<Modal.Title>
{truncateFilename(data.title, 50)}
</Modal.Title>
<a
className={"button-download-file"}
title={"Download file"}
href={fileUrl}
target={"_blank"}
>
</a>
</Modal.Header>

<Modal.Body>
{fileType ? (<>
{fileType === FileType.IMAGE && (
<img className={""} src={fileUrl} alt={`image "${data.filename}}`} />
)}
{fileType === FileType.VIDEO && (
<video className={""} controls={true}>
<source src={fileUrl} type={VIDEO_TYPES_BY_EXT[fileExt]} />
</video>
)}
{fileType === FileType.AUDIO && (
<div className={"audio-wrapper"}>
<audio className={""} controls={true}>
<source src={fileUrl} type={AUDIO_TYPES_BY_EXT[fileExt]} />
</audio>
</div>
)}
{fileType === FileType.PDF && (
<div className={"pdf-wrapper"}>
<iframe
className={""}
src={`${fileUrl}#view=fit&page=1&toolbar=0&navpanes=0`}
/>
</div>
)}
</>) : (
<div className={"other-type-wrapper"}>
This file type cannot be previewed.<br/>
Please download it, or open locally.
</div>
)}
</Modal.Body>
<Modal.Footer>
<div className={"file-path"}>
Local folder path:&nbsp;&nbsp;&nbsp;{data.unitDataFolder}
</div>
</Modal.Footer>
</Modal>
)
);
}

export { InReviewFileModal };
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ type ReviewModalProps = {
};

function ReviewModal(props: ReviewModalProps) {
const onModalClose = () => {
function onModalClose() {
props.setShow(!props.show);
};
}

const onChangeApplyToNext = (value: boolean) => {
function onChangeApplyToNext(value: boolean) {
props.setData({ ...props.data, applyToNext: value });
};
}

return (
props.show && (
Expand Down
39 changes: 37 additions & 2 deletions mephisto/review_app/client/src/pages/TaskPage/TaskPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
* LICENSE file in the root directory of this source tree.
*/

import { ReviewType } from "consts/review";
import {
MESSAGES_IFRAME_DATA_KEY,
MESSAGES_IN_REVIEW_FILE_DATA_KEY,
ReviewType,
} from "consts/review";
import cloneDeep from "lodash/cloneDeep";
import * as React from "react";
import { useEffect } from "react";
Expand All @@ -27,6 +31,7 @@ import {
import { postWorkerBlock } from "requests/workers";
import urls from "urls";
import { setPageTitle, updateModalState } from "./helpers";
import { InReviewFileModal } from "./InReviewFileModal/InReviewFileModal";
import {
APPROVE_MODAL_DATA_STATE,
DEFAULT_MODAL_STATE_VALUE,
Expand Down Expand Up @@ -108,14 +113,37 @@ function TaskPage(props: PropsType) {
const [inputsVisibility, setInputsVisibility] = React.useState<boolean>(null);
const [resultsVisibility, setResultsVisibility] = React.useState<boolean>(null);

const [inReviewFileModalShow, setInReviewFileModalShow] = React.useState<boolean>(false);
const [inReviewFileModalData, setInReviewFileModalData] = React.useState<
InReviewFileModalDataType
>({});

window.onmessage = function (e) {
if (
e.data &&
e.type === "message" && // Waiting for `message` type only
!e.data?.type // Exclude all unexpected messages from iframe
) {
const data = JSON.parse(e.data);
setIframeHeight(data["IFRAME_DATA"]["height"]);

// Resize iframe message
if (data.hasOwnProperty(MESSAGES_IFRAME_DATA_KEY)) {
setIframeHeight(data[MESSAGES_IFRAME_DATA_KEY]["height"]);
}
// Open file field modal message
else if (data.hasOwnProperty(MESSAGES_IN_REVIEW_FILE_DATA_KEY)) {
const filename = data[MESSAGES_IN_REVIEW_FILE_DATA_KEY].filename;
const unitDataFolderStartIndex = currentUnitDetails.unit_data_folder.indexOf("data/data");
const unitDataFolder = currentUnitDetails.unit_data_folder.slice(unitDataFolderStartIndex);

setInReviewFileModalData({
filename: filename,
title: filename,
unitId: currentUnitOnReview,
unitDataFolder: unitDataFolder,
});
setInReviewFileModalShow(true);
}
}
};

Expand Down Expand Up @@ -668,6 +696,13 @@ function TaskPage(props: PropsType) {
setErrors={props.setErrors}
workerId={currentWorkerOnReview}
/>

<InReviewFileModal
show={inReviewFileModalShow}
setShow={setInReviewFileModalShow}
data={inReviewFileModalData}
setData={setInReviewFileModalData}
/>
</div>
);
}
Expand Down
12 changes: 12 additions & 0 deletions mephisto/review_app/client/src/types/inReviewFileModal.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* 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.
*/

type InReviewFileModalDataType = {
filename?: string;
title?: string;
unitId?: number;
unitDataFolder?: string;
};
Loading

0 comments on commit 2477316

Please sign in to comment.