feature/webgl-preview-update #21
@@ -64,6 +64,7 @@ export type GetRouteResponse = {
|
||||
route_sys_number: string;
|
||||
scale_max: number;
|
||||
scale_min: number;
|
||||
video_preview: string;
|
||||
video_timer?: number;
|
||||
icon?: string;
|
||||
icon_size?: number;
|
||||
|
||||
@@ -7,8 +7,12 @@ import {
|
||||
InputLabel,
|
||||
Typography,
|
||||
Box,
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
DialogContent,
|
||||
DialogActions,
|
||||
} from "@mui/material";
|
||||
import { ImageUploadCard } from "@widgets";
|
||||
import { MediaViewer, VideoPreviewCard, ImageUploadCard } from "@widgets";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { ArrowLeft, Loader2, Save, Plus, X } from "lucide-react";
|
||||
import { useEffect, useState, useMemo } from "react";
|
||||
@@ -51,10 +55,14 @@ export const RouteCreatePage = observer(() => {
|
||||
const [centerLat, setCenterLat] = useState("");
|
||||
const [centerLng, setCenterLng] = useState("");
|
||||
const [videoTimer, setVideoTimer] = useState(420);
|
||||
const [videoPreview, setVideoPreview] = useState<string>("");
|
||||
const [icon, setIcon] = useState<string>("");
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isSelectArticleDialogOpen, setIsSelectArticleDialogOpen] =
|
||||
useState(false);
|
||||
const [isSelectVideoDialogOpen, setIsSelectVideoDialogOpen] = useState(false);
|
||||
const [isVideoPreviewOpen, setIsVideoPreviewOpen] = useState(false);
|
||||
const [isUploadVideoDialogOpen, setIsUploadVideoDialogOpen] = useState(false);
|
||||
const [isSelectIconDialogOpen, setIsSelectIconDialogOpen] = useState(false);
|
||||
const [isUploadIconDialogOpen, setIsUploadIconDialogOpen] = useState(false);
|
||||
const [isPreviewIconOpen, setIsPreviewIconOpen] = useState(false);
|
||||
@@ -62,6 +70,7 @@ export const RouteCreatePage = observer(() => {
|
||||
const [activeIconMenuType, setActiveIconMenuType] = useState<
|
||||
"thumbnail" | "watermark_lu" | "watermark_rd" | "image" | null
|
||||
>(null);
|
||||
const [fileToUpload, setFileToUpload] = useState<File | null>(null);
|
||||
const { language } = languageStore;
|
||||
|
||||
useEffect(() => {
|
||||
@@ -137,11 +146,42 @@ export const RouteCreatePage = observer(() => {
|
||||
setIsSelectIconDialogOpen(false);
|
||||
};
|
||||
|
||||
const handleVideoSelect = (media: {
|
||||
id: string;
|
||||
filename: string;
|
||||
media_name?: string;
|
||||
media_type: number;
|
||||
}) => {
|
||||
setVideoPreview(media.id);
|
||||
setIsSelectVideoDialogOpen(false);
|
||||
};
|
||||
|
||||
const handleVideoFileSelect = (file?: File) => {
|
||||
if (file) {
|
||||
setFileToUpload(file);
|
||||
setIsUploadVideoDialogOpen(true);
|
||||
} else {
|
||||
setIsSelectVideoDialogOpen(true);
|
||||
}
|
||||
};
|
||||
|
||||
const handleVideoUpload = (media: {
|
||||
id: string;
|
||||
filename: string;
|
||||
media_name?: string;
|
||||
media_type: number;
|
||||
}) => {
|
||||
setVideoPreview(media.id);
|
||||
setIsUploadVideoDialogOpen(false);
|
||||
setFileToUpload(null);
|
||||
};
|
||||
|
||||
const selectedIconMedia =
|
||||
icon && !isMediaIdEmpty(icon)
|
||||
? mediaStore.media.find((m) => m.id === icon)
|
||||
: null;
|
||||
const effectiveIconUrl = isMediaIdEmpty(icon) ? null : selectedIconMedia?.id ?? icon;
|
||||
const effectiveVideoId = isMediaIdEmpty(videoPreview) ? null : videoPreview;
|
||||
|
||||
const handleCreateRoute = async () => {
|
||||
try {
|
||||
@@ -236,6 +276,7 @@ export const RouteCreatePage = observer(() => {
|
||||
center_latitude,
|
||||
center_longitude,
|
||||
path,
|
||||
video_preview: !isMediaIdEmpty(videoPreview) ? videoPreview : undefined,
|
||||
icon: !isMediaIdEmpty(icon) ? icon : undefined,
|
||||
video_timer: videoTimer,
|
||||
};
|
||||
@@ -436,6 +477,16 @@ export const RouteCreatePage = observer(() => {
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4 max-w-[300px]">
|
||||
<VideoPreviewCard
|
||||
title="Видеозаставка"
|
||||
videoId={effectiveVideoId}
|
||||
onVideoClick={() => setIsVideoPreviewOpen(true)}
|
||||
onDeleteVideoClick={() => setVideoPreview("")}
|
||||
onSelectVideoClick={handleVideoFileSelect}
|
||||
className="w-full"
|
||||
/>
|
||||
</div>
|
||||
</Box>
|
||||
|
||||
<FormControl fullWidth required>
|
||||
@@ -552,6 +603,50 @@ export const RouteCreatePage = observer(() => {
|
||||
onClose={() => setIsSelectArticleDialogOpen(false)}
|
||||
onSelectArticle={handleArticleSelect}
|
||||
/>
|
||||
<SelectMediaDialog
|
||||
open={isSelectVideoDialogOpen}
|
||||
onClose={() => setIsSelectVideoDialogOpen(false)}
|
||||
onSelectMedia={handleVideoSelect}
|
||||
mediaType={2}
|
||||
/>
|
||||
{effectiveVideoId && (
|
||||
<Dialog
|
||||
open={isVideoPreviewOpen}
|
||||
onClose={() => setIsVideoPreviewOpen(false)}
|
||||
maxWidth="md"
|
||||
fullWidth
|
||||
>
|
||||
<DialogTitle>Предпросмотр видео</DialogTitle>
|
||||
<DialogContent>
|
||||
<Box className="flex justify-center items-center p-4">
|
||||
<MediaViewer
|
||||
media={{
|
||||
id: effectiveVideoId,
|
||||
media_type: 2,
|
||||
filename: "video_preview",
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setIsVideoPreviewOpen(false)}>
|
||||
Закрыть
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
)}
|
||||
<UploadMediaDialog
|
||||
open={isUploadVideoDialogOpen}
|
||||
onClose={() => {
|
||||
setIsUploadVideoDialogOpen(false);
|
||||
setFileToUpload(null);
|
||||
}}
|
||||
hardcodeType="video_preview"
|
||||
contextObjectName={routeName || "Маршрут"}
|
||||
contextType="route"
|
||||
initialFile={fileToUpload || undefined}
|
||||
afterUpload={handleVideoUpload}
|
||||
/>
|
||||
<SelectMediaDialog
|
||||
open={isSelectIconDialogOpen}
|
||||
onClose={() => setIsSelectIconDialogOpen(false)}
|
||||
|
||||
@@ -7,8 +7,14 @@ import {
|
||||
InputLabel,
|
||||
Typography,
|
||||
Box,
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
DialogContent,
|
||||
DialogActions,
|
||||
} from "@mui/material";
|
||||
import {
|
||||
MediaViewer,
|
||||
VideoPreviewCard,
|
||||
ImageUploadCard,
|
||||
DeleteModal,
|
||||
} from "@widgets";
|
||||
@@ -48,6 +54,9 @@ export const RouteEditPage = observer(() => {
|
||||
const [isLoadingData, setIsLoadingData] = useState(true);
|
||||
const [isSelectArticleDialogOpen, setIsSelectArticleDialogOpen] =
|
||||
useState(false);
|
||||
const [isSelectVideoDialogOpen, setIsSelectVideoDialogOpen] = useState(false);
|
||||
const [isVideoPreviewOpen, setIsVideoPreviewOpen] = useState(false);
|
||||
const [isUploadVideoDialogOpen, setIsUploadVideoDialogOpen] = useState(false);
|
||||
const [isSelectIconDialogOpen, setIsSelectIconDialogOpen] = useState(false);
|
||||
const [isUploadIconDialogOpen, setIsUploadIconDialogOpen] = useState(false);
|
||||
const [isPreviewIconOpen, setIsPreviewIconOpen] = useState(false);
|
||||
@@ -56,6 +65,7 @@ export const RouteEditPage = observer(() => {
|
||||
const [activeIconMenuType, setActiveIconMenuType] = useState<
|
||||
"thumbnail" | "watermark_lu" | "watermark_rd" | "image" | null
|
||||
>(null);
|
||||
const [fileToUpload, setFileToUpload] = useState<File | null>(null);
|
||||
const { language } = languageStore;
|
||||
const [coordinates, setCoordinates] = useState<string>("");
|
||||
|
||||
@@ -104,6 +114,9 @@ export const RouteEditPage = observer(() => {
|
||||
const effectiveIconUrl = isMediaIdEmpty(editRouteData.icon)
|
||||
? null
|
||||
: (selectedIconMedia?.id ?? editRouteData.icon);
|
||||
const effectiveVideoId = isMediaIdEmpty(editRouteData.video_preview)
|
||||
? null
|
||||
: editRouteData.video_preview;
|
||||
|
||||
useEffect(() => {
|
||||
if (editRouteData.path && editRouteData.path.length > 0) {
|
||||
@@ -225,6 +238,36 @@ export const RouteEditPage = observer(() => {
|
||||
articlesStore.getArticleList();
|
||||
};
|
||||
|
||||
const handleVideoSelect = (media: {
|
||||
id: string;
|
||||
filename: string;
|
||||
media_name?: string;
|
||||
media_type: number;
|
||||
}) => {
|
||||
routeStore.setEditRouteData({ video_preview: media.id });
|
||||
setIsSelectVideoDialogOpen(false);
|
||||
};
|
||||
|
||||
const handleVideoFileSelect = (file?: File) => {
|
||||
if (file) {
|
||||
setFileToUpload(file);
|
||||
setIsUploadVideoDialogOpen(true);
|
||||
} else {
|
||||
setIsSelectVideoDialogOpen(true);
|
||||
}
|
||||
};
|
||||
|
||||
const handleVideoUpload = (media: {
|
||||
id: string;
|
||||
filename: string;
|
||||
media_name?: string;
|
||||
media_type: number;
|
||||
}) => {
|
||||
routeStore.setEditRouteData({ video_preview: media.id });
|
||||
setIsUploadVideoDialogOpen(false);
|
||||
setFileToUpload(null);
|
||||
};
|
||||
|
||||
// Получаем название выбранной статьи для отображения
|
||||
const selectedArticle = articlesStore.articleList.ru.data.find(
|
||||
(article) => article.id === editRouteData.governor_appeal
|
||||
@@ -593,6 +636,18 @@ export const RouteEditPage = observer(() => {
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4 max-w-[300px]">
|
||||
<VideoPreviewCard
|
||||
title="Видеозаставка"
|
||||
videoId={effectiveVideoId}
|
||||
onVideoClick={() => setIsVideoPreviewOpen(true)}
|
||||
onDeleteVideoClick={() =>
|
||||
routeStore.setEditRouteData({ video_preview: "" })
|
||||
}
|
||||
onSelectVideoClick={handleVideoFileSelect}
|
||||
className="w-full"
|
||||
/>
|
||||
</div>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
@@ -638,6 +693,48 @@ export const RouteEditPage = observer(() => {
|
||||
onClose={() => setIsSelectArticleDialogOpen(false)}
|
||||
onSelectArticle={handleArticleSelect}
|
||||
/>
|
||||
<SelectMediaDialog
|
||||
open={isSelectVideoDialogOpen}
|
||||
onClose={() => setIsSelectVideoDialogOpen(false)}
|
||||
onSelectMedia={handleVideoSelect}
|
||||
mediaType={2}
|
||||
/>
|
||||
<Dialog
|
||||
open={isVideoPreviewOpen}
|
||||
onClose={() => setIsVideoPreviewOpen(false)}
|
||||
maxWidth="md"
|
||||
fullWidth
|
||||
>
|
||||
<DialogTitle>Предпросмотр видео</DialogTitle>
|
||||
<DialogContent>
|
||||
<Box className="flex justify-center items-center p-4">
|
||||
{effectiveVideoId && (
|
||||
<MediaViewer
|
||||
media={{
|
||||
id: effectiveVideoId,
|
||||
media_type: 2,
|
||||
filename: "video_preview",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setIsVideoPreviewOpen(false)}>Закрыть</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
<UploadMediaDialog
|
||||
open={isUploadVideoDialogOpen}
|
||||
onClose={() => {
|
||||
setIsUploadVideoDialogOpen(false);
|
||||
setFileToUpload(null);
|
||||
}}
|
||||
hardcodeType="video_preview"
|
||||
contextObjectName={editRouteData.route_name || "Маршрут"}
|
||||
contextType="route"
|
||||
initialFile={fileToUpload || undefined}
|
||||
afterUpload={handleVideoUpload}
|
||||
/>
|
||||
<SelectMediaDialog
|
||||
open={isSelectIconDialogOpen}
|
||||
onClose={() => setIsSelectIconDialogOpen(false)}
|
||||
|
||||
@@ -23,6 +23,7 @@ export type Route = {
|
||||
route_sys_number: string;
|
||||
scale_max: number;
|
||||
scale_min: number;
|
||||
video_preview: string;
|
||||
video_timer: number;
|
||||
};
|
||||
|
||||
@@ -153,16 +154,21 @@ class RouteStore {
|
||||
route_sys_number: "",
|
||||
scale_max: 0,
|
||||
scale_min: 0,
|
||||
video_preview: "" as string | undefined,
|
||||
video_timer: 420,
|
||||
};
|
||||
|
||||
setEditRouteData = (data: any) => {
|
||||
const routeData = { ...data };
|
||||
delete routeData.video_preview;
|
||||
this.editRouteData = { ...this.editRouteData, ...routeData };
|
||||
this.editRouteData = { ...this.editRouteData, ...data };
|
||||
};
|
||||
|
||||
editRoute = async (id: number) => {
|
||||
if (
|
||||
!this.editRouteData.video_preview ||
|
||||
isMediaIdEmpty(this.editRouteData.video_preview)
|
||||
) {
|
||||
delete this.editRouteData.video_preview;
|
||||
}
|
||||
if (!this.editRouteData.icon || isMediaIdEmpty(this.editRouteData.icon)) {
|
||||
delete (this.editRouteData as any).icon;
|
||||
}
|
||||
@@ -174,7 +180,6 @@ class RouteStore {
|
||||
center_latitude: parseFloat(this.editRouteData.center_latitude),
|
||||
center_longitude: parseFloat(this.editRouteData.center_longitude),
|
||||
};
|
||||
delete dataToSend.video_preview;
|
||||
if (
|
||||
this.editRouteData.governor_appeal === 0 ||
|
||||
!this.editRouteData.governor_appeal
|
||||
|
||||
Reference in New Issue
Block a user