feat: fix sight edit
This commit is contained in:
		| @@ -1,5 +1,10 @@ | ||||
| import { Box, Tab, Tabs } from "@mui/material"; | ||||
| import { articlesStore, cityStore, languageStore } from "@shared"; | ||||
| import { | ||||
|   articlesStore, | ||||
|   cityStore, | ||||
|   createSightStore, | ||||
|   languageStore, | ||||
| } from "@shared"; | ||||
| import { | ||||
|   CreateInformationTab, | ||||
|   CreateLeftTab, | ||||
| @@ -22,13 +27,15 @@ export const CreateSightPage = observer(() => { | ||||
|   const [value, setValue] = useState(0); | ||||
|   const { getCities } = cityStore; | ||||
|   const { getArticles } = articlesStore; | ||||
|   const { needLeaveAgree } = createSightStore; | ||||
|  | ||||
|   const handleChange = (_: React.SyntheticEvent, newValue: number) => { | ||||
|     setValue(newValue); | ||||
|   }; | ||||
|  | ||||
|   let blocker = useBlocker( | ||||
|     ({ currentLocation, nextLocation }) => | ||||
|       true && currentLocation.pathname !== nextLocation.pathname | ||||
|       needLeaveAgree && currentLocation.pathname !== nextLocation.pathname | ||||
|   ); | ||||
|  | ||||
|   useEffect(() => { | ||||
|   | ||||
| @@ -20,7 +20,7 @@ function a11yProps(index: number) { | ||||
|  | ||||
| export const EditSightPage = observer(() => { | ||||
|   const [value, setValue] = useState(0); | ||||
|   const { sight, getSightInfo } = editSightStore; | ||||
|   const { sight, getSightInfo, needLeaveAgree } = editSightStore; | ||||
|   const { getArticles } = articlesStore; | ||||
|   const { language } = languageStore; | ||||
|   const { id } = useParams(); | ||||
| @@ -28,7 +28,7 @@ export const EditSightPage = observer(() => { | ||||
|  | ||||
|   let blocker = useBlocker( | ||||
|     ({ currentLocation, nextLocation }) => | ||||
|       true && currentLocation.pathname !== nextLocation.pathname | ||||
|       needLeaveAgree && currentLocation.pathname !== nextLocation.pathname | ||||
|   ); | ||||
|  | ||||
|   const handleChange = (_: React.SyntheticEvent, newValue: number) => { | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import { useEffect, useState } from "react"; | ||||
| import { observer } from "mobx-react-lite"; | ||||
| import { Pencil, Trash2 } from "lucide-react"; | ||||
| import { useNavigate } from "react-router-dom"; | ||||
| import { DeleteModal, LanguageSwitcher } from "@widgets"; | ||||
| import { CreateButton, DeleteModal, LanguageSwitcher } from "@widgets"; | ||||
|  | ||||
| export const SightListPage = observer(() => { | ||||
|   const { sights, getSights, deleteListSight } = sightsStore; | ||||
| @@ -69,6 +69,13 @@ export const SightListPage = observer(() => { | ||||
|       <LanguageSwitcher /> | ||||
|  | ||||
|       <div className="w-full"> | ||||
|         <div className="flex justify-between items-center mb-10"> | ||||
|           <h1 className="text-2xl">Достопримечательности</h1> | ||||
|           <CreateButton | ||||
|             label="Создать достопримечательность" | ||||
|             path="/sight/create" | ||||
|           /> | ||||
|         </div> | ||||
|         <DataGrid | ||||
|           rows={rows} | ||||
|           columns={columns} | ||||
|   | ||||
| @@ -202,87 +202,100 @@ export const SelectArticleModal = observer( | ||||
|               )} | ||||
|             </List> | ||||
|           </Paper> | ||||
|           <Paper | ||||
|             elevation={3} | ||||
|             sx={{ | ||||
|               width: "100%", | ||||
|               minWidth: 320, | ||||
|               maxWidth: 310, | ||||
|  | ||||
|               background: | ||||
|                 "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||
|  | ||||
|               padding: 0, | ||||
|               margin: "0px auto", | ||||
|               display: "flex", | ||||
|               flexDirection: "column", | ||||
|             }} | ||||
|           > | ||||
|             <Box | ||||
|           <Box className="max-h-[80%] overflow-y-scroll mx-auto rounded-[10px]"> | ||||
|             <Paper | ||||
|               elevation={3} | ||||
|               sx={{ | ||||
|                 width: "100%", | ||||
|                 height: 175, | ||||
|                 display: "flex", | ||||
|                 alignItems: "center", | ||||
|                 justifyContent: "center", | ||||
|                 padding: "3px", | ||||
|               }} | ||||
|             > | ||||
|               {articlesStore.articleMedia ? ( | ||||
|                 <MediaViewer | ||||
|                   media={{ | ||||
|                     id: articlesStore.articleMedia.id, | ||||
|                     media_type: articlesStore.articleMedia.media_type, | ||||
|                     filename: articlesStore.articleMedia.filename, | ||||
|                   }} | ||||
|                 /> | ||||
|               ) : ( | ||||
|                 <ImagePlus size={48} color="white" /> | ||||
|               )} | ||||
|             </Box> | ||||
|                 minWidth: 320, | ||||
|                 maxWidth: 310, | ||||
|  | ||||
|             <Box | ||||
|               sx={{ | ||||
|                 background: | ||||
|                   "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||
|                 color: "white", | ||||
|                 margin: "5px 0px 5px 0px", | ||||
|  | ||||
|                 padding: 0, | ||||
|                 margin: "0px auto", | ||||
|                 display: "flex", | ||||
|                 flexDirection: "column", | ||||
|                 gap: 1, | ||||
|                 padding: 1, | ||||
|               }} | ||||
|             > | ||||
|               <Typography | ||||
|                 variant="h5" | ||||
|                 component="h2" | ||||
|                 sx={{ | ||||
|                   wordBreak: "break-word", | ||||
|                   fontSize: "24px", | ||||
|                   fontWeight: 700, | ||||
|                   lineHeight: "120%", | ||||
|                 }} | ||||
|               > | ||||
|                 {articlesStore.articleData?.heading || "Название cтатьи"} | ||||
|               </Typography> | ||||
|             </Box> | ||||
|  | ||||
|             {articlesStore.articleData?.body && ( | ||||
|               <Box | ||||
|                 sx={{ | ||||
|                   padding: 1, | ||||
|                   maxHeight: "200px", | ||||
|                   overflowY: "scroll", | ||||
|                   background: | ||||
|                     "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||
|                   overflow: "hidden", | ||||
|                   width: "100%", | ||||
|                   minHeight: 100, | ||||
|                   padding: "3px", | ||||
|                   display: "flex", | ||||
|  | ||||
|                   alignItems: "center", | ||||
|                   justifyContent: "center", | ||||
|  | ||||
|                   "& img": { | ||||
|                     borderTopLeftRadius: "10px", | ||||
|                     borderTopRightRadius: "10px", | ||||
|                     width: "100%", | ||||
|                     height: "auto", | ||||
|                     objectFit: "contain", | ||||
|                   }, | ||||
|                 }} | ||||
|               > | ||||
|                 <ReactMarkdownComponent | ||||
|                   value={articlesStore.articleData?.body || "Описание"} | ||||
|                 /> | ||||
|                 {articlesStore.articleMedia ? ( | ||||
|                   <MediaViewer | ||||
|                     media={{ | ||||
|                       id: articlesStore.articleMedia.id, | ||||
|                       media_type: articlesStore.articleMedia.media_type, | ||||
|                       filename: articlesStore.articleMedia.filename, | ||||
|                     }} | ||||
|                     fullWidth={true} | ||||
|                   /> | ||||
|                 ) : ( | ||||
|                   <ImagePlus size={48} color="white" /> | ||||
|                 )} | ||||
|               </Box> | ||||
|             )} | ||||
|           </Paper> | ||||
|  | ||||
|               <Box | ||||
|                 sx={{ | ||||
|                   background: | ||||
|                     "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||
|                   color: "white", | ||||
|                   margin: "5px 0px 5px 0px", | ||||
|                   display: "flex", | ||||
|                   flexDirection: "column", | ||||
|                   gap: 1, | ||||
|                   padding: 1, | ||||
|                 }} | ||||
|               > | ||||
|                 <Typography | ||||
|                   variant="h5" | ||||
|                   component="h2" | ||||
|                   sx={{ | ||||
|                     wordBreak: "break-word", | ||||
|                     fontSize: "24px", | ||||
|                     fontWeight: 700, | ||||
|                     lineHeight: "120%", | ||||
|                   }} | ||||
|                 > | ||||
|                   {articlesStore.articleData?.heading || "Название cтатьи"} | ||||
|                 </Typography> | ||||
|               </Box> | ||||
|  | ||||
|               {articlesStore.articleData?.body && ( | ||||
|                 <Box | ||||
|                   sx={{ | ||||
|                     padding: 1, | ||||
|                     maxHeight: "200px", | ||||
|                     overflowY: "scroll", | ||||
|                     background: | ||||
|                       "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||
|                   }} | ||||
|                 > | ||||
|                   <ReactMarkdownComponent | ||||
|                     value={articlesStore.articleData?.body || "Описание"} | ||||
|                   /> | ||||
|                 </Box> | ||||
|               )} | ||||
|             </Paper> | ||||
|           </Box> | ||||
|         </DialogContent> | ||||
|         <DialogActions sx={{ p: 2 }}> | ||||
|           <Button onClick={onClose}>Отмена</Button> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { MEDIA_TYPE_LABELS, editSightStore } from "@shared"; | ||||
| import { MEDIA_TYPE_LABELS, MEDIA_TYPE_VALUES, editSightStore } from "@shared"; | ||||
| import { observer } from "mobx-react-lite"; | ||||
| import { useEffect, useState } from "react"; | ||||
| import { | ||||
| @@ -31,6 +31,7 @@ interface UploadMediaDialogProps { | ||||
|     media_type: number; | ||||
|   }) => void; | ||||
|   afterUploadSight?: (id: string) => void; | ||||
|   hardcodeType?: "thumbnail" | "watermark_lu" | "watermark_rd" | null; | ||||
| } | ||||
|  | ||||
| export const UploadMediaDialog = observer( | ||||
| @@ -39,6 +40,7 @@ export const UploadMediaDialog = observer( | ||||
|     onClose, | ||||
|     afterUpload, | ||||
|     afterUploadSight, | ||||
|     hardcodeType, | ||||
|   }: UploadMediaDialogProps) => { | ||||
|     const [isLoading, setIsLoading] = useState(false); | ||||
|     const [error, setError] = useState<string | null>(null); | ||||
| @@ -165,10 +167,12 @@ export const UploadMediaDialog = observer( | ||||
|               <FormControl fullWidth sx={{ width: "50%" }}> | ||||
|                 <InputLabel>Тип медиа</InputLabel> | ||||
|                 <Select | ||||
|                   value={mediaType} | ||||
|                   value={ | ||||
|                     hardcodeType ? MEDIA_TYPE_VALUES[hardcodeType] : mediaType | ||||
|                   } | ||||
|                   disabled={!!hardcodeType} | ||||
|                   label="Тип медиа" | ||||
|                   onChange={(e) => setMediaType(Number(e.target.value))} | ||||
|                   disabled={isLoading} | ||||
|                 > | ||||
|                   {availableMediaTypes.map((type) => ( | ||||
|                     <MenuItem key={type} value={type}> | ||||
|   | ||||
| @@ -98,18 +98,22 @@ class CreateSightStore { | ||||
|       heading: "New Heading (EN)", | ||||
|       body: "New Text (EN)", | ||||
|     }; | ||||
|     const articleZhData = { heading: "新标题 (ZH)", body: "新文本 (ZH)" }; | ||||
|     const articleZhData = { | ||||
|       heading: "Новый заголовок (ZH)", | ||||
|       body: "Новый текст (ZH)", | ||||
|     }; | ||||
|  | ||||
|     try { | ||||
|       const articleRes = await languageInstance("ru").post( | ||||
|         "/article", | ||||
|         articleRuData | ||||
|       ); | ||||
|       this.needLeaveAgree = true; | ||||
|       const articleRes = await authInstance.post("/article", { | ||||
|         translation: { | ||||
|           ru: articleRuData, | ||||
|           en: articleEnData, | ||||
|           zh: articleZhData, | ||||
|         }, | ||||
|       }); | ||||
|       const { id } = articleRes.data; // New article's ID | ||||
|  | ||||
|       await languageInstance("en").patch(`/article/${id}`, articleEnData); | ||||
|       await languageInstance("zh").patch(`/article/${id}`, articleZhData); | ||||
|  | ||||
|       runInAction(() => { | ||||
|         const newArticleEntry = { id, media: [] }; | ||||
|         this.sight.ru.right.push({ ...newArticleEntry, ...articleRuData }); | ||||
| @@ -376,6 +380,7 @@ class CreateSightStore { | ||||
|  | ||||
|   // --- General Store Methods --- | ||||
|   clearCreateSight = () => { | ||||
|     this.needLeaveAgree = false; | ||||
|     this.sight = JSON.parse(JSON.stringify(initialSightState)); // Reset to initial | ||||
|   }; | ||||
|  | ||||
| @@ -383,6 +388,7 @@ class CreateSightStore { | ||||
|     content: Partial<SightLanguageInfo | SightCommonInfo>, // Corrected types | ||||
|     language?: Language | ||||
|   ) => { | ||||
|     this.needLeaveAgree = true; | ||||
|     if (language) { | ||||
|       this.sight[language] = { ...this.sight[language], ...content }; | ||||
|     } else { | ||||
| @@ -587,10 +593,31 @@ class CreateSightStore { | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   updateRightArticles = async (articles: any[], language: Language) => { | ||||
|     runInAction(() => { | ||||
|       this.sight[language].right = articles; | ||||
|     }); | ||||
|   updateRightArticles = async (articles: any[]) => { | ||||
|     const articlesIds = articles.map((article) => article.id); | ||||
|  | ||||
|     const sortArticles = (existing: any[]) => { | ||||
|       const articleMap = new Map( | ||||
|         existing.map((article) => [article.id, article]) | ||||
|       ); | ||||
|       return articlesIds | ||||
|         .map((id) => articleMap.get(id)) | ||||
|         .filter( | ||||
|           (article): article is (typeof existing)[number] => | ||||
|             article !== undefined | ||||
|         ); | ||||
|     }; | ||||
|  | ||||
|     this.sight.ru.right = sortArticles(this.sight.ru.right); | ||||
|     this.sight.en.right = sortArticles(this.sight.en.right); | ||||
|     this.sight.zh.right = sortArticles(this.sight.zh.right); // теперь zh тоже сортируется одинаково | ||||
|  | ||||
|     this.needLeaveAgree = true; | ||||
|   }; | ||||
|  | ||||
|   needLeaveAgree = false; | ||||
|   setNeedLeaveAgree = (need: boolean) => { | ||||
|     this.needLeaveAgree = need; | ||||
|   }; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -170,6 +170,7 @@ class EditSightStore { | ||||
|   }; | ||||
|  | ||||
|   clearSightInfo = () => { | ||||
|     this.needLeaveAgree = false; | ||||
|     this.sight = { | ||||
|       common: { | ||||
|         id: 0, | ||||
| @@ -215,6 +216,7 @@ class EditSightStore { | ||||
|     content: Partial<SightLanguageInfo | SightCommonInfo>, | ||||
|     common: boolean = false | ||||
|   ) => { | ||||
|     this.needLeaveAgree = true; | ||||
|     if (common) { | ||||
|       this.sight.common = { | ||||
|         ...this.sight.common, | ||||
| @@ -262,61 +264,72 @@ class EditSightStore { | ||||
|       this.sight.common.left_article != 0 && | ||||
|       this.sight.common.left_article != null | ||||
|     ) { | ||||
|       await languageInstance("ru").patch( | ||||
|         `/article/${this.sight.common.left_article}`, | ||||
|         { | ||||
|           heading: this.sight.ru.left.heading, | ||||
|           body: this.sight.ru.left.body, | ||||
|         } | ||||
|       ); | ||||
|       await languageInstance("en").patch( | ||||
|         `/article/${this.sight.common.left_article}`, | ||||
|         { | ||||
|           heading: this.sight.en.left.heading, | ||||
|           body: this.sight.en.left.body, | ||||
|         } | ||||
|       ); | ||||
|  | ||||
|       await languageInstance("zh").patch( | ||||
|         `/article/${this.sight.common.left_article}`, | ||||
|         { | ||||
|           heading: this.sight.zh.left.heading, | ||||
|           body: this.sight.zh.left.body, | ||||
|         } | ||||
|       ); | ||||
|       await authInstance.patch(`/article/${this.sight.common.left_article}`, { | ||||
|         translation: { | ||||
|           ru: { | ||||
|             heading: this.sight.ru.left.heading, | ||||
|             body: this.sight.ru.left.body, | ||||
|           }, | ||||
|           en: { | ||||
|             heading: this.sight.en.left.heading, | ||||
|             body: this.sight.en.left.body, | ||||
|           }, | ||||
|           zh: { | ||||
|             heading: this.sight.zh.left.heading, | ||||
|             body: this.sight.zh.left.body, | ||||
|           }, | ||||
|         }, | ||||
|       }); | ||||
|     } | ||||
|  | ||||
|     await languageInstance("ru").patch(`/sight/${this.sight.common.id}`, { | ||||
|     await authInstance.patch(`/sight/${this.sight.common.id}`, { | ||||
|       ...this.sight.common, | ||||
|       name: this.sight.ru.name, | ||||
|       address: this.sight.ru.address, | ||||
|       left_article: createdLeftArticleId, | ||||
|     }); | ||||
|     await languageInstance("en").patch(`/sight/${this.sight.common.id}`, { | ||||
|       ...this.sight.common, | ||||
|       name: this.sight.en.name, | ||||
|       address: this.sight.en.address, | ||||
|       left_article: createdLeftArticleId, | ||||
|     }); | ||||
|     await languageInstance("zh").patch(`/sight/${this.sight.common.id}`, { | ||||
|       ...this.sight.common, | ||||
|       name: this.sight.zh.name, | ||||
|       address: this.sight.zh.address, | ||||
|       left_article: createdLeftArticleId, | ||||
|       translation: { | ||||
|         ru: { | ||||
|           name: this.sight.ru.name, | ||||
|           address: this.sight.ru.address, | ||||
|         }, | ||||
|         en: { | ||||
|           name: this.sight.en.name, | ||||
|           address: this.sight.en.address, | ||||
|         }, | ||||
|         zh: { | ||||
|           name: this.sight.zh.name, | ||||
|           address: this.sight.zh.address, | ||||
|         }, | ||||
|       }, | ||||
|     }); | ||||
|  | ||||
|     for (const language of ["ru", "en", "zh"] as Language[]) { | ||||
|       for (const article of this.sight[language].right) { | ||||
|         if (article.id == 0 || article.id == null) { | ||||
|           continue; | ||||
|         } | ||||
|         await languageInstance(language).patch(`/article/${article.id}`, { | ||||
|           heading: article.heading, | ||||
|           body: article.body, | ||||
|         }); | ||||
|     for (const article of this.sight.ru.right) { | ||||
|       if (article.id == 0 || article.id == null) { | ||||
|         continue; | ||||
|       } | ||||
|       await authInstance.patch(`/article/${article.id}`, { | ||||
|         translation: { | ||||
|           ru: { | ||||
|             heading: article.heading, | ||||
|             body: article.body, | ||||
|           }, | ||||
|           en: { | ||||
|             heading: article.heading, | ||||
|             body: article.body, | ||||
|           }, | ||||
|           zh: { | ||||
|             heading: article.heading, | ||||
|             body: article.body, | ||||
|           }, | ||||
|         }, | ||||
|       }); | ||||
|     } | ||||
|  | ||||
|     const articleIdsInObject = this.sight.ru.right.map((article) => ({ | ||||
|       id: article.id, | ||||
|     })); | ||||
|  | ||||
|     await authInstance.post(`/sight/${this.sight.common.id}/article/order`, { | ||||
|       articles: articleIdsInObject, | ||||
|     }); | ||||
|  | ||||
|     // await languageInstance("ru").patch( | ||||
|     //   `/sight/${this.sight.common.left_article}/article`, | ||||
|     //   { | ||||
| @@ -578,19 +591,27 @@ class EditSightStore { | ||||
|   }; | ||||
|  | ||||
|   createNewRightArticle = async () => { | ||||
|     const articleId = await languageInstance("ru").post("/article", { | ||||
|       heading: "Введите русский заголовок", | ||||
|       body: "Введите русский текст", | ||||
|     const articleRuData = { | ||||
|       heading: "Новый заголовок (RU)", | ||||
|       body: "Новый текст (RU)", | ||||
|     }; | ||||
|     const articleEnData = { | ||||
|       heading: "New Heading (EN)", | ||||
|       body: "New Text (EN)", | ||||
|     }; | ||||
|     const articleZhData = { | ||||
|       heading: "Новый заголовок (ZH)", | ||||
|       body: "Новый текст (ZH)", | ||||
|     }; | ||||
|     const articleId = await authInstance.post("/article", { | ||||
|       translation: { | ||||
|         ru: articleRuData, | ||||
|         en: articleEnData, | ||||
|         zh: articleZhData, | ||||
|       }, | ||||
|     }); | ||||
|     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, | ||||
| @@ -598,20 +619,20 @@ class EditSightStore { | ||||
|  | ||||
|     this.sight.ru.right.push({ | ||||
|       id: id, | ||||
|       heading: "Введите русский заголовок", | ||||
|       body: "Введите русский текст", | ||||
|       heading: articleRuData.heading, | ||||
|       body: articleRuData.body, | ||||
|       media: [], | ||||
|     }); | ||||
|     this.sight.en.right.push({ | ||||
|       id: id, | ||||
|       heading: "Enter the English heading", | ||||
|       body: "Enter the English text", | ||||
|       heading: articleEnData.heading, | ||||
|       body: articleEnData.body, | ||||
|       media: [], | ||||
|     }); | ||||
|     this.sight.zh.right.push({ | ||||
|       id: id, | ||||
|       heading: "Введите китайский заголовок", | ||||
|       body: "Введите китайский текст", | ||||
|       heading: articleZhData.heading, | ||||
|       body: articleZhData.body, | ||||
|       media: [], | ||||
|     }); | ||||
|   }; | ||||
| @@ -671,14 +692,31 @@ class EditSightStore { | ||||
|     this.sight[language].right[index].body = body; | ||||
|   }; | ||||
|  | ||||
|   updateRightArticles = async (articles: any[], language: Language) => { | ||||
|     this.sight[language].right = articles; | ||||
|     const articleIdsInObject = articles.map((article) => ({ | ||||
|       id: article.id, | ||||
|     })); | ||||
|     await authInstance.post(`/sight/${this.sight.common.id}/article/order`, { | ||||
|       articles: articleIdsInObject, | ||||
|     }); | ||||
|   updateRightArticles = async (articles: any[]) => { | ||||
|     const articlesIds = articles.map((article) => article.id); | ||||
|  | ||||
|     const sortArticles = (existing: any[]) => { | ||||
|       const articleMap = new Map( | ||||
|         existing.map((article) => [article.id, article]) | ||||
|       ); | ||||
|       return articlesIds | ||||
|         .map((id) => articleMap.get(id)) | ||||
|         .filter( | ||||
|           (article): article is (typeof existing)[number] => | ||||
|             article !== undefined | ||||
|         ); | ||||
|     }; | ||||
|  | ||||
|     this.sight.ru.right = sortArticles(this.sight.ru.right); | ||||
|     this.sight.en.right = sortArticles(this.sight.en.right); | ||||
|     this.sight.zh.right = sortArticles(this.sight.zh.right); // теперь zh тоже сортируется одинаково | ||||
|  | ||||
|     this.needLeaveAgree = true; | ||||
|   }; | ||||
|  | ||||
|   needLeaveAgree = false; | ||||
|   setNeedLeaveAgree = (need: boolean) => { | ||||
|     this.needLeaveAgree = need; | ||||
|   }; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| import React, { useRef, useState, DragEvent, useEffect } from "react"; | ||||
| import { Paper, Box, Typography, Button, Tooltip } from "@mui/material"; | ||||
| import { X, Info, MousePointer } from "lucide-react"; // Assuming lucide-react for icons | ||||
| import { X, Info, Plus } from "lucide-react"; // Assuming lucide-react for icons | ||||
| import { editSightStore } from "@shared"; | ||||
|  | ||||
| import { toast } from "react-toastify"; | ||||
| interface ImageUploadCardProps { | ||||
|   title: string; | ||||
|   imageKey?: "thumbnail" | "watermark_lu" | "watermark_rd"; | ||||
| @@ -12,16 +12,18 @@ interface ImageUploadCardProps { | ||||
|   onSelectFileClick: () => void; | ||||
|   setUploadMediaOpen: (open: boolean) => void; | ||||
|   tooltipText?: string; | ||||
|   setHardcodeType?: (type: string) => void; | ||||
| } | ||||
|  | ||||
| export const ImageUploadCard: React.FC<ImageUploadCardProps> = ({ | ||||
|   title, | ||||
|  | ||||
|   imageKey, | ||||
|   imageUrl, | ||||
|   onImageClick, | ||||
|   onDeleteImageClick, | ||||
|   onSelectFileClick, | ||||
|   setUploadMediaOpen, | ||||
|   setHardcodeType, | ||||
|   tooltipText, | ||||
| }) => { | ||||
|   const fileInputRef = useRef<HTMLInputElement>(null); | ||||
| @@ -46,6 +48,9 @@ export const ImageUploadCard: React.FC<ImageUploadCardProps> = ({ | ||||
|     if (file) { | ||||
|       setFileToUpload(file); | ||||
|       setUploadMediaOpen(true); | ||||
|       if (imageKey && setHardcodeType) { | ||||
|         setHardcodeType(imageKey); | ||||
|       } | ||||
|     } | ||||
|     // Reset the input value so selecting the same file again triggers change | ||||
|     event.target.value = ""; | ||||
| @@ -73,8 +78,12 @@ export const ImageUploadCard: React.FC<ImageUploadCardProps> = ({ | ||||
|     const files = event.dataTransfer.files; | ||||
|     if (files && files.length > 0) { | ||||
|       const file = files[0]; | ||||
|       setFileToUpload(file); | ||||
|       setUploadMediaOpen(true); | ||||
|       if (file.type.startsWith("image/")) { | ||||
|         setFileToUpload(file); | ||||
|         setUploadMediaOpen(true); | ||||
|       } else { | ||||
|         toast.error("Пожалуйста, выберите изображение"); | ||||
|       } | ||||
|     } | ||||
|   }; | ||||
|  | ||||
| @@ -159,7 +168,7 @@ export const ImageUploadCard: React.FC<ImageUploadCardProps> = ({ | ||||
|             <Button | ||||
|               variant="contained" | ||||
|               color="primary" | ||||
|               startIcon={<MousePointer color="white" size={18} />} | ||||
|               startIcon={<Plus color="white" size={18} />} | ||||
|               onClick={(e) => { | ||||
|                 e.stopPropagation(); // Prevent `handleZoneClick` from firing | ||||
|                 onSelectFileClick(); // This button might trigger a different modal | ||||
|   | ||||
| @@ -96,10 +96,10 @@ export const MediaArea = observer( | ||||
|             </Button> | ||||
|           </div> | ||||
|  | ||||
|           <div className="w-full flex flex-start flex-wrap gap-2 mt-4"> | ||||
|           <div className="w-full flex flex-start flex-wrap gap-2 mt-4 py-10"> | ||||
|             {mediaIds.map((m) => ( | ||||
|               <button | ||||
|                 className="relative w-40 h-40" | ||||
|                 className="relative w-20 h-20" | ||||
|                 key={m.id} | ||||
|                 onClick={() => handleMediaModal(m.id)} | ||||
|               > | ||||
|   | ||||
| @@ -12,29 +12,17 @@ export interface MediaData { | ||||
| export function MediaViewer({ | ||||
|   media, | ||||
|   className, | ||||
| }: Readonly<{ media?: MediaData; className?: string }>) { | ||||
|   fullWidth, | ||||
| }: Readonly<{ media?: MediaData; className?: string; fullWidth?: boolean }>) { | ||||
|   const token = localStorage.getItem("token"); | ||||
|   return ( | ||||
|     <Box | ||||
|       sx={{ | ||||
|         width: "100%", | ||||
|         height: "100%", | ||||
|         display: "flex", | ||||
|         flexGrow: 1, | ||||
|       }} | ||||
|       className={className} | ||||
|     > | ||||
|     <Box className={className} width={fullWidth ? "100%" : "auto"}> | ||||
|       {media?.media_type === 1 && ( | ||||
|         <img | ||||
|           src={`${import.meta.env.VITE_KRBL_MEDIA}${ | ||||
|             media?.id | ||||
|           }/download?token=${token}`} | ||||
|           alt={media?.filename} | ||||
|           style={{ | ||||
|             width: "100%", | ||||
|             height: "100%", | ||||
|             objectFit: "contain", | ||||
|           }} | ||||
|         /> | ||||
|       )} | ||||
|  | ||||
| @@ -46,7 +34,7 @@ export function MediaViewer({ | ||||
|           style={{ | ||||
|             width: "100%", | ||||
|             height: "100%", | ||||
|             objectFit: "contain", | ||||
|             objectFit: "cover", | ||||
|             borderRadius: 8, | ||||
|           }} | ||||
|           controls | ||||
| @@ -60,12 +48,6 @@ export function MediaViewer({ | ||||
|             media?.id | ||||
|           }/download?token=${token}`} | ||||
|           alt={media?.filename} | ||||
|           style={{ | ||||
|             width: "100%", | ||||
|             height: "100%", | ||||
|             objectFit: "contain", | ||||
|             borderRadius: 8, | ||||
|           }} | ||||
|         /> | ||||
|       )} | ||||
|       {media?.media_type === 4 && ( | ||||
| @@ -75,10 +57,7 @@ export function MediaViewer({ | ||||
|           }/download?token=${token}`} | ||||
|           alt={media?.filename} | ||||
|           style={{ | ||||
|             width: "100%", | ||||
|             height: "100%", | ||||
|             objectFit: "contain", | ||||
|             borderRadius: 8, | ||||
|             objectFit: "cover", | ||||
|           }} | ||||
|         /> | ||||
|       )} | ||||
|   | ||||
| @@ -25,13 +25,20 @@ const StyledMarkdownEditor = styled("div")(({ theme }) => ({ | ||||
|     color: theme.palette.text.primary, | ||||
|     borderColor: theme.palette.divider, | ||||
|     height: "auto", | ||||
|     minHeight: "200px", | ||||
|     minHeight: "400px", | ||||
|     maxHeight: "500px", | ||||
|     overflow: "auto", | ||||
|     overflowY: "auto", | ||||
|     overflowX: "hidden", | ||||
|     wordWrap: "break-word", // ✅ добавлено | ||||
|     whiteSpace: "pre-wrap", // ✅ добавлено | ||||
|   }, | ||||
|  | ||||
|   "& .CodeMirror-scroll": { | ||||
|     minHeight: "200px", | ||||
|     minHeight: "400px", | ||||
|     maxHeight: "500px", | ||||
|     overflowY: "auto", | ||||
|     overflowX: "hidden", | ||||
|     wordBreak: "break-word", // ✅ добавлено | ||||
|   }, | ||||
|   "& .CodeMirror-selected": { | ||||
|     backgroundColor: `${theme.palette.action.selected} !important`, | ||||
| @@ -76,6 +83,9 @@ export const ReactMarkdownEditor = ({ | ||||
|   const mergedOptions = useMemo(() => { | ||||
|     return { | ||||
|       ...incomingOptions, | ||||
|       codeMirrorOptions: { | ||||
|         lineWrapping: true, | ||||
|       }, | ||||
|       forceSync: true, | ||||
|       spellChecker: false, | ||||
|       toolbar: [ | ||||
|   | ||||
| @@ -48,6 +48,9 @@ export const CreateInformationTab = observer( | ||||
|       "thumbnail" | "watermark_lu" | "watermark_rd" | null | ||||
|     >(null); | ||||
|     const [isAddMediaOpen, setIsAddMediaOpen] = useState(false); | ||||
|     const [hardcodeType, setHardcodeType] = useState< | ||||
|       "thumbnail" | "watermark_lu" | "watermark_rd" | null | ||||
|     >(null); | ||||
|  | ||||
|     // const handleMenuOpen = ( | ||||
|     //   event: React.MouseEvent<HTMLElement>, | ||||
| @@ -260,10 +263,15 @@ export const CreateInformationTab = observer( | ||||
|                       setIsUploadMediaOpen(true); | ||||
|                       setActiveMenuType("thumbnail"); | ||||
|                     }} | ||||
|                     setHardcodeType={(type) => { | ||||
|                       setHardcodeType( | ||||
|                         type as "thumbnail" | "watermark_lu" | "watermark_rd" | ||||
|                       ); | ||||
|                     }} | ||||
|                   /> | ||||
|  | ||||
|                   <ImageUploadCard | ||||
|                     title="Водяной знак (л.в)" | ||||
|                     title="Водяной знак (леввый верхний)" | ||||
|                     imageKey="watermark_lu" | ||||
|                     imageUrl={sight.watermark_lu} | ||||
|                     onImageClick={() => { | ||||
| @@ -284,10 +292,15 @@ export const CreateInformationTab = observer( | ||||
|                       setIsUploadMediaOpen(true); | ||||
|                       setActiveMenuType("watermark_lu"); | ||||
|                     }} | ||||
|                     setHardcodeType={(type) => { | ||||
|                       setHardcodeType( | ||||
|                         type as "thumbnail" | "watermark_lu" | "watermark_rd" | ||||
|                       ); | ||||
|                     }} | ||||
|                   /> | ||||
|  | ||||
|                   <ImageUploadCard | ||||
|                     title="Водяной знак (п.в)" | ||||
|                     title="Водяной знак (правый нижний)" | ||||
|                     imageKey="watermark_rd" | ||||
|                     imageUrl={sight.watermark_rd} | ||||
|                     onImageClick={() => { | ||||
| @@ -308,6 +321,11 @@ export const CreateInformationTab = observer( | ||||
|                       setIsUploadMediaOpen(true); | ||||
|                       setActiveMenuType("watermark_rd"); | ||||
|                     }} | ||||
|                     setHardcodeType={(type) => { | ||||
|                       setHardcodeType( | ||||
|                         type as "thumbnail" | "watermark_lu" | "watermark_rd" | ||||
|                       ); | ||||
|                     }} | ||||
|                   /> | ||||
|                 </Box> | ||||
|               </Box> | ||||
| @@ -397,6 +415,7 @@ export const CreateInformationTab = observer( | ||||
|             setActiveMenuType(null); | ||||
|             setIsUploadMediaOpen(false); | ||||
|           }} | ||||
|           hardcodeType={hardcodeType} | ||||
|         /> | ||||
|       </> | ||||
|     ); | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import { | ||||
|   createSightStore, | ||||
|   SelectArticleModal, | ||||
|   UploadMediaDialog, | ||||
|   Language, | ||||
| } from "@shared"; | ||||
| import { | ||||
|   LanguageSwitcher, | ||||
| @@ -308,8 +309,8 @@ export const CreateLeftTab = observer( | ||||
|                     flex: 1, | ||||
|                     display: "flex", | ||||
|                     flexDirection: "column", | ||||
|                     gap: 1.5, | ||||
|                     maxWidth: "320px", | ||||
|                     gap: 0.5, | ||||
|                   }} | ||||
|                 > | ||||
|                   <Paper | ||||
| @@ -317,49 +318,32 @@ export const CreateLeftTab = observer( | ||||
|                     sx={{ | ||||
|                       width: "100%", | ||||
|                       minWidth: 320, | ||||
|                       maxWidth: 400, | ||||
|                       height: "auto", | ||||
|                       minHeight: 500, | ||||
|                       backgroundColor: "#877361", | ||||
|                       background: | ||||
|                         "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||
|                       overflowY: "auto", | ||||
|                       padding: 0, | ||||
|                       display: "flex", | ||||
|  | ||||
|                       flexDirection: "column", | ||||
|                       borderRadius: "10px", | ||||
|                     }} | ||||
|                   > | ||||
|                     {/* {data.left.media?.filename ? ( | ||||
|                   <Box | ||||
|                     sx={{ | ||||
|                       width: "100%", | ||||
|                       height: 200, | ||||
|                       backgroundColor: "grey.300", | ||||
|                       display: "flex", | ||||
|                       alignItems: "center", | ||||
|                       justifyContent: "center", | ||||
|                     }} | ||||
|                   > | ||||
|                     <img | ||||
|                       src={data.left.media?.filename ?? ""} | ||||
|                       alt="Превью медиа" | ||||
|                       style={{ | ||||
|                         objectFit: "cover", | ||||
|                         width: "100%", | ||||
|                         height: "100%", | ||||
|                       }} | ||||
|                     /> | ||||
|                   </Box> | ||||
|                 ) : ( | ||||
|                    | ||||
|                 )} */} | ||||
|  | ||||
|                     <Box | ||||
|                       sx={{ | ||||
|                         overflow: "hidden", | ||||
|                         width: "100%", | ||||
|                         height: 200, | ||||
|                         backgroundColor: "grey.300", | ||||
|                         minHeight: 100, | ||||
|                         padding: "3px", | ||||
|                         display: "flex", | ||||
|                         alignItems: "center", | ||||
|                         justifyContent: "center", | ||||
|  | ||||
|                         "& img": { | ||||
|                           borderTopLeftRadius: "10px", | ||||
|                           borderTopRightRadius: "10px", | ||||
|                           width: "100%", | ||||
|                           height: "auto", | ||||
|                           objectFit: "contain", | ||||
|                         }, | ||||
|                       }} | ||||
|                     > | ||||
|                       {sight[language].left.media.length > 0 ? ( | ||||
| @@ -370,40 +354,67 @@ export const CreateLeftTab = observer( | ||||
|                               sight[language].left.media[0].media_type, | ||||
|                             filename: sight[language].left.media[0].filename, | ||||
|                           }} | ||||
|                           fullWidth | ||||
|                         /> | ||||
|                       ) : ( | ||||
|                         <ImagePlus size={48} color="grey" /> | ||||
|                         <ImagePlus size={48} color="white" /> | ||||
|                       )} | ||||
|                     </Box> | ||||
|  | ||||
|                     {/* Заголовок в превью */} | ||||
|                     <Box | ||||
|                       sx={{ | ||||
|                         backgroundColor: "#877361", | ||||
|                         background: | ||||
|                           "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||
|                         color: "white", | ||||
|                         padding: 1.5, | ||||
|                         margin: "5px 0px 5px 0px", | ||||
|                         display: "flex", | ||||
|                         flexDirection: "column", | ||||
|                         gap: 1, | ||||
|                         padding: 1, | ||||
|                       }} | ||||
|                     > | ||||
|                       <Typography | ||||
|                         variant="h5" | ||||
|                         component="h2" | ||||
|                         sx={{ wordBreak: "break-word" }} | ||||
|                         sx={{ | ||||
|                           wordBreak: "break-word", | ||||
|                           fontSize: "24px", | ||||
|                           fontWeight: 700, | ||||
|                           lineHeight: "120%", | ||||
|                         }} | ||||
|                       > | ||||
|                         {sight[language].left.heading || "Название информации"} | ||||
|                       </Typography> | ||||
|                       <Typography | ||||
|                         variant="h6" | ||||
|                         component="h2" | ||||
|                         sx={{ | ||||
|                           wordBreak: "break-word", | ||||
|                           fontSize: "18px", | ||||
|  | ||||
|                           lineHeight: "120%", | ||||
|                         }} | ||||
|                       > | ||||
|                         {sight[language as Language].address} | ||||
|                       </Typography> | ||||
|                     </Box> | ||||
|  | ||||
|                     {/* Текст статьи в превью */} | ||||
|                     <Box | ||||
|                       sx={{ | ||||
|                         padding: 2, | ||||
|                         flexGrow: 1, | ||||
|                       }} | ||||
|                     > | ||||
|                       <ReactMarkdownComponent | ||||
|                         value={sight[language].left.body} | ||||
|                       /> | ||||
|                     </Box> | ||||
|                     {sight[language].left.body && ( | ||||
|                       <Box | ||||
|                         sx={{ | ||||
|                           padding: 1, | ||||
|                           maxHeight: "300px", | ||||
|                           overflowY: "scroll", | ||||
|                           background: | ||||
|                             "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||
|                           flexGrow: 1, | ||||
|                         }} | ||||
|                       > | ||||
|                         <ReactMarkdownComponent | ||||
|                           value={sight[language].left.body} | ||||
|                         /> | ||||
|                       </Box> | ||||
|                     )} | ||||
|                   </Paper> | ||||
|                 </Box> | ||||
|               </Box> | ||||
|   | ||||
| @@ -239,7 +239,7 @@ export const CreateRightTab = observer( | ||||
|  | ||||
|       // 4. Update the store with the new order: | ||||
|       //    This will typically trigger a re-render of the component with the updated list. | ||||
|       updateRightArticles(newRightArticles, language); | ||||
|       updateRightArticles(newRightArticles); | ||||
|     }; | ||||
|  | ||||
|     return ( | ||||
| @@ -511,7 +511,7 @@ export const CreateRightTab = observer( | ||||
|                 <Paper | ||||
|                   className="flex-1 flex flex-col  max-w-[500px]" | ||||
|                   sx={{ | ||||
|                     borderRadius: "16px", | ||||
|                     borderRadius: "10px", | ||||
|                     overflow: "hidden", | ||||
|                   }} | ||||
|                   elevation={2} | ||||
| @@ -531,13 +531,17 @@ export const CreateRightTab = observer( | ||||
|                     0 ? ( | ||||
|                       <Box | ||||
|                         sx={{ | ||||
|                           overflow: "hidden", | ||||
|                           width: "100%", | ||||
|                           maxHeight: "290px", | ||||
|                           flexShrink: 0, | ||||
|                           padding: "2px 2px 0px 2px", | ||||
|  | ||||
|                           display: "flex", | ||||
|                           alignItems: "center", | ||||
|                           justifyContent: "center", | ||||
|                           "& img": { | ||||
|                             borderTopLeftRadius: "10px", | ||||
|                             borderTopRightRadius: "10px", | ||||
|                             width: "100%", | ||||
|                             height: "auto", | ||||
|                             objectFit: "contain", | ||||
|                           }, | ||||
|                         }} | ||||
|                       > | ||||
|                         <MediaViewer | ||||
| @@ -571,6 +575,7 @@ export const CreateRightTab = observer( | ||||
|                         fontWeight: 700, | ||||
|                         lineHeight: "120%", | ||||
|                         backdropFilter: "blur(12px)", | ||||
|                         borderBottom: "1px solid #A89F90", | ||||
|                         boxShadow: | ||||
|                           "inset 4px 4px 12px 0 rgba(255,255,255,0.12)", | ||||
|                         background: | ||||
|   | ||||
| @@ -50,7 +50,9 @@ export const InformationTab = observer( | ||||
|       "thumbnail" | "watermark_lu" | "watermark_rd" | null | ||||
|     >(null); | ||||
|     const [isAddMediaOpen, setIsAddMediaOpen] = useState(false); | ||||
|  | ||||
|     const [hardcodeType, setHardcodeType] = useState< | ||||
|       "thumbnail" | "watermark_lu" | "watermark_rd" | null | ||||
|     >(null); | ||||
|     useEffect(() => { | ||||
|       // Показывать только при инициализации (не менять при ошибках пользователя) | ||||
|       if (sight.common.latitude !== 0 || sight.common.longitude !== 0) { | ||||
| @@ -260,9 +262,14 @@ export const InformationTab = observer( | ||||
|                       setIsUploadMediaOpen(true); | ||||
|                       setActiveMenuType("thumbnail"); | ||||
|                     }} | ||||
|                     setHardcodeType={(type) => { | ||||
|                       setHardcodeType( | ||||
|                         type as "thumbnail" | "watermark_lu" | "watermark_rd" | ||||
|                       ); | ||||
|                     }} | ||||
|                   /> | ||||
|                   <ImageUploadCard | ||||
|                     title="Водяной знак (л.в)" | ||||
|                     title="Водяной знак (левый верхний)" | ||||
|                     imageKey="watermark_lu" | ||||
|                     imageUrl={sight.common.watermark_lu} | ||||
|                     onImageClick={() => { | ||||
| @@ -287,9 +294,14 @@ export const InformationTab = observer( | ||||
|                       setIsUploadMediaOpen(true); | ||||
|                       setActiveMenuType("watermark_lu"); | ||||
|                     }} | ||||
|                     setHardcodeType={(type) => { | ||||
|                       setHardcodeType( | ||||
|                         type as "thumbnail" | "watermark_lu" | "watermark_rd" | ||||
|                       ); | ||||
|                     }} | ||||
|                   /> | ||||
|                   <ImageUploadCard | ||||
|                     title="Водяной знак (п.в)" | ||||
|                     title="Водяной знак (правый нижний)" | ||||
|                     imageKey="watermark_rd" | ||||
|                     imageUrl={sight.common.watermark_rd} | ||||
|                     onImageClick={() => { | ||||
| @@ -314,6 +326,11 @@ export const InformationTab = observer( | ||||
|                       setIsUploadMediaOpen(true); | ||||
|                       setActiveMenuType("watermark_rd"); | ||||
|                     }} | ||||
|                     setHardcodeType={(type) => { | ||||
|                       setHardcodeType( | ||||
|                         type as "thumbnail" | "watermark_lu" | "watermark_rd" | ||||
|                       ); | ||||
|                     }} | ||||
|                   /> | ||||
|                 </Box> | ||||
|               </Box> | ||||
| @@ -399,6 +416,7 @@ export const InformationTab = observer( | ||||
|             setActiveMenuType(null); | ||||
|             setIsUploadMediaOpen(false); | ||||
|           }} | ||||
|           hardcodeType={hardcodeType} | ||||
|         /> | ||||
|         <PreviewMediaDialog | ||||
|           open={isPreviewMediaOpen} | ||||
|   | ||||
| @@ -260,22 +260,32 @@ export const LeftWidgetTab = observer( | ||||
|                     sx={{ | ||||
|                       width: "100%", | ||||
|                       minWidth: 320, | ||||
|  | ||||
|                       background: | ||||
|                         "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||
|                       overflowY: "auto", | ||||
|                       padding: 0, | ||||
|                       display: "flex", | ||||
|  | ||||
|                       flexDirection: "column", | ||||
|                       borderRadius: "10px", | ||||
|                     }} | ||||
|                   > | ||||
|                     <Box | ||||
|                       sx={{ | ||||
|                         overflow: "hidden", | ||||
|                         width: "100%", | ||||
|                         height: 175, | ||||
|                         minHeight: 100, | ||||
|                         padding: "3px", | ||||
|                         display: "flex", | ||||
|                         alignItems: "center", | ||||
|                         padding: "3px", | ||||
|                         justifyContent: "center", | ||||
|  | ||||
|                         "& img": { | ||||
|                           borderTopLeftRadius: "10px", | ||||
|                           borderTopRightRadius: "10px", | ||||
|                           width: "100%", | ||||
|                           height: "auto", | ||||
|                           objectFit: "contain", | ||||
|                         }, | ||||
|                       }} | ||||
|                     > | ||||
|                       {data.left.media.length > 0 ? ( | ||||
| @@ -285,9 +295,10 @@ export const LeftWidgetTab = observer( | ||||
|                             media_type: data.left.media[0].media_type, | ||||
|                             filename: data.left.media[0].filename, | ||||
|                           }} | ||||
|                           fullWidth | ||||
|                         /> | ||||
|                       ) : ( | ||||
|                         <ImagePlus size={48} color="grey" /> | ||||
|                         <ImagePlus size={48} color="white" /> | ||||
|                       )} | ||||
|                     </Box> | ||||
|  | ||||
|   | ||||
| @@ -182,7 +182,7 @@ export const RightWidgetTab = observer( | ||||
|  | ||||
|       // 4. Update the store with the new order: | ||||
|       //    This will typically trigger a re-render of the component with the updated list. | ||||
|       updateRightArticles(newRightArticles, language); | ||||
|       updateRightArticles(newRightArticles); | ||||
|     }; | ||||
|  | ||||
|     return ( | ||||
| @@ -347,7 +347,7 @@ export const RightWidgetTab = observer( | ||||
|                               value={ | ||||
|                                 sight[language].right[activeArticleIndex].body | ||||
|                               } | ||||
|                               onChange={(value) => | ||||
|                               onChange={(value: any) => | ||||
|                                 updateRightArticleInfo( | ||||
|                                   activeArticleIndex, | ||||
|                                   language, | ||||
| @@ -381,11 +381,11 @@ export const RightWidgetTab = observer( | ||||
|                   </Box> | ||||
|                 )} | ||||
|                 {type === "media" && ( | ||||
|                   <Box className="w-[80%] border border-gray-300 rounded-2xl relative"> | ||||
|                   <Box className="w-[80%] border border-gray-300 rounded-2xl relative flex justify-center items-center"> | ||||
|                     {sight.common.preview_media && ( | ||||
|                       <> | ||||
|                         {type === "media" && ( | ||||
|                           <Box className="w-[80%] h-full  rounded-2xl relative flex items-center justify-center"> | ||||
|                           <Box className="w-full h-full rounded-2xl relative flex items-center justify-center"> | ||||
|                             {previewMedia && ( | ||||
|                               <> | ||||
|                                 <Box className="absolute top-4 right-4  z-10"> | ||||
| @@ -397,7 +397,7 @@ export const RightWidgetTab = observer( | ||||
|                                   </button> | ||||
|                                 </Box> | ||||
|  | ||||
|                                 <Box className="w-1/2 h-1/2"> | ||||
|                                 <Box className="w-1/2 h-1/2 flex justify-center items-center"> | ||||
|                                   <MediaViewer | ||||
|                                     media={{ | ||||
|                                       id: previewMedia.id || "", | ||||
| @@ -453,7 +453,7 @@ export const RightWidgetTab = observer( | ||||
|                   <Paper | ||||
|                     className="flex-1 flex flex-col  max-w-[500px]" | ||||
|                     sx={{ | ||||
|                       borderRadius: "16px", | ||||
|                       borderRadius: "10px", | ||||
|                       overflow: "hidden", | ||||
|                     }} | ||||
|                     elevation={2} | ||||
| @@ -473,13 +473,17 @@ export const RightWidgetTab = observer( | ||||
|                       0 ? ( | ||||
|                         <Box | ||||
|                           sx={{ | ||||
|                             overflow: "hidden", | ||||
|                             width: "100%", | ||||
|                             maxHeight: "290px", | ||||
|                             flexShrink: 0, | ||||
|                             padding: "2px 2px 0px 2px", | ||||
|  | ||||
|                             display: "flex", | ||||
|                             alignItems: "center", | ||||
|                             justifyContent: "center", | ||||
|                             "& img": { | ||||
|                               borderTopLeftRadius: "10px", | ||||
|                               borderTopRightRadius: "10px", | ||||
|                               width: "100%", | ||||
|                               height: "auto", | ||||
|                               objectFit: "contain", | ||||
|                             }, | ||||
|                           }} | ||||
|                         > | ||||
|                           <MediaViewer | ||||
| @@ -513,6 +517,7 @@ export const RightWidgetTab = observer( | ||||
|                           fontWeight: 700, | ||||
|                           lineHeight: "120%", | ||||
|                           backdropFilter: "blur(12px)", | ||||
|                           borderBottom: "1px solid #A89F90", | ||||
|                           boxShadow: | ||||
|                             "inset 4px 4px 12px 0 rgba(255,255,255,0.12)", | ||||
|                           background: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user