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 19, 2024
1 parent 8b2072c commit b2efe47
Show file tree
Hide file tree
Showing 16 changed files with 892 additions and 18 deletions.
60 changes: 60 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,63 @@ 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 FILE_EXT_TYPES = {
image: [
"png",
"jpg",
"jpeg",
"gif",
"webp",
"bmp",
],
video: [
"mkv",
"mp4",
"webm",
],
audio: [
"mp3",
"ogg",
"wav",
],
};

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,
"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",
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* 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: 5px;
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: 38px;
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: 30px;
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: lightgrey;
}

.in-review-file-modal .modal-dialog .modal-header .modal-title {
font-size: 26px;
}

/* 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 .modal-body {
/*width: fit-content;*/
display: flex;
flex-direction: row;
justify-content: center;
}

.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 .iframe-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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* 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.unitFile(data.unitId, data.filename));
setFileExt(data.filename.split(".").pop().toLowerCase());
}
}, [data]);

return (
show && (
<Modal className={"in-review-file-modal"} show={show} onHide={onModalClose}>
<Modal.Header closeButton={false}>
<button className={"button-close"} onClick={() => setShow(false)}>
</button>
<Modal.Title>
{truncateFilename(data.title, 50)}
</Modal.Title>
<a
className={"button-download-file"}
title={"Download source"}
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 && (
<audio className={""} controls={true}>
<source src={fileUrl} type={AUDIO_TYPES_BY_EXT[fileExt]} />
</audio>
)}
{fileType === FileType.PDF && (
<div className={"iframe-wrapper"}>
<iframe
className={""}
src={`${fileUrl}#view=fit&page=1&toolbar=0&navpanes=0`}
/>
</div>
)}
</>) : (<>
Cannot show preview for this type of file.
<br />
You can download and open file on your computer
</>)}
</Modal.Body>
</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
35 changes: 33 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,33 @@ 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;
setInReviewFileModalData({
filename: filename,
title: `File "${filename}"`,
unitId: currentUnitOnReview,
});
setInReviewFileModalShow(true);
}
}
};

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

<InReviewFileModal
show={inReviewFileModalShow}
setShow={setInReviewFileModalShow}
data={inReviewFileModalData}
setData={setInReviewFileModalData}
/>
</div>
);
}
Expand Down
11 changes: 11 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,11 @@
/*
* 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;
};
1 change: 1 addition & 0 deletions mephisto/review_app/client/src/urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const urls = {
unitsDetails: API_URL + "/api/units/details",
unitsReject: API_URL + "/api/units/reject",
unitsSoftReject: API_URL + "/api/units/soft-reject",
unitFile: (id, filename) => API_URL + `/api/units/${id}/static/${filename}`,
workersBlock: (id) => API_URL + `/api/workers/${id}/block`,
},
};
Expand Down
1 change: 1 addition & 0 deletions mephisto/review_app/server/api/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from .task_view import TaskView
from .tasks_view import TasksView
from .tasks_worker_units_view import TaskUnitIdsView
from .unit_data_static_view import UnitDataStaticView
from .unit_review_bundle_view import UnitReviewBundleView
from .unit_review_html_view import UnitReviewHtmlView
from .units_approve_view import UnitsApproveView
Expand Down
Loading

0 comments on commit b2efe47

Please sign in to comment.