diff --git a/src/shared/api/index.tsx b/src/shared/api/index.tsx index 1a803db..50970d9 100644 --- a/src/shared/api/index.tsx +++ b/src/shared/api/index.tsx @@ -6,7 +6,6 @@ const authInstance = axios.create({ }); authInstance.interceptors.request.use((config: InternalAxiosRequestConfig) => { - console.log(config); config.headers.Authorization = `Bearer ${localStorage.getItem("token")}`; config.headers["X-Language"] = languageStore.language ?? "ru"; return config; diff --git a/src/shared/modals/SelectMediaDialog/index.tsx b/src/shared/modals/SelectMediaDialog/index.tsx index 75f7a93..cd29f84 100644 --- a/src/shared/modals/SelectMediaDialog/index.tsx +++ b/src/shared/modals/SelectMediaDialog/index.tsx @@ -21,12 +21,13 @@ import { MediaViewer } from "@widgets"; interface SelectMediaDialogProps { open: boolean; // Corrected prop name onClose: () => void; - onSelectMedia: (media: { + onSelectMedia?: (media: { id: string; filename: string; media_name?: string; media_type: number; }) => void; // Renamed from onSelectArticle + onSelectForSightMedia?: (mediaId: string) => void; linkedMediaIds?: string[]; // Renamed from linkedArticleIds, assuming it refers to media already in use } @@ -35,6 +36,7 @@ export const SelectMediaDialog = observer( open, // Corrected prop name onClose, onSelectMedia, // Renamed prop + onSelectForSightMedia, linkedMediaIds = [], // Default to empty array if not provided, renamed }: SelectMediaDialogProps) => { const { media, getMedia } = mediaStore; @@ -55,7 +57,11 @@ export const SelectMediaDialog = observer( if (hoveredMediaId) { const mediaItem = media.find((m) => m.id === hoveredMediaId); if (mediaItem) { - onSelectMedia(mediaItem); + if (onSelectForSightMedia) { + onSelectForSightMedia(mediaItem.id); + } else if (onSelectMedia) { + onSelectMedia(mediaItem); + } } onClose(); } @@ -114,7 +120,11 @@ export const SelectMediaDialog = observer( key={mediaItem.id} onClick={() => setHoveredMediaId(mediaItem.id)} // Call onSelectMedia onDoubleClick={() => { - onSelectMedia(mediaItem); + if (onSelectForSightMedia) { + onSelectForSightMedia(mediaItem.id); + } else if (onSelectMedia) { + onSelectMedia(mediaItem); + } onClose(); }} sx={{ diff --git a/src/shared/modals/UploadMediaDialog/index.tsx b/src/shared/modals/UploadMediaDialog/index.tsx index 8b35bb8..b3daf7f 100644 --- a/src/shared/modals/UploadMediaDialog/index.tsx +++ b/src/shared/modals/UploadMediaDialog/index.tsx @@ -24,16 +24,22 @@ import { ModelViewer3D } from "@widgets"; interface UploadMediaDialogProps { open: boolean; onClose: () => void; - afterUpload: (media: { + afterUpload?: (media: { id: string; filename: string; media_name?: string; media_type: number; }) => void; + afterUploadSight?: (id: string) => void; } export const UploadMediaDialog = observer( - ({ open, onClose, afterUpload }: UploadMediaDialogProps) => { + ({ + open, + onClose, + afterUpload, + afterUploadSight, + }: UploadMediaDialogProps) => { const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const [success, setSuccess] = useState(false); @@ -103,7 +109,11 @@ export const UploadMediaDialog = observer( mediaName ); if (media) { - await afterUpload(media); + if (afterUploadSight) { + await afterUploadSight(media.id); + } else if (afterUpload) { + await afterUpload(media); + } } setSuccess(true); } catch (err) { diff --git a/src/shared/store/CreateSightStore/index.tsx b/src/shared/store/CreateSightStore/index.tsx index 227fcb4..d431a1a 100644 --- a/src/shared/store/CreateSightStore/index.tsx +++ b/src/shared/store/CreateSightStore/index.tsx @@ -22,7 +22,7 @@ type SightLanguageInfo = { media_type: number; }[]; }; - right: { heading: string; body: string }[]; + right: { id: number; heading: string; body: string; media: [] }[]; }; type SightCommonInfo = { @@ -90,19 +90,43 @@ class CreateSightStore { makeAutoObservable(this); } - createNewRightArticle = () => { - this.sight.ru.right.push({ + createNewRightArticle = async () => { + const articleId = await languageInstance("ru").post("/article", { heading: "Введите русский заголовок", body: "Введите русский текст", }); - this.sight.en.right.push({ + const { id } = articleId.data; + await languageInstance("en").patch(`/article/${id}`, { heading: "Enter the English heading", body: "Enter the English text", }); - this.sight.zh.right.push({ + await languageInstance("zh").patch(`/article/${id}`, { heading: "Введите китайский заголовок", body: "Введите китайский текст", }); + await authInstance.post(`/sight/${this.sight.id}/article`, { + article_id: id, + page_num: this.sight.ru.right.length + 1, + }); + + this.sight.ru.right.push({ + id: id, + heading: "Введите русский заголовок", + body: "Введите русский текст", + media: [], + }); + this.sight.en.right.push({ + id: id, + heading: "Enter the English heading", + body: "Enter the English text", + media: [], + }); + this.sight.zh.right.push({ + id: id, + heading: "Введите китайский заголовок", + body: "Введите китайский текст", + media: [], + }); }; updateLeftInfo = (language: Language, heading: string, body: string) => { @@ -444,6 +468,32 @@ class CreateSightStore { filename: media.filename, }); }; + + unlinkRightAritcle = async (id: number) => { + this.sight.ru.right = this.sight.ru.right.filter( + (article) => article.id !== id + ); + this.sight.en.right = this.sight.en.right.filter( + (article) => article.id !== id + ); + this.sight.zh.right = this.sight.zh.right.filter( + (article) => article.id !== id + ); + }; + + deleteRightArticle = async (id: number) => { + await authInstance.delete(`/article/${id}`); + + this.sight.ru.right = this.sight.ru.right.filter( + (article) => article.id !== id + ); + this.sight.en.right = this.sight.en.right.filter( + (article) => article.id !== id + ); + this.sight.zh.right = this.sight.zh.right.filter( + (article) => article.id !== id + ); + }; } export const createSightStore = new CreateSightStore(); diff --git a/src/shared/store/EditSightStore/index.tsx b/src/shared/store/EditSightStore/index.tsx index 37af665..f4436e7 100644 --- a/src/shared/store/EditSightStore/index.tsx +++ b/src/shared/store/EditSightStore/index.tsx @@ -11,7 +11,12 @@ export type SightLanguageInfo = { body: string; media: { id: string; media_type: number; filename: string }[]; }; - right: { heading: string; body: string }[]; + right: { + id: number; + heading: string; + body: string; + media: { id: string; media_type: number; filename: string }[]; + }[]; }; export type SightCommonInfo = { @@ -111,21 +116,42 @@ class EditSightStore { }; getRightArticles = async (id: number) => { - const responseRu = await languageInstance("ru").get(`/sight/${id}/article`); - const responseEn = await languageInstance("en").get(`/sight/${id}/article`); - const responseZh = await languageInstance("zh").get(`/sight/${id}/article`); + let responseRu = await languageInstance("ru").get(`/sight/${id}/article`); + let responseEn = await languageInstance("en").get(`/sight/${id}/article`); + let responseZh = await languageInstance("zh").get(`/sight/${id}/article`); + + // Function to fetch media for a given set of articles + const fetchMediaForArticles = async (articles: any[]) => { + const articlesWithMedia = []; + for (const article of articles) { + const responseMedia = await authInstance.get( + `/article/${article.id}/media` + ); + articlesWithMedia.push({ + ...article, + media: responseMedia.data, + }); + } + return articlesWithMedia; + }; + + // Fetch media for articles in each language + const ruArticlesWithMedia = await fetchMediaForArticles(responseRu.data); + const enArticlesWithMedia = await fetchMediaForArticles(responseEn.data); + const zhArticlesWithMedia = await fetchMediaForArticles(responseZh.data); const data = { ru: { - right: responseRu.data, + right: ruArticlesWithMedia, }, en: { - right: responseEn.data, + right: enArticlesWithMedia, }, zh: { - right: responseZh.data, + right: zhArticlesWithMedia, }, }; + runInAction(() => { this.sight = { ...this.sight, @@ -137,7 +163,6 @@ class EditSightStore { ...this.sight.en, right: data.en.right, }, - zh: { ...this.sight.zh, right: data.zh.right, @@ -279,8 +304,13 @@ class EditSightStore { left_article: createdLeftArticleId, }); - if (this.sight.common.left_article == 0) { - return; + for (const language of ["ru", "en", "zh"] as Language[]) { + for (const article of this.sight[language].right) { + await languageInstance(language).patch(`/article/${article.id}`, { + heading: article.heading, + body: article.body, + }); + } } // await languageInstance("ru").patch( @@ -375,6 +405,38 @@ class EditSightStore { ); }; + unlinkRightArticle = async (article_id: number) => { + await authInstance.delete(`/sight/${this.sight.common.id}/article`, { + data: { + article_id: article_id, + }, + }); + + this.sight.ru.right = this.sight.ru.right.filter( + (article) => article.id !== article_id + ); + this.sight.en.right = this.sight.en.right.filter( + (article) => article.id !== article_id + ); + this.sight.zh.right = this.sight.zh.right.filter( + (article) => article.id !== article_id + ); + }; + + deleteRightArticle = async (article_id: number) => { + this.sight.ru.right = this.sight.ru.right.filter( + (article) => article.id !== article_id + ); + this.sight.en.right = this.sight.en.right.filter( + (article) => article.id !== article_id + ); + this.sight.zh.right = this.sight.zh.right.filter( + (article) => article.id !== article_id + ); + + await authInstance.delete(`/article/${article_id}`); + }; + uploadMediaOpen = false; setUploadMediaOpen = (open: boolean) => { this.uploadMediaOpen = open; @@ -442,6 +504,168 @@ class EditSightStore { filename: media.filename, }); }; + + unlinkPreviewMedia = async () => { + this.sight.common.preview_media = null; + }; + + linkPreviewMedia = async (mediaId: string) => { + this.sight.common.preview_media = mediaId; + }; + + linkArticle = async (article_id: number) => { + const response = await languageInstance("ru").get(`/article/${article_id}`); + const responseEn = await languageInstance("en").get( + `/article/${article_id}` + ); + const responseZh = await languageInstance("zh").get( + `/article/${article_id}` + ); + const mediaIds = await authInstance.get(`/article/${article_id}/media`); + runInAction(() => { + this.sight.ru.right.push({ + id: article_id, + heading: response.data.heading, + body: response.data.body, + media: mediaIds.data, + }); + this.sight.en.right.push({ + id: article_id, + heading: responseEn.data.heading, + body: responseEn.data.body, + media: mediaIds.data, + }); + this.sight.zh.right.push({ + id: article_id, + heading: responseZh.data.heading, + body: responseZh.data.body, + media: mediaIds.data, + }); + }); + }; + + deleteRightArticleMedia = async (article_id: number, media_id: string) => { + await authInstance.delete(`/article/${article_id}/media`, { + data: { + media_id: media_id, + }, + }); + + this.sight.ru.right = this.sight.ru.right.map((article) => { + if (article.id === article_id) { + article.media = article.media.filter((media) => media.id !== media_id); + } + return article; + }); + + this.sight.en.right = this.sight.en.right.map((article) => { + if (article.id === article_id) { + article.media = article.media.filter((media) => media.id !== media_id); + } + return article; + }); + + this.sight.zh.right = this.sight.zh.right.map((article) => { + if (article.id === article_id) { + article.media = article.media.filter((media) => media.id !== media_id); + } + return article; + }); + }; + + createNewRightArticle = async () => { + const articleId = await languageInstance("ru").post("/article", { + heading: "Введите русский заголовок", + body: "Введите русский текст", + }); + const { id } = articleId.data; + await languageInstance("en").patch(`/article/${id}`, { + heading: "Enter the English heading", + body: "Enter the English text", + }); + await languageInstance("zh").patch(`/article/${id}`, { + heading: "Введите китайский заголовок", + body: "Введите китайский текст", + }); + await authInstance.post(`/sight/${this.sight.common.id}/article`, { + article_id: id, + page_num: this.sight.ru.right.length + 1, + }); + + this.sight.ru.right.push({ + id: id, + heading: "Введите русский заголовок", + body: "Введите русский текст", + media: [], + }); + this.sight.en.right.push({ + id: id, + heading: "Enter the English heading", + body: "Enter the English text", + media: [], + }); + this.sight.zh.right.push({ + id: id, + heading: "Введите китайский заголовок", + body: "Введите китайский текст", + media: [], + }); + }; + + createLinkWithRightArticle = async ( + media: { + id: string; + filename: string; + media_name?: string; + media_type: number; + }, + article_id: number + ) => { + await authInstance.post(`/article/${article_id}/media`, { + media_id: media.id, + media_order: 1, + }); + this.sight.ru.right = this.sight.ru.right.map((article) => { + if (article.id === article_id) { + article.media.unshift({ + id: media.id, + media_type: media.media_type, + filename: media.filename, + }); + } + return article; + }); + this.sight.en.right = this.sight.en.right.map((article) => { + if (article.id === article_id) { + article.media.unshift({ + id: media.id, + media_type: media.media_type, + filename: media.filename, + }); + } + return article; + }); + this.sight.zh.right = this.sight.zh.right.map((article) => { + if (article.id === article_id) { + article.media.unshift({ + id: media.id, + media_type: media.media_type, + filename: media.filename, + }); + } + return article; + }); + }; + + updateRightArticleInfo = ( + index: number, + language: Language, + heading: string, + body: string + ) => { + this.sight[language].right[index].heading = heading; + this.sight[language].right[index].body = body; + }; } export const editSightStore = new EditSightStore(); diff --git a/src/widgets/MediaAreaForSight/index.tsx b/src/widgets/MediaAreaForSight/index.tsx new file mode 100644 index 0000000..41f4015 --- /dev/null +++ b/src/widgets/MediaAreaForSight/index.tsx @@ -0,0 +1,107 @@ +import { Box, Button } from "@mui/material"; +import { editSightStore, SelectMediaDialog, UploadMediaDialog } from "@shared"; +import { Upload } from "lucide-react"; +import { observer } from "mobx-react-lite"; +import { useState, DragEvent, useRef } from "react"; + +export const MediaAreaForSight = observer( + ({ + onFilesDrop, // 👈 Проп для обработки загруженных файлов + onFinishUpload, + }: { + onFilesDrop?: (files: File[]) => void; + onFinishUpload?: (mediaId: string) => void; + }) => { + const [selectMediaDialogOpen, setSelectMediaDialogOpen] = useState(false); + const [uploadMediaDialogOpen, setUploadMediaDialogOpen] = useState(false); + const [isDragging, setIsDragging] = useState(false); + const fileInputRef = useRef(null); + const { setFileToUpload } = editSightStore; + + const handleDrop = (e: DragEvent) => { + e.preventDefault(); + e.stopPropagation(); + setIsDragging(false); + + const files = Array.from(e.dataTransfer.files); + if (files.length && onFilesDrop) { + setFileToUpload(files[0]); + } + + setUploadMediaDialogOpen(true); + }; + + const handleDragOver = (e: DragEvent) => { + e.preventDefault(); + setIsDragging(true); + }; + + const handleDragLeave = () => { + setIsDragging(false); + }; + + const handleClick = () => { + fileInputRef.current?.click(); + }; + + const handleFileSelect = (event: React.ChangeEvent) => { + const files = Array.from(event.target.files || []); + if (files.length && onFilesDrop) { + setFileToUpload(files[0]); + onFilesDrop(files); + setUploadMediaDialogOpen(true); + } + + // Сбрасываем значение input, чтобы можно было выбрать тот же файл снова + event.target.value = ""; + }; + + return ( + <> + + +
+
+ + Перетащите медиа файлы сюда или нажмите для выбора +
+
или
+ +
+
+ + setUploadMediaDialogOpen(false)} + afterUploadSight={onFinishUpload} + /> + setSelectMediaDialogOpen(false)} + onSelectForSightMedia={onFinishUpload} + /> + + ); + } +); diff --git a/src/widgets/SightTabs/CreateRightTab/index.tsx b/src/widgets/SightTabs/CreateRightTab/index.tsx index 97b4723..bc52c4f 100644 --- a/src/widgets/SightTabs/CreateRightTab/index.tsx +++ b/src/widgets/SightTabs/CreateRightTab/index.tsx @@ -7,7 +7,13 @@ import { MenuItem, TextField, } from "@mui/material"; -import { BackButton, createSightStore, languageStore, TabPanel } from "@shared"; +import { + BackButton, + createSightStore, + languageStore, + SelectArticleModal, + TabPanel, +} from "@shared"; import { LanguageSwitcher, ReactMarkdownComponent, @@ -16,6 +22,7 @@ import { import { ImagePlus, Plus } from "lucide-react"; import { observer } from "mobx-react-lite"; import { useState } from "react"; +import { MediaViewer } from "../../MediaViewer/index"; // --- RightWidgetTab (Parent) Component --- export const CreateRightTab = observer( @@ -24,10 +31,11 @@ export const CreateRightTab = observer( const { sight, createNewRightArticle, updateRightArticleInfo } = createSightStore; const { language } = languageStore; - + const [articleDialogOpen, setArticleDialogOpen] = useState(false); const [activeArticleIndex, setActiveArticleIndex] = useState( null ); + const [type, setType] = useState<"article" | "media">("media"); const open = Boolean(anchorEl); const handleClick = (event: React.MouseEvent) => { setAnchorEl(event.currentTarget); @@ -66,9 +74,9 @@ export const CreateRightTab = observer( { - // setMediaType("preview"); + setType("media"); }} - className="w-full bg-gray-200 p-4 rounded-2xl cursor-pointer text-sm hover:bg-gray-300 transition-all duration-300" + className="w-full bg-green-200 p-4 rounded-2xl cursor-pointer text-sm hover:bg-gray-300 transition-all duration-300" > Предпросмотр медиа @@ -79,6 +87,7 @@ export const CreateRightTab = observer( className="w-full bg-gray-200 p-4 rounded-2xl text-sm cursor-pointer hover:bg-gray-300 transition-all duration-300" onClick={() => { handleSelectArticle(index); + setType("article"); }} > {article.heading} @@ -113,6 +122,7 @@ export const CreateRightTab = observer( { + setArticleDialogOpen(true); handleClose(); }} > @@ -120,63 +130,65 @@ export const CreateRightTab = observer( - - {activeArticleIndex !== null && ( - <> - - + {type === "article" && ( + + {activeArticleIndex !== null && ( + <> + + - - - - {/* Левая колонка: Редактирование */} - - - - updateRightArticleInfo( - activeArticleIndex, - language, - e.target.value, - sight[language].right[activeArticleIndex].body - ) - } - variant="outlined" - fullWidth - /> - - - updateRightArticleInfo( - activeArticleIndex, - language, - sight[language].right[activeArticleIndex] - .heading, - value - ) - } - /> + - {/* Блок МЕДИА для статьи */} - {/* + + {/* Левая колонка: Редактирование */} + + + + updateRightArticleInfo( + activeArticleIndex, + language, + e.target.value, + sight[language].right[activeArticleIndex].body + ) + } + variant="outlined" + fullWidth + /> + + + updateRightArticleInfo( + activeArticleIndex, + language, + sight[language].right[activeArticleIndex] + .heading, + value + ) + } + /> + + {/* Блок МЕДИА для статьи */} + {/* МЕДИА @@ -241,10 +253,22 @@ export const CreateRightTab = observer( )} */} - - - )} - + + + )} + + )} + {type === "media" && ( + + + + )} @@ -264,7 +288,7 @@ export const CreateRightTab = observer( flexDirection: "column", }} > - {false ? ( + {type === "media" ? ( */} + setArticleDialogOpen(false)} + onSelectArticle={handleSelectArticle} + linkedArticleIds={sight[language].right.map((article) => article.id)} + /> ); } diff --git a/src/widgets/SightTabs/InformationTab/index.tsx b/src/widgets/SightTabs/InformationTab/index.tsx index cdcfcfb..d2cdacb 100644 --- a/src/widgets/SightTabs/InformationTab/index.tsx +++ b/src/widgets/SightTabs/InformationTab/index.tsx @@ -313,6 +313,7 @@ export const InformationTab = observer( /> + { const [anchorEl, setAnchorEl] = useState(null); - const { createNewRightArticle, updateRightArticleInfo } = createSightStore; - const { sight, getRightArticles, updateSight } = editSightStore; - const { language } = languageStore; + const { + sight, + updateRightArticleInfo, + getRightArticles, + updateSight, + unlinkPreviewMedia, + linkPreviewMedia, + unlinkRightArticle, + deleteRightArticle, + linkArticle, + deleteRightArticleMedia, + createLinkWithRightArticle, + setFileToUpload, + createNewRightArticle, + } = editSightStore; + + const [uploadMediaOpen, setUploadMediaOpen] = useState(false); + const { language } = languageStore; + const [type, setType] = useState<"article" | "media">("media"); useEffect(() => { - if (sight.common.id) { - getRightArticles(sight.common.id); - } + const fetchData = async () => { + if (sight.common.id) { + await getRightArticles(sight.common.id); + } + }; + fetchData(); + console.log(sight[language].right); }, [sight.common.id]); const [activeArticleIndex, setActiveArticleIndex] = useState( null ); const [isSelectModalOpen, setIsSelectModalOpen] = useState(false); - + const [isSelectMediaModalOpen, setIsSelectMediaModalOpen] = useState(false); const open = Boolean(anchorEl); + const handleClick = (event: React.MouseEvent) => { setAnchorEl(event.currentTarget); }; @@ -69,16 +95,32 @@ export const RightWidgetTab = observer( setIsSelectModalOpen(false); }; - const handleArticleSelect = () => { - // TODO: Implement article selection logic + const handleArticleSelect = (id: number) => { + linkArticle(id); handleCloseSelectModal(); }; + const handleMediaSelected = async (media: { + id: string; + filename: string; + media_name?: string; + media_type: number; + }) => { + await createLinkWithRightArticle( + media, + sight[language].right[activeArticleIndex || 0].id + ); + }; + const handleSave = async () => { await updateSight(); toast.success("Достопримечательность сохранена"); }; + useEffect(() => { + console.log(sight[language].right); + }, [sight[language].right]); + return ( @@ -99,23 +141,26 @@ export const RightWidgetTab = observer( - + setMediaType("preview")} - className="w-full bg-gray-200 p-4 rounded-2xl cursor-pointer text-sm hover:bg-gray-300 transition-all duration-300" + onClick={() => setType("media")} + className="w-full bg-green-200 p-4 rounded-2xl cursor-pointer text-sm hover:bg-gray-300 transition-all duration-300" > Предпросмотр медиа - - {sight[language].right.map((article, index) => ( - handleSelectArticle(index)} - > - {article.heading} - - ))} + {sight[language].right.length > 0 && + sight[language].right.map((article, index) => ( + { + handleSelectArticle(index); + setType("article"); + }} + > + {article.heading} + + ))} - - - - - - updateRightArticleInfo( - activeArticleIndex, - language, - e.target.value, - sight[language].right[activeArticleIndex].body - ) - } - variant="outlined" - fullWidth - /> - - - updateRightArticleInfo( - activeArticleIndex, - language, - sight[language].right[activeArticleIndex] - .heading, - value - ) - } - /> - {/* {}} - /> */} + {type === "article" && ( + + {activeArticleIndex !== null && ( + <> + + + - - - )} - + + + + updateRightArticleInfo( + activeArticleIndex, + language, + e.target.value, + sight[language].right[activeArticleIndex].body + ) + } + variant="outlined" + fullWidth + /> + + + updateRightArticleInfo( + activeArticleIndex, + language, + sight[language].right[activeArticleIndex] + .heading, + value + ) + } + /> + + { + setFileToUpload(files[0]); + setUploadMediaOpen(true); + }} + deleteMedia={deleteRightArticleMedia} + setSelectMediaDialogOpen={() => { + setIsSelectMediaModalOpen(true); + }} + /> + + + + )} + + )} + {type === "media" && ( + + {sight.common.preview_media && ( + <> + + + + + + + )} + {!sight.common.preview_media && ( + { + linkPreviewMedia(mediaId); + }} + onFilesDrop={() => {}} + /> + )} + + )} - - {activeArticleIndex !== null && ( - - + {activeArticleIndex !== null && ( + - - - - - - {sight[language].right[activeArticleIndex].heading || - "Выберите статью"} - - - - - {sight[language].right[activeArticleIndex].body ? ( - + 0 ? ( + ) : ( - - Предпросмотр статьи появится здесь - + + )} + + + + {sight[language].right[activeArticleIndex].heading || + "Выберите статью"} + + + + + {sight[language].right[activeArticleIndex].body ? ( + + ) : ( + + Предпросмотр статьи появится здесь + + )} + - - - )} - + + )} + + )} + setUploadMediaOpen(false)} + afterUpload={async (media) => { + setUploadMediaOpen(false); + setFileToUpload(null); + await createLinkWithRightArticle( + media, + sight[language].right[activeArticleIndex || 0].id + ); + }} + /> + + setIsSelectMediaModalOpen(false)} + onSelectMedia={handleMediaSelected} + /> ); } diff --git a/src/widgets/index.ts b/src/widgets/index.ts index 4ca557b..5c7cb56 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -10,3 +10,4 @@ export * from "./SightsTable"; export * from "./MediaViewer"; export * from "./MediaArea"; export * from "./ModelViewer3D"; +export * from "./MediaAreaForSight";