fix: Delete ai comments
This commit is contained in:
@@ -1,158 +0,0 @@
|
||||
// import { Box, Button, Paper, Typography } from "@mui/material";
|
||||
// import { X, Upload } from "lucide-react";
|
||||
// import { useCallback, useState } from "react";
|
||||
// import { useDropzone } from "react-dropzone";
|
||||
// import { UploadMediaDialog } from "@shared";
|
||||
// import { createSightStore } from "@shared";
|
||||
|
||||
// interface MediaUploadBoxProps {
|
||||
// title: string;
|
||||
// tooltip?: string;
|
||||
// mediaId: string | null;
|
||||
// onMediaSelect: (mediaId: string) => void;
|
||||
// onMediaRemove: () => void;
|
||||
// onPreviewClick: (mediaId: string) => void;
|
||||
// token: string;
|
||||
// type: "thumbnail" | "watermark_lu" | "watermark_rd";
|
||||
// }
|
||||
|
||||
// export const MediaUploadBox = ({
|
||||
// title,
|
||||
// tooltip,
|
||||
// mediaId,
|
||||
// onMediaSelect,
|
||||
// onMediaRemove,
|
||||
// onPreviewClick,
|
||||
// token,
|
||||
// type,
|
||||
// }: MediaUploadBoxProps) => {
|
||||
// const [uploadMediaOpen, setUploadMediaOpen] = useState(false);
|
||||
// const [fileToUpload, setFileToUpload] = useState<File | null>(null);
|
||||
|
||||
// const onDrop = useCallback((acceptedFiles: File[]) => {
|
||||
// if (acceptedFiles.length > 0) {
|
||||
// setFileToUpload(acceptedFiles[0]);
|
||||
// setUploadMediaOpen(true);
|
||||
// }
|
||||
// }, []);
|
||||
|
||||
// const { getRootProps, getInputProps, isDragActive } = useDropzone({
|
||||
// onDrop,
|
||||
// accept: {
|
||||
// "image/*": [".png", ".jpg", ".jpeg", ".gif"],
|
||||
// },
|
||||
// multiple: false,
|
||||
// });
|
||||
|
||||
// const handleUploadComplete = async (media: {
|
||||
// id: string;
|
||||
// filename: string;
|
||||
// media_name?: string;
|
||||
// media_type: number;
|
||||
// }) => {
|
||||
// onMediaSelect(media.id);
|
||||
// };
|
||||
|
||||
// return (
|
||||
// <>
|
||||
// <Paper
|
||||
// elevation={2}
|
||||
// sx={{
|
||||
// padding: 2,
|
||||
// display: "flex",
|
||||
// flexDirection: "column",
|
||||
// alignItems: "center",
|
||||
// gap: 1,
|
||||
// flex: 1,
|
||||
// minWidth: 150,
|
||||
// }}
|
||||
// >
|
||||
// <Box sx={{ display: "flex", alignItems: "center" }}>
|
||||
// <Typography variant="subtitle2" gutterBottom sx={{ mb: 0, mr: 0.5 }}>
|
||||
// {title}
|
||||
// </Typography>
|
||||
// </Box>
|
||||
// <Box
|
||||
// {...getRootProps()}
|
||||
// sx={{
|
||||
// position: "relative",
|
||||
// width: "200px",
|
||||
// height: "200px",
|
||||
// display: "flex",
|
||||
// alignItems: "center",
|
||||
// justifyContent: "center",
|
||||
// borderRadius: 1,
|
||||
// mb: 1,
|
||||
// cursor: mediaId ? "pointer" : "default",
|
||||
// border: isDragActive ? "2px dashed #1976d2" : "none",
|
||||
// backgroundColor: isDragActive
|
||||
// ? "rgba(25, 118, 210, 0.04)"
|
||||
// : "transparent",
|
||||
// transition: "all 0.2s ease",
|
||||
// }}
|
||||
// >
|
||||
// <input {...getInputProps()} />
|
||||
// {mediaId && (
|
||||
// <button
|
||||
// className="absolute top-2 right-2 z-10"
|
||||
// onClick={(e) => {
|
||||
// e.stopPropagation();
|
||||
// onMediaRemove();
|
||||
// }}
|
||||
// >
|
||||
// <X color="red" />
|
||||
// </button>
|
||||
// )}
|
||||
// {mediaId ? (
|
||||
// <img
|
||||
// src={`${
|
||||
// import.meta.env.VITE_KRBL_MEDIA
|
||||
// }${mediaId}/download?token=${token}`}
|
||||
// alt={title}
|
||||
// style={{ maxWidth: "100%", maxHeight: "100%" }}
|
||||
// onClick={(e) => {
|
||||
// e.stopPropagation();
|
||||
// onPreviewClick(mediaId);
|
||||
// }}
|
||||
// />
|
||||
// ) : (
|
||||
// <div className="w-full flex flex-col items-center justify-center gap-3">
|
||||
// <div
|
||||
// className={`w-full h-20 border rounded-md flex flex-col items-center transition-all duration-300 justify-center border-dashed ${
|
||||
// isDragActive
|
||||
// ? "border-blue-500 bg-blue-50"
|
||||
// : "border-gray-300"
|
||||
// } cursor-pointer hover:bg-gray-100`}
|
||||
// >
|
||||
// <Upload size={24} className="mb-2" />
|
||||
// <p>
|
||||
// {isDragActive ? "Отпустите файл здесь" : "Перетащите файл"}
|
||||
// </p>
|
||||
// </div>
|
||||
// <p>или</p>
|
||||
// <Button
|
||||
// variant="contained"
|
||||
// color="primary"
|
||||
// onClick={(e) => {
|
||||
// e.stopPropagation();
|
||||
// onMediaSelect("");
|
||||
// }}
|
||||
// >
|
||||
// Выбрать файл
|
||||
// </Button>
|
||||
// </div>
|
||||
// )}
|
||||
// </Box>
|
||||
// </Paper>
|
||||
|
||||
// <UploadMediaDialog
|
||||
// open={uploadMediaOpen}
|
||||
// onClose={() => {
|
||||
// setUploadMediaOpen(false);
|
||||
// setFileToUpload(null);
|
||||
// }}
|
||||
// afterUpload={handleUploadComplete}
|
||||
// />
|
||||
// </>
|
||||
// );
|
||||
// };
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// @widgets/LeftWidgetTab.tsx
|
||||
import { Box, Button, TextField, Paper, Typography } from "@mui/material";
|
||||
import {
|
||||
BackButton,
|
||||
@@ -50,17 +49,6 @@ export const CreateLeftTab = observer(
|
||||
const [isSelectMediaDialogOpen, setIsSelectMediaDialogOpen] =
|
||||
useState(false);
|
||||
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||
// const handleMediaSelected = useCallback(() => {
|
||||
// // При выборе медиа, обновляем данные для ТЕКУЩЕГО ЯЗЫКА
|
||||
// // сохраняя текущие heading и body.
|
||||
// updateSightInfo(language, {
|
||||
// left: {
|
||||
// heading: data.left.heading,
|
||||
// body: data.left.body,
|
||||
// },
|
||||
// });
|
||||
// setIsSelectMediaDialogOpen(false);
|
||||
// }, [language, data.left.heading, data.left.body]);
|
||||
|
||||
const handleCloseArticleDialog = useCallback(() => {
|
||||
setIsSelectArticleDialogOpen(false);
|
||||
|
||||
@@ -13,28 +13,27 @@ import {
|
||||
languageStore,
|
||||
SelectArticleModal,
|
||||
TabPanel,
|
||||
SelectMediaDialog, // Import
|
||||
SelectMediaDialog,
|
||||
UploadMediaDialog,
|
||||
Media, // Import
|
||||
Media,
|
||||
} from "@shared";
|
||||
import {
|
||||
LanguageSwitcher,
|
||||
MediaArea, // Import
|
||||
MediaAreaForSight, // Import
|
||||
MediaArea,
|
||||
MediaAreaForSight,
|
||||
ReactMarkdownComponent,
|
||||
ReactMarkdownEditor,
|
||||
DeleteModal,
|
||||
} from "@widgets";
|
||||
import { ImagePlus, Plus, Save, Trash2, Unlink, X } from "lucide-react"; // Import X
|
||||
import { ImagePlus, Plus, Save, Trash2, Unlink, X } from "lucide-react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useState, useEffect } from "react"; // Added useEffect
|
||||
import { useState, useEffect } from "react";
|
||||
import { MediaViewer } from "../../MediaViewer/index";
|
||||
import { toast } from "react-toastify";
|
||||
import { authInstance } from "@shared";
|
||||
import { DragDropContext, Droppable, Draggable } from "@hello-pangea/dnd";
|
||||
|
||||
type MediaItemShared = {
|
||||
// Define if not already available from @shared
|
||||
id: string;
|
||||
filename: string;
|
||||
media_name?: string;
|
||||
@@ -52,14 +51,14 @@ export const CreateRightTab = observer(
|
||||
unlinkPreviewMedia,
|
||||
createLinkWithRightArticle,
|
||||
deleteRightArticleMedia,
|
||||
setFileToUpload, // From store
|
||||
setUploadMediaOpen, // From store
|
||||
uploadMediaOpen, // From store
|
||||
unlinkRightAritcle, // Corrected spelling
|
||||
setFileToUpload,
|
||||
setUploadMediaOpen,
|
||||
uploadMediaOpen,
|
||||
unlinkRightAritcle,
|
||||
deleteRightArticle,
|
||||
linkExistingRightArticle,
|
||||
createSight,
|
||||
clearCreateSight, // For resetting form
|
||||
clearCreateSight,
|
||||
updateRightArticles,
|
||||
} = createSightStore;
|
||||
const { language } = languageStore;
|
||||
@@ -78,7 +77,7 @@ export const CreateRightTab = observer(
|
||||
>(null);
|
||||
|
||||
const [previewMedia, setPreviewMedia] = useState<Media | null>(null);
|
||||
// Reset activeArticleIndex if language changes and index is out of bounds
|
||||
|
||||
useEffect(() => {
|
||||
if (sight.preview_media) {
|
||||
const fetchMedia = async () => {
|
||||
@@ -97,7 +96,7 @@ export const CreateRightTab = observer(
|
||||
activeArticleIndex >= sight[language].right.length
|
||||
) {
|
||||
setActiveArticleIndex(null);
|
||||
setType("media"); // Default back to media preview if selected article disappears
|
||||
setType("media");
|
||||
}
|
||||
}, [language, sight[language].right, activeArticleIndex]);
|
||||
|
||||
@@ -113,10 +112,9 @@ export const CreateRightTab = observer(
|
||||
try {
|
||||
await createSight(language);
|
||||
toast.success("Достопримечательность успешно создана!");
|
||||
clearCreateSight(); // Reset form
|
||||
clearCreateSight();
|
||||
setActiveArticleIndex(null);
|
||||
setType("media");
|
||||
// Potentially navigate away: history.push('/sights-list');
|
||||
} catch (error) {
|
||||
console.error("Failed to save sight:", error);
|
||||
toast.error("Ошибка при создании достопримечательности.");
|
||||
@@ -132,7 +130,7 @@ export const CreateRightTab = observer(
|
||||
handleCloseMenu();
|
||||
try {
|
||||
const newArticleId = await createNewRightArticle();
|
||||
// Automatically select the new article if ID is returned
|
||||
|
||||
const newIndex = sight[language].right.findIndex(
|
||||
(a) => a.id === newArticleId
|
||||
);
|
||||
@@ -140,7 +138,6 @@ export const CreateRightTab = observer(
|
||||
setActiveArticleIndex(newIndex);
|
||||
setType("article");
|
||||
} else {
|
||||
// Fallback if findIndex fails (should not happen if store updates correctly)
|
||||
setActiveArticleIndex(sight[language].right.length - 1);
|
||||
setType("article");
|
||||
}
|
||||
@@ -156,7 +153,7 @@ export const CreateRightTab = observer(
|
||||
const linkedArticleId = await linkExistingRightArticle(
|
||||
selectedArticleId
|
||||
);
|
||||
setSelectArticleDialogOpen(false); // Close dialog
|
||||
setSelectArticleDialogOpen(false);
|
||||
const newIndex = sight[language].right.findIndex(
|
||||
(a) => a.id === linkedArticleId
|
||||
);
|
||||
@@ -174,7 +171,6 @@ export const CreateRightTab = observer(
|
||||
? sight[language].right[activeArticleIndex]
|
||||
: null;
|
||||
|
||||
// Media Handling for Dialogs
|
||||
const handleOpenUploadMedia = () => {
|
||||
setUploadMediaOpen(true);
|
||||
};
|
||||
@@ -203,7 +199,6 @@ export const CreateRightTab = observer(
|
||||
};
|
||||
|
||||
const handleMediaUploaded = async (media: MediaItemShared) => {
|
||||
// After UploadMediaDialog finishes
|
||||
setUploadMediaOpen(false);
|
||||
setFileToUpload(null);
|
||||
if (mediaTarget === "sightPreview") {
|
||||
@@ -211,36 +206,25 @@ export const CreateRightTab = observer(
|
||||
} else if (mediaTarget === "rightArticle" && currentRightArticle) {
|
||||
await createLinkWithRightArticle(media, currentRightArticle.id);
|
||||
}
|
||||
setMediaTarget(null); // Reset target
|
||||
setMediaTarget(null);
|
||||
};
|
||||
|
||||
const handleDragEnd = (result: any) => {
|
||||
const { source, destination } = result;
|
||||
|
||||
// 1. Guard clause: If dropped outside any droppable area, do nothing.
|
||||
if (!destination) return;
|
||||
|
||||
// Extract source and destination indices
|
||||
const sourceIndex = source.index;
|
||||
const destinationIndex = destination.index;
|
||||
|
||||
// 2. Guard clause: If dropped in the same position, do nothing.
|
||||
if (sourceIndex === destinationIndex) return;
|
||||
|
||||
// 3. Create a new array with reordered articles:
|
||||
// - Create a shallow copy of the current articles array.
|
||||
// This is important for immutability and triggering re-renders.
|
||||
const newRightArticles = [...sight[language].right];
|
||||
|
||||
// - Remove the dragged article from its original position.
|
||||
// `splice` returns an array of removed items, so we destructure the first (and only) one.
|
||||
const [movedArticle] = newRightArticles.splice(sourceIndex, 1);
|
||||
|
||||
// - Insert the moved article into its new position.
|
||||
newRightArticles.splice(destinationIndex, 0, movedArticle);
|
||||
|
||||
// 4. Update the store with the new order:
|
||||
// This will typically trigger a re-render of the component with the updated list.
|
||||
updateRightArticles(newRightArticles);
|
||||
};
|
||||
|
||||
@@ -254,7 +238,7 @@ export const CreateRightTab = observer(
|
||||
height: "100%",
|
||||
minHeight: "calc(100vh - 200px)",
|
||||
gap: 2,
|
||||
paddingBottom: "70px", // Space for the save button
|
||||
paddingBottom: "70px",
|
||||
position: "relative",
|
||||
}}
|
||||
>
|
||||
@@ -264,7 +248,6 @@ export const CreateRightTab = observer(
|
||||
</div>
|
||||
|
||||
<Box sx={{ display: "flex", flexGrow: 1, gap: 2.5 }}>
|
||||
{/* Left Column: Navigation & Article List */}
|
||||
<Box className="flex flex-col w-[75%] gap-2">
|
||||
<Box className="w-full flex gap-2 ">
|
||||
<Box className="relative w-[20%] h-[70vh] flex flex-col rounded-2xl overflow-y-auto gap-3 border border-gray-300 p-3">
|
||||
@@ -272,7 +255,6 @@ export const CreateRightTab = observer(
|
||||
<Box
|
||||
onClick={() => {
|
||||
setType("media");
|
||||
// setActiveArticleIndex(null); // Optional: deselect article when switching to general media view
|
||||
}}
|
||||
className={`w-full p-4 rounded-2xl cursor-pointer text-sm hover:bg-gray-300 transition-all duration-300 ${
|
||||
type === "media"
|
||||
@@ -364,7 +346,6 @@ export const CreateRightTab = observer(
|
||||
</Menu>
|
||||
</Box>
|
||||
|
||||
{/* Main content area: Article Editor or Sight Media Preview */}
|
||||
{type === "article" && currentRightArticle ? (
|
||||
<Box className="w-[80%] border border-gray-300 p-3 flex flex-col gap-2 overflow-hidden">
|
||||
<Box className="flex justify-end gap-2 mb-1 flex-shrink-0">
|
||||
@@ -375,7 +356,7 @@ export const CreateRightTab = observer(
|
||||
startIcon={<Unlink color="white" size={18} />}
|
||||
onClick={() => {
|
||||
if (currentRightArticle) {
|
||||
unlinkRightAritcle(currentRightArticle.id); // Corrected function name
|
||||
unlinkRightAritcle(currentRightArticle.id);
|
||||
setActiveArticleIndex(null);
|
||||
setType("media");
|
||||
}
|
||||
@@ -435,7 +416,7 @@ export const CreateRightTab = observer(
|
||||
/>
|
||||
</Box>
|
||||
<MediaArea
|
||||
articleId={currentRightArticle.id} // Needs a real ID
|
||||
articleId={currentRightArticle.id}
|
||||
mediaIds={currentRightArticle.media || []}
|
||||
onFilesDrop={(files) => {
|
||||
if (files.length > 0) {
|
||||
@@ -507,7 +488,6 @@ export const CreateRightTab = observer(
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Right Column: Live Preview */}
|
||||
<Box className="w-[25%] mr-10">
|
||||
{type === "article" && activeArticleIndex !== null && (
|
||||
<Paper
|
||||
@@ -662,12 +642,11 @@ export const CreateRightTab = observer(
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Sticky Save Button Footer */}
|
||||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
bottom: "-20px",
|
||||
left: 0, // ensure it spans from left
|
||||
left: 0,
|
||||
right: 0,
|
||||
padding: 2,
|
||||
backgroundColor: "background.paper",
|
||||
@@ -689,19 +668,17 @@ export const CreateRightTab = observer(
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Modals */}
|
||||
<SelectArticleModal
|
||||
open={selectArticleDialogOpen}
|
||||
onClose={() => setSelectArticleDialogOpen(false)}
|
||||
onSelectArticle={handleSelectExistingArticleAndLink}
|
||||
// Pass IDs of already linked/added right articles to exclude them from selection
|
||||
linkedArticleIds={sight[language].right.map((article) => article.id)}
|
||||
/>
|
||||
<UploadMediaDialog
|
||||
open={uploadMediaOpen} // From store
|
||||
open={uploadMediaOpen}
|
||||
onClose={() => {
|
||||
setUploadMediaOpen(false);
|
||||
setFileToUpload(null); // Clear file if dialog is closed without upload
|
||||
setFileToUpload(null);
|
||||
setMediaTarget(null);
|
||||
}}
|
||||
contextObjectName={sight[language].name}
|
||||
@@ -712,7 +689,7 @@ export const CreateRightTab = observer(
|
||||
? sight[language].right[activeArticleIndex].heading
|
||||
: undefined
|
||||
}
|
||||
afterUpload={handleMediaUploaded} // This will use the mediaTarget
|
||||
afterUpload={handleMediaUploaded}
|
||||
/>
|
||||
<SelectMediaDialog
|
||||
open={isSelectMediaDialogOpen}
|
||||
|
||||
@@ -118,7 +118,7 @@ export const RightWidgetTab = observer(
|
||||
try {
|
||||
const newArticleId = await createNewRightArticle();
|
||||
handleClose();
|
||||
// Automatically select the newly created article
|
||||
|
||||
const newIndex = sight[language].right.findIndex(
|
||||
(article) => article.id === newArticleId
|
||||
);
|
||||
@@ -144,7 +144,7 @@ export const RightWidgetTab = observer(
|
||||
try {
|
||||
const linkedArticleId = await linkArticle(id);
|
||||
handleCloseSelectModal();
|
||||
// Automatically select the newly linked article
|
||||
|
||||
const newIndex = sight[language].right.findIndex(
|
||||
(article) => article.id === linkedArticleId
|
||||
);
|
||||
@@ -177,30 +177,19 @@ export const RightWidgetTab = observer(
|
||||
const handleDragEnd = (result: DropResult) => {
|
||||
const { source, destination } = result;
|
||||
|
||||
// 1. Guard clause: If dropped outside any droppable area, do nothing.
|
||||
if (!destination) return;
|
||||
|
||||
// Extract source and destination indices
|
||||
const sourceIndex = source.index;
|
||||
const destinationIndex = destination.index;
|
||||
|
||||
// 2. Guard clause: If dropped in the same position, do nothing.
|
||||
if (sourceIndex === destinationIndex) return;
|
||||
|
||||
// 3. Create a new array with reordered articles:
|
||||
// - Create a shallow copy of the current articles array.
|
||||
// This is important for immutability and triggering re-renders.
|
||||
const newRightArticles = [...sight[language].right];
|
||||
|
||||
// - Remove the dragged article from its original position.
|
||||
// `splice` returns an array of removed items, so we destructure the first (and only) one.
|
||||
const [movedArticle] = newRightArticles.splice(sourceIndex, 1);
|
||||
|
||||
// - Insert the moved article into its new position.
|
||||
newRightArticles.splice(destinationIndex, 0, movedArticle);
|
||||
|
||||
// 4. Update the store with the new order:
|
||||
// This will typically trigger a re-render of the component with the updated list.
|
||||
updateRightArticles(newRightArticles);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user