diff --git a/src/common/DeleteDialog.jsx b/src/common/DeleteDialog.jsx index 5e5cd812..76d004bf 100644 --- a/src/common/DeleteDialog.jsx +++ b/src/common/DeleteDialog.jsx @@ -101,6 +101,7 @@ const DeleteDialog = ({ Cancel + + + + ); +}; + +export default TaskReopenDialog; diff --git a/src/common/VideoDialog.jsx b/src/common/VideoDialog.jsx index 4a1e29fb..fbf5f142 100644 --- a/src/common/VideoDialog.jsx +++ b/src/common/VideoDialog.jsx @@ -1,14 +1,15 @@ -import React, { useCallback, useEffect, useRef, useState } from "react"; +import React, { Fragment, useCallback, useEffect, useRef, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { getMilliseconds, getTimeStamp, MenuProps } from "utils"; import { useVideoSubtitle } from "hooks"; -import { voiceOptions } from "config"; +import { speakerFields, voiceOptions } from "config"; //Styles import { ProjectStyle } from "styles"; import useMediaQuery from "@mui/material/useMediaQuery"; import { useTheme } from "@mui/material/styles"; + //Components import { Box, @@ -26,12 +27,21 @@ import { Select, MenuItem, Tooltip, + Radio, + RadioGroup, + FormControlLabel, + Accordion, + AccordionDetails, + AccordionSummary, } from "@mui/material"; import FullscreenIcon from "@mui/icons-material/Fullscreen"; import FullscreenExitIcon from "@mui/icons-material/FullscreenExit"; import CustomSwitchDarkBackground from "./CustomSwitchDarkBackground"; import CloseIcon from "@mui/icons-material/Close"; import VideoTaskList from "containers/Organization/Project/VideoTaskList"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; +import DeleteIcon from "@mui/icons-material/Delete"; +import AddIcon from "@mui/icons-material/Add"; //APIs import C from "redux/constants"; @@ -46,7 +56,8 @@ const VideoDialog = ({ open, handleClose, videoDetails }) => { const theme = useTheme(); const dispatch = useDispatch(); const fullScreen = useMediaQuery(theme.breakpoints.down("lg")); - + // const [speakerType, setSpeakerType] = useState("individual"); + const [speakerType, setSpeakerType] = useState(videoDetails[0].multiple_speaker?"multiple":"individual"); const [time, setTime] = useState(""); const [subtitles, setSubtitles] = useState([]); const [highlightedSubtitle, setHighlightedSubtitle] = useState([]); @@ -59,6 +70,7 @@ const VideoDialog = ({ open, handleClose, videoDetails }) => { message: "", variant: "success", }); + const [speakerInfo, setSpeakerInfo] = useState(videoDetails[0].speaker_info); const ref = useRef(null); const { subtitle } = useVideoSubtitle(videoDetails[0].id); @@ -95,6 +107,48 @@ const VideoDialog = ({ open, handleClose, videoDetails }) => { // eslint-disable-next-line }, [subtitles]); + const handleRemoveSpeaker = (event, index) => { + event.stopPropagation(); + + const temp = [...speakerInfo]; + temp.splice(index, 1); + + setSpeakerInfo(temp); + }; + + const handleSpeakerFieldChange = (event, index) => { + const { + target: { name, value }, + } = event; + + const temp = [...speakerInfo]; + + if (name === "name") { + const spaceIndex = value.indexOf(" "); + + if (spaceIndex !== -1) { + temp[index]["id"] = value.substring(0, spaceIndex); + } else { + temp[index]["id"] = value; + } + } + temp[index][name] = value; + + setSpeakerInfo(temp); + }; + + const handleAddMoreSpeakers = () => { + setSpeakerInfo((prevState) => [ + ...prevState, + { + name: "", + gender: "", + age: "", + id: "", + }, + ]); + }; + const getHighlightedWords = (index, currentTime, word, start, end) => { return ( { } }; - useEffect(() => { - const handleKeyDown = (e) => { - if ( - e.which === 32 && - e.target.id !== "description" && - document.activeElement !== ref.current - ) { - e.preventDefault(); - var video = document.getElementById("myBtn"); - if (video.paused) { - video.play(); - } else { - video.pause(); - } - } - }; - window.addEventListener("keydown", handleKeyDown); - return () => { - window.removeEventListener("keydown", handleKeyDown); - }; - }, []); + // useEffect(() => { + // const handleKeyDown = (e) => { + // if ( + // e.which === 32 && + // e.target.id !== "description" && + // document.activeElement !== ref.current + // ) { + // e.preventDefault(); + // var video = document.getElementById("myBtn"); + // if (video.paused) { + // video.play(); + // } else { + // video.pause(); + // } + // } + // }; + // window.addEventListener("keydown", handleKeyDown); + // return () => { + // window.removeEventListener("keydown", handleKeyDown); + // }; + // }, []); const updateVideoHandler = async () => { const updateData = { gender: voice, description: videoDescription, video_id: videoDetails[0].id, + // multiple_speaker: speakerType !== 'individual', + multiple_speaker: String(speakerType !== 'individual'), + speaker_info: speakerInfo }; const apiObj = new UpdateVideoAPI(updateData); @@ -331,18 +388,7 @@ const VideoDialog = ({ open, handleClose, videoDetails }) => { marginBottom="20px" > - setVideoDescription(event.target.value)} - sx={{ mb: 3, mt: 3 }} - /> - - + Voice Selection + + setSpeakerType(event.target.value)} + > + } + label="Individual Speaker" + sx={{ + "& .MuiFormControlLabel-label": { fontSize: "18px" }, + }} + /> + + } + label="Multi Speaker" + sx={{ + "& .MuiFormControlLabel-label": { fontSize: "18px" }, + }} + /> + + {speakerType === "multiple" && ( + <> + {speakerInfo.map((item, index) => { + return ( + + } + id={`speakerInfo-accordion-child-${index}`} + > + + Speaker {index + 1} + + + + handleRemoveSpeaker(event, index)} + sx={{ marginLeft: "auto" }} + disabled={speakerInfo.length === 1} + color="error" + > + + + + + + {speakerFields.map((element, idx) => { + return ( + + {element.type === "text" ? ( + + handleSpeakerFieldChange(event, index) + } + sx={element.sx} + /> + ) : ( + + + {element.label} + + + + )} + + ); + })} + + + ); + })} + + + + )} + + setVideoDescription(event.target.value)} + sx={{ mb: 3, mt: 3 }} + /> - + {/* + */}
@@ -470,4 +651,4 @@ const VideoDialog = ({ open, handleClose, videoDetails }) => { ); }; -export default VideoDialog; +export default VideoDialog; \ No newline at end of file diff --git a/src/common/index.js b/src/common/index.js index af83e45c..d5f60ac6 100644 --- a/src/common/index.js +++ b/src/common/index.js @@ -11,6 +11,7 @@ import CreateVideoDialog from "./CreateVideoDialog"; import CustomMenuComponent from "./CustomMenuComponent"; import CustomSwitchDarkBackground from "./CustomSwitchDarkBackground"; import DeleteDialog from "./DeleteDialog"; +import TaskReopenDialog from "./TaskReopenDialog"; import DeleteMemberErrorDialog from "./DeleteMemberErrorDialog"; import ExportAllDialog from "./ExportAllDialog"; import ExportDialog from "./ExportDialog"; @@ -58,6 +59,7 @@ export { CustomMenuComponent, CustomSwitchDarkBackground, DeleteDialog, + TaskReopenDialog, DeleteMemberErrorDialog, ExportAllDialog, ExportDialog, diff --git a/src/config/apiendpoint.js b/src/config/apiendpoint.js index 92b7977c..eb96d4ea 100644 --- a/src/config/apiendpoint.js +++ b/src/config/apiendpoint.js @@ -14,6 +14,9 @@ const endpoints = { confirmResetPassword: "/users/auth/users/reset_password_confirm/", languages: "/users/languages/fetch/", userRoles: "/users/roles/", + newsletterSubscribe: "/newsletter/subscribe/", + newsletter: "/newsletter/", + preview: "/newsletter/preview/", //Video video: "/video/", diff --git a/src/config/tableColumns.js b/src/config/tableColumns.js index 8fe867cd..2b763130 100644 --- a/src/config/tableColumns.js +++ b/src/config/tableColumns.js @@ -500,14 +500,14 @@ export const taskQueueStatusColumns = [ ]; export const failInfoColumns = [ - { - name: "index", - label: "Id", - }, { name: "page_number", label: "Page Number", }, + { + name: "index", + label: "Id", + }, { name: "start_time", label: "Start Time", @@ -524,17 +524,21 @@ export const failInfoColumns = [ name: "target_text", label: "Target Text", }, + { + name: "issue_type", + label: "Issue Type", + }, ]; export const failTranscriptionInfoColumns = [ - { - name: "index", - label: "Id", - }, { name: "page_number", label: "Page Number", }, + { + name: "index", + label: "Id", + }, { name: "start_time", label: "Start Time", @@ -550,14 +554,14 @@ export const failTranscriptionInfoColumns = [ ]; export const voiceoverFailInfoColumns = [ - { - name: "index", - label: "Id", - }, { name: "page_number", label: "Page Number", }, + { + name: "index", + label: "Id", + }, { name: "reason", label: "Reason", diff --git a/src/containers/Admin/Dashboard.jsx b/src/containers/Admin/Dashboard.jsx index 8f3e7e36..ae5e44df 100644 --- a/src/containers/Admin/Dashboard.jsx +++ b/src/containers/Admin/Dashboard.jsx @@ -14,6 +14,7 @@ import AdminLevelReport from "./AdminLevelReport"; //Apis import { APITransport, AddOrganizationMemberAPI } from "redux/actions"; +import NewsLetter from "./NewsLetterTemplate"; const TabPanel = (props) => { const { children, value, index, ...other } = props; @@ -67,7 +68,10 @@ const DashBoard = () => { /> - + @@ -142,7 +146,18 @@ const DashBoard = () => { value={value} index={3} style={{ textAlign: "center", maxWidth: "100%" }} - > + > + +
+ +
+
+ {addUserDialog && ( diff --git a/src/containers/Admin/NewsLetterTemplate.jsx b/src/containers/Admin/NewsLetterTemplate.jsx new file mode 100644 index 00000000..d2997131 --- /dev/null +++ b/src/containers/Admin/NewsLetterTemplate.jsx @@ -0,0 +1,207 @@ +import { Grid, Select, MenuItem, FormControl, InputLabel, Box, TextField, Button } from "@mui/material"; +import { useCallback, useEffect, useState } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { APITransport, NewsletterTemplate } from "redux/actions"; +import CloudUploadIcon from '@mui/icons-material/CloudUpload'; +import { styled } from '@mui/material/styles'; +import NewsletterPreview from "redux/actions/api/Admin/NewsLetterPreview"; +import clearTemplatePreview from "redux/actions/api/Admin/ClearTemplatePreview"; + +const VisuallyHiddenInput = styled('input')({ + clip: 'rect(0 0 0 0)', + clipPath: 'inset(50%)', + height: 1, + overflow: 'hidden', + position: 'absolute', + bottom: 0, + left: 0, + whiteSpace: 'nowrap', + width: 1, +}); + + +const NewsLetter = () => { + const [selectedTemplate, setSelectedTemplate] = useState(null); + const [templateInfo, setTemplateInfo] = useState({ + 1: null, + 2: null, + 3: null + }) + const dispatch = useDispatch(); + + const { html } = useSelector(state => state.newsletterPreviewReducer); + + const handleTemplateChange = (e) => { + setTemplateInfo((prev) => ({ + ...prev, + 1: null, + 2: null, + 3: null + })) + setSelectedTemplate(e.target.value); + + }; + + const handleTemplateSubmit = () => { + const payload = { + submitter_id: 1, + content: selectedTemplate !== 3 ? [templateInfo?.[selectedTemplate]] : templateInfo?.[selectedTemplate], + category: "NEW_FEATURE", + template_id: selectedTemplate + } + const templateOneObj = new NewsletterTemplate(payload, selectedTemplate); + dispatch(APITransport(templateOneObj)); + }; + + const handleTemplatePreview = () => { + const payload = { + submitter_id: 1, + content: selectedTemplate !== 3 ? [templateInfo?.[selectedTemplate]] : templateInfo?.[selectedTemplate], + category: "NEW_FEATURE", + template_id: selectedTemplate + } + const templateOneObj = new NewsletterPreview(payload, selectedTemplate); + dispatch(APITransport(templateOneObj)); + }; + + const handleChange = (prop, value) => { + setTemplateInfo((prev) => ({ + ...prev, + [selectedTemplate]: { + ...prev[selectedTemplate], + [prop]: value, + }, + })); + }; + + useEffect(() => { + dispatch(clearTemplatePreview()); + }, [selectedTemplate]); + + function getBase64(file) { + return new Promise((resolve, reject) => { + var reader = new FileReader(); + reader.readAsDataURL(file); + + reader.onload = function () { + resolve(reader.result); + }; + + reader.onerror = function (error) { + reject(error); + }; + }); + } + + const templateOne = () => { + return + + handleChange("header", e.target.value)} /> + + +