feat: uploading skeletons
This commit is contained in:
parent
9b0454eab5
commit
95ae8c6a83
@ -69,26 +69,24 @@ export default function OptionsAndPicture({
|
|||||||
|
|
||||||
setPictureUploading(true);
|
setPictureUploading(true);
|
||||||
|
|
||||||
try {
|
const url = await uploadQuestionImage(
|
||||||
const url = await uploadQuestionImage(
|
question.id,
|
||||||
question.id,
|
quizQid,
|
||||||
quizQid,
|
file,
|
||||||
file,
|
(question, url) => {
|
||||||
(question, url) => {
|
if (!("variants" in question.content)) return;
|
||||||
if (!("variants" in question.content)) return;
|
|
||||||
|
|
||||||
const variant = question.content.variants.find(
|
const variant = question.content.variants.find(
|
||||||
(variant) => variant.id === selectedVariantId,
|
(variant) => variant.id === selectedVariantId,
|
||||||
);
|
);
|
||||||
if (!variant) return;
|
if (!variant) return;
|
||||||
|
|
||||||
variant.extendedText = url;
|
variant.extendedText = url;
|
||||||
variant.originalImageUrl = url;
|
variant.originalImageUrl = url;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
closeImageUploadModal();
|
closeImageUploadModal();
|
||||||
openCropModal(file, url);
|
openCropModal(file, url);
|
||||||
} catch {}
|
|
||||||
|
|
||||||
setPictureUploading(false);
|
setPictureUploading(false);
|
||||||
};
|
};
|
||||||
|
@ -63,27 +63,25 @@ export default function OptionsPicture({
|
|||||||
|
|
||||||
setPictureUploading(true);
|
setPictureUploading(true);
|
||||||
|
|
||||||
try {
|
const url = await uploadQuestionImage(
|
||||||
const url = await uploadQuestionImage(
|
question.id,
|
||||||
question.id,
|
quizQid,
|
||||||
quizQid,
|
file,
|
||||||
file,
|
(question, url) => {
|
||||||
(question, url) => {
|
if (!("variants" in question.content)) return;
|
||||||
if (!("variants" in question.content)) return;
|
|
||||||
|
|
||||||
const variant = question.content.variants.find(
|
const variant = question.content.variants.find(
|
||||||
(variant) => variant.id === selectedVariantId,
|
(variant) => variant.id === selectedVariantId,
|
||||||
);
|
);
|
||||||
if (!variant) return;
|
if (!variant) return;
|
||||||
|
|
||||||
variant.extendedText = url;
|
variant.extendedText = url;
|
||||||
variant.originalImageUrl = url;
|
variant.originalImageUrl = url;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
closeImageUploadModal();
|
closeImageUploadModal();
|
||||||
openCropModal(file, url);
|
openCropModal(file, url);
|
||||||
} catch {}
|
|
||||||
|
|
||||||
setPictureUploading(false);
|
setPictureUploading(false);
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
|
import { useState } from "react";
|
||||||
import { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
|
import { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
|
||||||
import { Box, ButtonBase, Typography, useTheme } from "@mui/material";
|
import { Box, Skeleton, Typography, useTheme } from "@mui/material";
|
||||||
import { updateQuestion, uploadQuestionImage } from "@root/questions/actions";
|
import { updateQuestion, uploadQuestionImage } from "@root/questions/actions";
|
||||||
import { useCurrentQuiz } from "@root/quizes/hooks";
|
import { useCurrentQuiz } from "@root/quizes/hooks";
|
||||||
import { CropModal, useCropModalState } from "@ui_kit/Modal/CropModal";
|
import { CropModal, useCropModalState } from "@ui_kit/Modal/CropModal";
|
||||||
@ -12,6 +13,7 @@ type UploadImageProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function UploadImage({ question }: UploadImageProps) {
|
export default function UploadImage({ question }: UploadImageProps) {
|
||||||
|
const [pictureUploding, setPictureUploading] = useState<boolean>(false);
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const quiz = useCurrentQuiz();
|
const quiz = useCurrentQuiz();
|
||||||
|
|
||||||
@ -29,29 +31,50 @@ export default function UploadImage({ question }: UploadImageProps) {
|
|||||||
>
|
>
|
||||||
Загрузить изображение
|
Загрузить изображение
|
||||||
</Typography>
|
</Typography>
|
||||||
<DropZone
|
{pictureUploding ? (
|
||||||
text={"5 MB максимум"}
|
<Skeleton variant="rounded" sx={{ height: "120px", width: "300px" }} />
|
||||||
heightImg={"110px"}
|
) : (
|
||||||
sx={{ maxWidth: "300px", width: "100%" }}
|
<DropZone
|
||||||
imageUrl={question.content.back}
|
text={"5 MB максимум"}
|
||||||
originalImageUrl={question.content.originalBack}
|
sx={{ maxWidth: "300px", width: "100%" }}
|
||||||
onImageUploadClick={(file) => {
|
imageUrl={question.content.back}
|
||||||
uploadQuestionImage(question.id, quiz.qid, file, (question, url) => {
|
originalImageUrl={question.content.originalBack}
|
||||||
question.content.back = url;
|
onImageUploadClick={async (file) => {
|
||||||
question.content.originalBack = url;
|
setPictureUploading(true);
|
||||||
});
|
|
||||||
}}
|
await uploadQuestionImage(
|
||||||
onDeleteClick={() => {
|
question.id,
|
||||||
updateQuestion(question.id, (question) => {
|
quiz.qid,
|
||||||
question.content.back = null;
|
file,
|
||||||
});
|
(question, url) => {
|
||||||
}}
|
question.content.back = url;
|
||||||
onImageSaveClick={(file) => {
|
question.content.originalBack = url;
|
||||||
uploadQuestionImage(question.id, quiz.qid, file, (question, url) => {
|
},
|
||||||
question.content.back = url;
|
);
|
||||||
});
|
|
||||||
}}
|
setPictureUploading(false);
|
||||||
/>
|
}}
|
||||||
|
onDeleteClick={() => {
|
||||||
|
updateQuestion(question.id, (question) => {
|
||||||
|
question.content.back = null;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
onImageSaveClick={async (file) => {
|
||||||
|
setPictureUploading(true);
|
||||||
|
|
||||||
|
await uploadQuestionImage(
|
||||||
|
question.id,
|
||||||
|
quiz.qid,
|
||||||
|
file,
|
||||||
|
(question, url) => {
|
||||||
|
question.content.back = url;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
setPictureUploading(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import {
|
|||||||
Select,
|
Select,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Typography,
|
Typography,
|
||||||
|
Skeleton,
|
||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
useTheme,
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
@ -75,6 +76,9 @@ export default function StartPageSettings() {
|
|||||||
const quiz = useCurrentQuiz();
|
const quiz = useCurrentQuiz();
|
||||||
const [formState, setFormState] = useState<"design" | "content">("design");
|
const [formState, setFormState] = useState<"design" | "content">("design");
|
||||||
const [mobileVersion, setMobileVersion] = useState(false);
|
const [mobileVersion, setMobileVersion] = useState(false);
|
||||||
|
const [faviconUploding, setFaviconUploading] = useState<boolean>(false);
|
||||||
|
const [backgroundUploding, setBackgroundUploading] = useState<boolean>(false);
|
||||||
|
const [logoUploding, setLogoUploading] = useState<boolean>(false);
|
||||||
|
|
||||||
if (!quiz) return null;
|
if (!quiz) return null;
|
||||||
|
|
||||||
@ -84,14 +88,20 @@ export default function StartPageSettings() {
|
|||||||
|
|
||||||
const designType = quiz?.config?.startpageType;
|
const designType = quiz?.config?.startpageType;
|
||||||
|
|
||||||
const favIconDropZoneElement = (
|
const favIconDropZoneElement = faviconUploding ? (
|
||||||
|
<Skeleton sx={{ width: "48px", height: "48px", transform: "none" }} />
|
||||||
|
) : (
|
||||||
<FaviconDropZone
|
<FaviconDropZone
|
||||||
imageUrl={quiz.config.startpage.favIcon}
|
imageUrl={quiz.config.startpage.favIcon}
|
||||||
onImageUploadClick={async (file) => {
|
onImageUploadClick={async (file) => {
|
||||||
|
setFaviconUploading(true);
|
||||||
const resizedImage = await resizeFavIcon(file);
|
const resizedImage = await resizeFavIcon(file);
|
||||||
uploadQuizImage(quiz.id, resizedImage, (quiz, url) => {
|
|
||||||
|
await uploadQuizImage(quiz.id, resizedImage, (quiz, url) => {
|
||||||
quiz.config.startpage.favIcon = url;
|
quiz.config.startpage.favIcon = url;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setFaviconUploading(false);
|
||||||
}}
|
}}
|
||||||
onDeleteClick={() => {
|
onDeleteClick={() => {
|
||||||
updateQuiz(quiz.id, (quiz) => {
|
updateQuiz(quiz.id, (quiz) => {
|
||||||
@ -330,30 +340,47 @@ export default function StartPageSettings() {
|
|||||||
>
|
>
|
||||||
Изображение
|
Изображение
|
||||||
</Typography>
|
</Typography>
|
||||||
<DropZone
|
{backgroundUploding ? (
|
||||||
value={"5 MB максимум"}
|
<Skeleton
|
||||||
sx={{ maxWidth: "300px" }}
|
sx={{
|
||||||
imageUrl={quiz.config.startpage.background.desktop}
|
width: "300px",
|
||||||
originalImageUrl={
|
height: "120px",
|
||||||
quiz.config.startpage.background.originalDesktop
|
transform: "none",
|
||||||
}
|
}}
|
||||||
onImageUploadClick={(file) => {
|
/>
|
||||||
uploadQuizImage(quiz.id, file, (quiz, url) => {
|
) : (
|
||||||
quiz.config.startpage.background.desktop = url;
|
<DropZone
|
||||||
quiz.config.startpage.background.originalDesktop = url;
|
text={"5 MB максимум"}
|
||||||
});
|
sx={{ maxWidth: "300px" }}
|
||||||
}}
|
imageUrl={quiz.config.startpage.background.desktop}
|
||||||
onImageSaveClick={(file) => {
|
originalImageUrl={
|
||||||
uploadQuizImage(quiz.id, file, (quiz, url) => {
|
quiz.config.startpage.background.originalDesktop
|
||||||
quiz.config.startpage.background.desktop = url;
|
}
|
||||||
});
|
onImageUploadClick={async (file) => {
|
||||||
}}
|
setBackgroundUploading(true);
|
||||||
onDeleteClick={() => {
|
await uploadQuizImage(quiz.id, file, (quiz, url) => {
|
||||||
updateQuiz(quiz.id, (quiz) => {
|
quiz.config.startpage.background.desktop = url;
|
||||||
quiz.config.startpage.background.desktop = null;
|
quiz.config.startpage.background.originalDesktop =
|
||||||
});
|
url;
|
||||||
}}
|
});
|
||||||
/>
|
|
||||||
|
setBackgroundUploading(false);
|
||||||
|
}}
|
||||||
|
onImageSaveClick={async (file) => {
|
||||||
|
setBackgroundUploading(true);
|
||||||
|
await uploadQuizImage(quiz.id, file, (quiz, url) => {
|
||||||
|
quiz.config.startpage.background.desktop = url;
|
||||||
|
});
|
||||||
|
|
||||||
|
setBackgroundUploading(false);
|
||||||
|
}}
|
||||||
|
onDeleteClick={() => {
|
||||||
|
updateQuiz(quiz.id, (quiz) => {
|
||||||
|
quiz.config.startpage.background.desktop = null;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<ModalSizeImage />
|
<ModalSizeImage />
|
||||||
@ -386,47 +413,68 @@ export default function StartPageSettings() {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<ButtonBase
|
{backgroundUploding ? (
|
||||||
component="label"
|
<Skeleton
|
||||||
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={{
|
sx={{
|
||||||
height: "48px",
|
|
||||||
width: "48px",
|
width: "48px",
|
||||||
|
height: "48px",
|
||||||
|
transform: "none",
|
||||||
|
margin: "20px 0",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</ButtonBase>
|
) : (
|
||||||
{quiz.config.startpage.background.video ? (
|
<>
|
||||||
<video
|
<ButtonBase
|
||||||
src={quiz.config.startpage.background.video}
|
component="label"
|
||||||
width="400"
|
sx={{
|
||||||
controls
|
justifyContent: "center",
|
||||||
/>
|
height: "48px",
|
||||||
) : null}
|
width: "48px",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
my: "20px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
onChange={async (event) => {
|
||||||
|
setBackgroundUploading(true);
|
||||||
|
const file = event.target.files?.[0];
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
await uploadQuizImage(
|
||||||
|
quiz.id,
|
||||||
|
file,
|
||||||
|
(quiz, url) => {
|
||||||
|
quiz.config.startpage.background.video = url;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
// setVideo(URL.createObjectURL(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
setBackgroundUploading(false);
|
||||||
|
}}
|
||||||
|
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
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{designType !== "centered" && (
|
{designType !== "centered" && (
|
||||||
@ -500,28 +548,44 @@ export default function StartPageSettings() {
|
|||||||
>
|
>
|
||||||
Логотип
|
Логотип
|
||||||
</Typography>
|
</Typography>
|
||||||
<DropZone
|
{logoUploding ? (
|
||||||
value={"5 MB максимум"}
|
<Skeleton
|
||||||
sx={{ maxWidth: "300px" }}
|
sx={{
|
||||||
imageUrl={quiz.config.startpage.logo}
|
width: "300px",
|
||||||
originalImageUrl={quiz.config.startpage.originalLogo}
|
height: "120px",
|
||||||
onImageUploadClick={(file) => {
|
transform: "none",
|
||||||
uploadQuizImage(quiz.id, file, (quiz, url) => {
|
}}
|
||||||
quiz.config.startpage.logo = url;
|
/>
|
||||||
quiz.config.startpage.originalLogo = url;
|
) : (
|
||||||
});
|
<DropZone
|
||||||
}}
|
text={"5 MB максимум"}
|
||||||
onImageSaveClick={(file) => {
|
sx={{ maxWidth: "300px" }}
|
||||||
uploadQuizImage(quiz.id, file, (quiz, url) => {
|
imageUrl={quiz.config.startpage.logo}
|
||||||
quiz.config.startpage.logo = url;
|
originalImageUrl={quiz.config.startpage.originalLogo}
|
||||||
});
|
onImageUploadClick={async (file) => {
|
||||||
}}
|
setLogoUploading(true);
|
||||||
onDeleteClick={() => {
|
await uploadQuizImage(quiz.id, file, (quiz, url) => {
|
||||||
updateQuiz(quiz.id, (quiz) => {
|
quiz.config.startpage.logo = url;
|
||||||
quiz.config.startpage.logo = null;
|
quiz.config.startpage.originalLogo = url;
|
||||||
});
|
});
|
||||||
}}
|
|
||||||
/>
|
setLogoUploading(false);
|
||||||
|
}}
|
||||||
|
onImageSaveClick={async (file) => {
|
||||||
|
setLogoUploading(true);
|
||||||
|
await uploadQuizImage(quiz.id, file, (quiz, url) => {
|
||||||
|
quiz.config.startpage.logo = url;
|
||||||
|
});
|
||||||
|
|
||||||
|
setLogoUploading(false);
|
||||||
|
}}
|
||||||
|
onDeleteClick={() => {
|
||||||
|
updateQuiz(quiz.id, (quiz) => {
|
||||||
|
quiz.config.startpage.logo = null;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Typography
|
<Typography
|
||||||
@ -567,28 +631,44 @@ export default function StartPageSettings() {
|
|||||||
>
|
>
|
||||||
Логотип
|
Логотип
|
||||||
</Typography>
|
</Typography>
|
||||||
<DropZone
|
{logoUploding ? (
|
||||||
value={"5 MB максимум"}
|
<Skeleton
|
||||||
sx={{ maxWidth: "300px" }}
|
sx={{
|
||||||
imageUrl={quiz.config.startpage.logo}
|
width: "300px",
|
||||||
originalImageUrl={quiz.config.startpage.originalLogo}
|
height: "120px",
|
||||||
onImageUploadClick={(file) => {
|
transform: "none",
|
||||||
uploadQuizImage(quiz.id, file, (quiz, url) => {
|
}}
|
||||||
quiz.config.startpage.logo = url;
|
/>
|
||||||
quiz.config.startpage.originalLogo = url;
|
) : (
|
||||||
});
|
<DropZone
|
||||||
}}
|
text={"5 MB максимум"}
|
||||||
onImageSaveClick={(file) => {
|
sx={{ maxWidth: "300px" }}
|
||||||
uploadQuizImage(quiz.id, file, (quiz, url) => {
|
imageUrl={quiz.config.startpage.logo}
|
||||||
quiz.config.startpage.logo = url;
|
originalImageUrl={quiz.config.startpage.originalLogo}
|
||||||
});
|
onImageUploadClick={async (file) => {
|
||||||
}}
|
setLogoUploading(true);
|
||||||
onDeleteClick={() => {
|
await uploadQuizImage(quiz.id, file, (quiz, url) => {
|
||||||
updateQuiz(quiz.id, (quiz) => {
|
quiz.config.startpage.logo = url;
|
||||||
quiz.config.startpage.logo = null;
|
quiz.config.startpage.originalLogo = url;
|
||||||
});
|
});
|
||||||
}}
|
|
||||||
/>
|
setLogoUploading(false);
|
||||||
|
}}
|
||||||
|
onImageSaveClick={async (file) => {
|
||||||
|
setLogoUploading(true);
|
||||||
|
await uploadQuizImage(quiz.id, file, (quiz, url) => {
|
||||||
|
quiz.config.startpage.logo = url;
|
||||||
|
});
|
||||||
|
|
||||||
|
setLogoUploading(false);
|
||||||
|
}}
|
||||||
|
onDeleteClick={() => {
|
||||||
|
updateQuiz(quiz.id, (quiz) => {
|
||||||
|
quiz.config.startpage.logo = null;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Typography
|
<Typography
|
||||||
|
@ -41,19 +41,17 @@ export const MediaSelectionAndDisplay: FC<Iprops> = ({ resultData }) => {
|
|||||||
async function handleImageUpload(file: File) {
|
async function handleImageUpload(file: File) {
|
||||||
setPictureUploading(true);
|
setPictureUploading(true);
|
||||||
|
|
||||||
try {
|
const url = await uploadQuestionImage(
|
||||||
const url = await uploadQuestionImage(
|
resultData.id,
|
||||||
resultData.id,
|
quizQid,
|
||||||
quizQid,
|
file,
|
||||||
file,
|
(question, url) => {
|
||||||
(question, url) => {
|
question.content.back = url;
|
||||||
question.content.back = url;
|
question.content.originalBack = url;
|
||||||
question.content.originalBack = url;
|
},
|
||||||
},
|
);
|
||||||
);
|
closeImageUploadModal();
|
||||||
closeImageUploadModal();
|
openCropModal(file, url);
|
||||||
openCropModal(file, url);
|
|
||||||
} catch {}
|
|
||||||
|
|
||||||
setPictureUploading(false);
|
setPictureUploading(false);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user