Merge branch 'fixes' into 'main'

Fixes

See merge request frontend/squiz!106
This commit is contained in:
Nastya 2024-01-04 19:46:35 +00:00
commit ae32cdf07b
15 changed files with 202 additions and 43 deletions

@ -3,7 +3,7 @@ import { Box, useMediaQuery, useTheme, Skeleton } from "@mui/material";
import { setQuizes, setCurrentStep } from "@root/quizes/actions"; import { setQuizes, setCurrentStep } from "@root/quizes/actions";
import { useCurrentQuiz } from "@root/quizes/hooks"; import { useCurrentQuiz } from "@root/quizes/hooks";
import { useQuizStore } from "@root/quizes/store"; import { useQuizStore } from "@root/quizes/store";
import Sidebar from "@ui_kit/Sidebar"; import Sidebar from "@ui_kit/Sidebar/Sidebar";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { SidebarMobile } from "../../ui_kit/Sidebar/SidebarMobile"; import { SidebarMobile } from "../../ui_kit/Sidebar/SidebarMobile";

@ -135,6 +135,11 @@ export const usePopper = ({
setModalQuestionParentContentId(item.id()); setModalQuestionParentContentId(item.id());
setOpenedModalQuestions(true); setOpenedModalQuestions(true);
}); });
layoutElement.addEventListener("ontouchend", () => {
//Узнаём грани, идущие от этой ноды
setModalQuestionParentContentId(item.id());
setOpenedModalQuestions(true);
});
layoutsContainer.current?.appendChild(layoutElement); layoutsContainer.current?.appendChild(layoutElement);
return layoutElement; return layoutElement;
@ -162,6 +167,9 @@ export const usePopper = ({
plusElement.addEventListener("mouseup", () => { plusElement.addEventListener("mouseup", () => {
setStartCreate(node.id()); setStartCreate(node.id());
}); });
plusElement.addEventListener("ontouchend", () => {
setStartCreate(node.id());
});
plusesContainer.current?.appendChild(plusElement); plusesContainer.current?.appendChild(plusElement);
@ -191,6 +199,9 @@ export const usePopper = ({
crossElement.addEventListener("mouseup", () => { crossElement.addEventListener("mouseup", () => {
setStartRemove(node.id()); setStartRemove(node.id());
}); });
crossElement.addEventListener("ontouchend", () => {
setStartRemove(node.id());
});
return crossElement; return crossElement;
}, },
@ -225,6 +236,9 @@ export const usePopper = ({
gearElement.addEventListener("mouseup", () => { gearElement.addEventListener("mouseup", () => {
updateOpenedModalSettingsId(item.id()); updateOpenedModalSettingsId(item.id());
}); });
gearElement.addEventListener("ontouchend", () => {
updateOpenedModalSettingsId(item.id());
});
console.log("собираюсь анализировать папашу"); console.log("собираюсь анализировать папашу");
console.log("Тип папаши ", parentQuestion.type); console.log("Тип папаши ", parentQuestion.type);

@ -13,6 +13,7 @@ import InfoIcon from "../../../assets/icons/InfoIcon";
import type { QuizQuestionText } from "../../../model/questionTypes/text"; import type { QuizQuestionText } from "../../../model/questionTypes/text";
import ButtonsOptions from "../ButtonsOptions"; import ButtonsOptions from "../ButtonsOptions";
import SwitchTextField from "./switchTextField"; import SwitchTextField from "./switchTextField";
import TooltipClickInfo from "@ui_kit/Toolbars/TooltipClickInfo";
interface Props { interface Props {
question: QuizQuestionText; question: QuizQuestionText;
@ -77,14 +78,20 @@ export default function OwnTextField({ question }: Props) {
> >
Пользователю будет дано поле для ввода значения Пользователю будет дано поле для ввода значения
</Typography> </Typography>
<Tooltip {isMobile ? (
title="Будет использоваться для ввода значения." <TooltipClickInfo
placement="top" title={"Будет использоваться для ввода значения."}
> />
<Box> ) : (
<InfoIcon /> <Tooltip
</Box> title="Будет использоваться для ввода значения."
</Tooltip> placement="top"
>
<Box>
<InfoIcon />
</Box>
</Tooltip>
)}
</Box> </Box>
</Box> </Box>
<ButtonsOptions <ButtonsOptions

@ -96,7 +96,7 @@ export default function QuestionsPage({
}} }}
sx={{ sx={{
position: "fixed", position: "fixed",
bottom: "140px", bottom: "103px",
}} }}
data-cy="create-question" data-cy="create-question"
> >

@ -84,6 +84,8 @@ export const StartPageViewPublication = ({ setVisualStartPage }: Props) => {
) : null ) : null
) : null; ) : null;
console.log(background)
return ( return (
<Paper <Paper
className="quiz-preview-draghandle" className="quiz-preview-draghandle"

@ -62,7 +62,7 @@ export default function QuizCard({
const params = new URLSearchParams(window.location.search); const params = new URLSearchParams(window.location.search);
const fromSquiz = params.get("action"); const fromSquiz = params.get("action");
if (fromSquiz === "fromhub") { if (fromSquiz === "fromhub") {
window.history.replaceState(null, '', "/list") window.history.replaceState(null, "", "/list");
pay(); pay();
} }
}, []); }, []);

@ -1,5 +1,5 @@
import { Header } from "@ui_kit/Header/Header"; import { Header } from "@ui_kit/Header/Header";
import Sidebar from "@ui_kit/Sidebar"; import Sidebar from "@ui_kit/Sidebar/Sidebar";
import Box from "@mui/material/Box"; import Box from "@mui/material/Box";
import { useTheme, useMediaQuery, IconButton } from "@mui/material"; import { useTheme, useMediaQuery, IconButton } from "@mui/material";
import HeaderFull from "@ui_kit/Header/HeaderFull"; import HeaderFull from "@ui_kit/Header/HeaderFull";

@ -14,7 +14,7 @@ import {
import { setQuizes, updateQuiz, setCurrentStep } from "@root/quizes/actions"; import { setQuizes, updateQuiz, setCurrentStep } from "@root/quizes/actions";
import { useCurrentQuiz } from "@root/quizes/hooks"; import { useCurrentQuiz } from "@root/quizes/hooks";
import { useQuizStore } from "@root/quizes/store"; import { useQuizStore } from "@root/quizes/store";
import Sidebar from "@ui_kit/Sidebar"; import Sidebar from "@ui_kit/Sidebar/Sidebar";
import Stepper from "@ui_kit/Stepper"; import Stepper from "@ui_kit/Stepper";
import SwitchStepPages from "@ui_kit/switchStepPages"; import SwitchStepPages from "@ui_kit/switchStepPages";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";

@ -6,16 +6,24 @@ import ArrowLeft from "@icons/ArrowLeftSP";
import LayoutCenteredIcon from "@icons/LayoutCenteredIcon"; import LayoutCenteredIcon from "@icons/LayoutCenteredIcon";
import LayoutExpandedIcon from "@icons/LayoutExpandedIcon"; import LayoutExpandedIcon from "@icons/LayoutExpandedIcon";
import LayoutStandartIcon from "@icons/LayoutStandartIcon"; import LayoutStandartIcon from "@icons/LayoutStandartIcon";
import UploadIcon from "../../assets/icons/UploadIcon";
import MobilePhoneIcon from "@icons/MobilePhoneIcon"; import MobilePhoneIcon from "@icons/MobilePhoneIcon";
import { QuizStartpageType } from "@model/quizSettings"; import { QuizStartpageType } from "@model/quizSettings";
import InfoIcon from "@icons/InfoIcon";
import UploadBox from "@ui_kit/UploadBox";
import { import {
Box, Box,
Button, Button,
ButtonBase,
Checkbox, Checkbox,
FormControl, FormControl,
FormControlLabel, FormControlLabel,
MenuItem, MenuItem,
Select, Select,
Tooltip,
Typography, Typography,
useMediaQuery, useMediaQuery,
useTheme, useTheme,
@ -294,6 +302,7 @@ export default function StartPageSettings() {
</SelectableButton> </SelectableButton>
</Box> </Box>
{quiz.config.startpage.background.type === "image" &&
<Box <Box
sx={{ sx={{
display: display:
@ -348,27 +357,67 @@ export default function StartPageSettings() {
<ModalSizeImage /> <ModalSizeImage />
</Box> </Box>
<Box }
sx={{
display:
quiz.config.startpage.background.type === "image"
? "none"
: "flex",
flexDirection: "column",
mt: "20px",
}}
>
<CustomTextField
placeholder="URL видео"
value={quiz.config.startpage.background.video ?? ""}
onChange={(e) =>
updateQuiz(quiz.id, (quiz) => {
quiz.config.startpage.background.video = e.target.value;
})
}
/>
</Box>
{quiz.config.startpage.background.type === "video" && <>
<Box
sx={{
display: "flex",
alignItems: "center",
gap: "7px",
mt: "20px",
mb: "14px",
}}
>
<Typography
sx={{ fontWeight: 500, color: theme.palette.grey3.main }}
>
Добавить видео
</Typography>
<Tooltip title="Можно загрузить видео." placement="top">
<Box>
<InfoIcon />
</Box>
</Tooltip>
</Box>
<ButtonBase
component="label"
sx={{ justifyContent: "center",
height: "48px",
width: "48px",
display: "flex",
alignItems: "center",
my: "20px"
}}
>
<input
onChange={(event) => {
const file = event.target.files?.[0];
if (file) {
uploadQuizImage(quiz.id, file, (quiz, url) => {
quiz.config.startpage.background.video = url;
});
// setVideo(URL.createObjectURL(file));
}
}}
hidden
accept=".mp4"
multiple
type="file"
/>
<UploadBox
icon={<UploadIcon />}
sx={{
height: "48px",
width: "48px",
}}
/>
</ButtonBase>
{quiz.config.startpage.background.video ? <video src={quiz.config.startpage.background.video} width="400" controls /> : null}
</>}
{designType !== "centered" && ( {designType !== "centered" && (
<> <>
<Typography <Typography

@ -7,7 +7,7 @@ import { quizSetupSteps } from "@model/quizSettings";
import { Box, IconButton, List, Typography, useTheme } from "@mui/material"; import { Box, IconButton, List, Typography, useTheme } from "@mui/material";
import { useQuizStore } from "@root/quizes/store"; import { useQuizStore } from "@root/quizes/store";
import { useState } from "react"; import { useState } from "react";
import MenuItem from "./MenuItem"; import MenuItem from "../MenuItem";
import { useCurrentQuiz } from "@root/quizes/hooks"; import { useCurrentQuiz } from "@root/quizes/hooks";
import { useLocation, useNavigate } from "react-router-dom"; import { useLocation, useNavigate } from "react-router-dom";
import { setCurrentStep } from "@root/quizes/actions"; import { setCurrentStep } from "@root/quizes/actions";

@ -18,10 +18,16 @@ import { Question } from "./icons/Question";
import { Settings } from "./icons/Settings"; import { Settings } from "./icons/Settings";
import { Pencil } from "./icons/Pencil"; import { Pencil } from "./icons/Pencil";
import { ArrowDown } from "./icons/ArrowDown"; import { ArrowDown } from "./icons/ArrowDown";
import Sidebar from "@ui_kit/Sidebar"; import Sidebar from "@ui_kit/Sidebar/Sidebar";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { updateQuiz } from "@root/quizes/actions"; import { updateQuiz } from "@root/quizes/actions";
import { useCurrentQuiz } from "@root/quizes/hooks"; import { useCurrentQuiz } from "@root/quizes/hooks";
import { LogoutButton } from "@ui_kit/LogoutButton";
import { ToTariffsButton } from "@ui_kit/Toolbars/ToTariffsButton";
import { logout } from "@api/auth";
import { enqueueSnackbar } from "notistack";
import { clearAuthToken } from "@frontend/kitui";
import { clearUserData } from "@root/user";
interface Iprops { interface Iprops {
open: boolean; open: boolean;
@ -45,10 +51,21 @@ export const SidebarMobile: FC<Iprops> = ({ open, changePage }) => {
const [inputOpen, setInputOpen] = useState<boolean>(false); const [inputOpen, setInputOpen] = useState<boolean>(false);
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const ref = useRef(null); const ref = useRef(null);
const navigate = useNavigate();
const handleClick = (event) => { const handleClick = (event) => {
setAnchorEl(anchorEl ? null : event.currentTarget); setAnchorEl(anchorEl ? null : event.currentTarget);
}; };
async function handleLogoutClick() {
const [, logoutError] = await logout();
if (logoutError) {
return enqueueSnackbar(logoutError);
}
clearAuthToken();
clearUserData();
navigate("/");
}
const clickInput = (event) => { const clickInput = (event) => {
if (ref.current && !ref.current.contains(event.target)) setInputOpen(false); if (ref.current && !ref.current.contains(event.target)) setInputOpen(false);
@ -149,7 +166,7 @@ export const SidebarMobile: FC<Iprops> = ({ open, changePage }) => {
<Box <Box
sx={{ sx={{
width: "100%", width: "100%",
justifyContent: "end", justifyContent: "space-between",
display: "flex", display: "flex",
marginTop: "20px", marginTop: "20px",
flexWrap: "wrap", flexWrap: "wrap",
@ -173,6 +190,24 @@ export const SidebarMobile: FC<Iprops> = ({ open, changePage }) => {
{/* {sidebarIcon}*/} {/* {sidebarIcon}*/}
{/* </Box>*/} {/* </Box>*/}
{/*))}*/} {/*))}*/}
<Box sx={{ display: "flex" }}>
<Box
sx={{
display: "flex",
ml: "auto",
gap: "15px",
}}
>
<LogoutButton
onClick={handleLogoutClick}
sx={{
backgroundColor: "transparent",
border: "1px solid #9A9AAF",
}}
/>
</Box>
<ToTariffsButton color={"#F2F3F7"} />
</Box>
<Box <Box
aria-describedby={id} aria-describedby={id}
onClick={handleClick} onClick={handleClick}

@ -1,6 +1,6 @@
import { Box, Modal, Popper } from "@mui/material"; import { Box, Modal, Popper } from "@mui/material";
import Sidebar from "@ui_kit/Sidebar"; import Sidebar from "@ui_kit/Sidebar/Sidebar";
type SidebarModalProps = { type SidebarModalProps = {
open: boolean; open: boolean;

@ -6,14 +6,16 @@ interface Props {
} }
export default function YoutubeEmbedIframe({ videoUrl, containerSX }: Props) { export default function YoutubeEmbedIframe({ videoUrl, containerSX }: Props) {
const extractYoutubeVideoId = const extractYoutubeVideoId =
/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/gi; /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/gi;
const videoId = extractYoutubeVideoId.exec(videoUrl)?.[1]; const videoId = extractYoutubeVideoId.exec(videoUrl)?.[1];
if (!videoId) return null; // if (!videoId) return null;
const embedUrl = `https://www.youtube.com/embed/${videoId}?controls=0&autoplay=1&modestbranding=0&showinfo=0&disablekb=1&mute=1&loop=1`; const embedUrl = `https://www.youtube.com/embed/${videoId}?controls=0&autoplay=1&modestbranding=0&showinfo=0&disablekb=1&mute=1&loop=1`;
// https://www.youtube.com/shorts/9VgqBPd6RPA // https://www.youtube.com/shorts/9VgqBPd6RPA
// https://www.youtube.com/watch?v=I2N8hTHhvGY // https://www.youtube.com/watch?v=I2N8hTHhvGY
console.log()
return ( return (
<Box <Box
sx={{ sx={{
@ -27,13 +29,25 @@ export default function YoutubeEmbedIframe({ videoUrl, containerSX }: Props) {
...containerSX, ...containerSX,
}} }}
> >
<iframe <Box
component="video"
sx={{
width: "100%",
height: "100%",
}}
autoPlay
muted
src={videoUrl}
/>
{/* <iframe
src={embedUrl} src={embedUrl}
title="YouTube video player" title="YouTube video player"
frameBorder="0" frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowFullScreen allowFullScreen
/> /> */}
</Box> </Box>
); );
} }

@ -1,10 +1,10 @@
import { Button } from "@mui/material"; import { Button } from "@mui/material";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
export const ToTariffsButton = () => { export const ToTariffsButton = (color?: string) => {
return ( return (
<Link to="/tariffs"> <Link to="/tariffs">
<Button>Пополнить</Button> <Button sx={{ color: color }}>Пополнить</Button>
</Link> </Link>
); );
}; };

@ -0,0 +1,38 @@
import { Button, ClickAwayListener, IconButton, Tooltip } from "@mui/material";
import InfoIcon from "@icons/InfoIcon";
import { useState } from "react";
export default function TooltipClickInfo({ title }: string) {
const [open, setOpen] = useState(false);
const handleTooltipClose = () => {
setOpen(false);
};
const handleTooltipOpen = () => {
setOpen(true);
};
return (
<>
<ClickAwayListener onClickAway={handleTooltipClose}>
<div>
<Tooltip
PopperProps={{
disablePortal: true,
}}
onClose={handleTooltipClose}
open={open}
disableFocusListener
disableHoverListener
disableTouchListener
title={title}
>
<IconButton onClick={handleTooltipOpen}>
<InfoIcon />
</IconButton>
</Tooltip>
</div>
</ClickAwayListener>
</>
);
}