changes for 15.05
This commit is contained in:
parent
ab1fd6b22a
commit
34423b73a3
@ -162,9 +162,7 @@ export const CreateSightArticle = ({
|
|||||||
|
|
||||||
// Получаем существующие статьи для определения порядкового номера
|
// Получаем существующие статьи для определения порядкового номера
|
||||||
const existingItemsResponse = await axiosInstance.get(
|
const existingItemsResponse = await axiosInstance.get(
|
||||||
`${
|
`${import.meta.env.VITE_KRBL_API}/${parentResource}/${parentId}/${childResource}`
|
||||||
import.meta.env.VITE_KRBL_API
|
|
||||||
}/${parentResource}/${parentId}/${childResource}`
|
|
||||||
);
|
);
|
||||||
const existingItems = existingItemsResponse.data ?? [];
|
const existingItems = existingItemsResponse.data ?? [];
|
||||||
const nextPageNum = existingItems.length + 1;
|
const nextPageNum = existingItems.length + 1;
|
||||||
@ -172,14 +170,26 @@ export const CreateSightArticle = ({
|
|||||||
if (!left) {
|
if (!left) {
|
||||||
// Привязываем статью к достопримечательности если она не левая
|
// Привязываем статью к достопримечательности если она не левая
|
||||||
await axiosInstance.post(
|
await axiosInstance.post(
|
||||||
`${
|
`${import.meta.env.VITE_KRBL_API}/${parentResource}/${parentId}/${childResource}/`,
|
||||||
import.meta.env.VITE_KRBL_API
|
|
||||||
}/${parentResource}/${parentId}/${childResource}/`,
|
|
||||||
{
|
{
|
||||||
[`${childResource}_id`]: itemId,
|
[`${childResource}_id`]: itemId,
|
||||||
page_num: nextPageNum,
|
page_num: nextPageNum,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
const response = await axiosInstance.get(
|
||||||
|
`${import.meta.env.VITE_KRBL_API}/${parentResource}/${parentId}/`
|
||||||
|
);
|
||||||
|
const data = response.data;
|
||||||
|
if(data) {
|
||||||
|
await axiosInstance.patch(
|
||||||
|
`${import.meta.env.VITE_KRBL_API}/${parentResource}/${parentId}/`,
|
||||||
|
{
|
||||||
|
...data,
|
||||||
|
left_article: itemId
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Загружаем все медиа файлы и получаем их ID
|
// Загружаем все медиа файлы и получаем их ID
|
||||||
@ -220,7 +230,7 @@ export const CreateSightArticle = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box component="form" onSubmit={handleSubmitItem(handleCreate)}>
|
<Box>
|
||||||
<TextField
|
<TextField
|
||||||
{...registerItem("heading", {
|
{...registerItem("heading", {
|
||||||
required: "Это поле является обязательным",
|
required: "Это поле является обязательным",
|
||||||
@ -335,7 +345,7 @@ export const CreateSightArticle = ({
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box sx={{ mt: 2, display: "flex", gap: 2 }}>
|
<Box sx={{ mt: 2, display: "flex", gap: 2 }}>
|
||||||
<Button variant="contained" color="primary" type="submit">
|
<Button variant="contained" color="primary" onClick={handleSubmitItem(handleCreate)}>
|
||||||
Создать
|
Создать
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
|
@ -69,6 +69,7 @@ type LinkedItemsProps<T> = {
|
|||||||
dontRecurse?: boolean;
|
dontRecurse?: boolean;
|
||||||
disableCreation?: boolean;
|
disableCreation?: boolean;
|
||||||
updatedLinkedItems?: T[];
|
updatedLinkedItems?: T[];
|
||||||
|
refresh?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
const reorder = (list: any[], startIndex: number, endIndex: number) => {
|
const reorder = (list: any[], startIndex: number, endIndex: number) => {
|
||||||
@ -126,7 +127,8 @@ export const LinkedItemsContents = <T extends { id: number; [key: string]: any }
|
|||||||
type,
|
type,
|
||||||
onUpdate,
|
onUpdate,
|
||||||
disableCreation = false,
|
disableCreation = false,
|
||||||
updatedLinkedItems
|
updatedLinkedItems,
|
||||||
|
refresh
|
||||||
}: LinkedItemsProps<T>) => {
|
}: LinkedItemsProps<T>) => {
|
||||||
const { language } = languageStore;
|
const { language } = languageStore;
|
||||||
const { setArticleModalOpenAction, setArticleIdAction } = articleStore;
|
const { setArticleModalOpenAction, setArticleIdAction } = articleStore;
|
||||||
@ -207,7 +209,7 @@ export const LinkedItemsContents = <T extends { id: number; [key: string]: any }
|
|||||||
setLinkedItems([]);
|
setLinkedItems([]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [parentId, parentResource, childResource, language]);
|
}, [parentId, parentResource, childResource, language, refresh]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (type === "edit") {
|
if (type === "edit") {
|
||||||
|
@ -7,7 +7,7 @@ import "easymde/dist/easymde.min.css";
|
|||||||
import { memo, useMemo, useEffect, useCallback, useState } from "react";
|
import { memo, useMemo, useEffect, useCallback, useState } from "react";
|
||||||
import { MarkdownEditor } from "../../MarkdownEditor";
|
import { MarkdownEditor } from "../../MarkdownEditor";
|
||||||
import { Edit } from "@refinedev/mui";
|
import { Edit } from "@refinedev/mui";
|
||||||
import { languageStore } from "../../../store/LanguageStore";
|
import { EVERY_LANGUAGE, languageStore } from "../../../store/LanguageStore";
|
||||||
import { LanguageSwitch } from "../../LanguageSwitch/index";
|
import { LanguageSwitch } from "../../LanguageSwitch/index";
|
||||||
import { useDropzone } from "react-dropzone";
|
import { useDropzone } from "react-dropzone";
|
||||||
import {
|
import {
|
||||||
@ -24,7 +24,7 @@ type MediaFile = {
|
|||||||
file: File;
|
file: File;
|
||||||
preview: string;
|
preview: string;
|
||||||
uploading: boolean;
|
uploading: boolean;
|
||||||
mediaId?: number;
|
media_id?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
const style = {
|
const style = {
|
||||||
@ -42,26 +42,18 @@ const style = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const ArticleEditModal = observer(() => {
|
export const ArticleEditModal = observer(() => {
|
||||||
|
const { language } = languageStore;
|
||||||
const [articleData, setArticleData] = useState({
|
const [articleData, setArticleData] = useState({
|
||||||
ru: {
|
heading: EVERY_LANGUAGE(language),
|
||||||
heading: "",
|
body: EVERY_LANGUAGE(language),
|
||||||
body: "",
|
|
||||||
},
|
|
||||||
en: {
|
|
||||||
heading: "",
|
|
||||||
body: "",
|
|
||||||
},
|
|
||||||
zh: {
|
|
||||||
heading: "",
|
|
||||||
body: "",
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
const { articleModalOpen, setArticleModalOpenAction, selectedArticleId } =
|
const { articleModalOpen, setArticleModalOpenAction, selectedArticleId } =
|
||||||
articleStore;
|
articleStore;
|
||||||
const { language } = languageStore;
|
|
||||||
|
|
||||||
const [mediaFiles, setMediaFiles] = useState<MediaFile[]>([]);
|
const [mediaFiles, setMediaFiles] = useState<MediaFile[]>([]);
|
||||||
|
|
||||||
|
const [refresh, setRefresh] = useState(0);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
setArticleModalOpenAction(false);
|
setArticleModalOpenAction(false);
|
||||||
@ -103,6 +95,7 @@ export const ArticleEditModal = observer(() => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
setMediaFiles(mediaFiles);
|
setMediaFiles(mediaFiles);
|
||||||
|
setRefresh(refresh+1);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error loading existing media:", error);
|
console.error("Error loading existing media:", error);
|
||||||
}
|
}
|
||||||
@ -131,7 +124,8 @@ export const ArticleEditModal = observer(() => {
|
|||||||
onMutationSuccess: async () => {
|
onMutationSuccess: async () => {
|
||||||
try {
|
try {
|
||||||
// Upload new media files
|
// Upload new media files
|
||||||
const newMediaFiles = mediaFiles.filter((file) => !file.mediaId);
|
const newMediaFiles = mediaFiles.filter((file) => !file.media_id);
|
||||||
|
const existingMediaAmount = mediaFiles.filter((file) => file.media_id).length;
|
||||||
const mediaIds = await Promise.all(
|
const mediaIds = await Promise.all(
|
||||||
newMediaFiles.map(async (mediaFile) => {
|
newMediaFiles.map(async (mediaFile) => {
|
||||||
return await uploadMedia(mediaFile);
|
return await uploadMedia(mediaFile);
|
||||||
@ -147,7 +141,7 @@ export const ArticleEditModal = observer(() => {
|
|||||||
}/article/${selectedArticleId}/media/`,
|
}/article/${selectedArticleId}/media/`,
|
||||||
{
|
{
|
||||||
media_id: mediaId,
|
media_id: mediaId,
|
||||||
media_order: index + 1,
|
media_order: index + existingMediaAmount + 1,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -169,27 +163,25 @@ export const ArticleEditModal = observer(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (articleData[language as keyof typeof articleData]?.heading) {
|
if (articleData.heading[language]) {
|
||||||
setValue(
|
setValue("heading", articleData.heading[language])
|
||||||
"heading",
|
|
||||||
articleData[language as keyof typeof articleData]?.heading || ""
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (articleData[language as keyof typeof articleData]?.body) {
|
if (articleData.body[language]) {
|
||||||
setValue(
|
setValue("body", articleData.body[language])
|
||||||
"body",
|
|
||||||
articleData[language as keyof typeof articleData]?.body || ""
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}, [language, articleData, setValue]);
|
}, [language, articleData, setValue]);
|
||||||
|
|
||||||
const handleLanguageChange = () => {
|
const handleLanguageChange = () => {
|
||||||
setArticleData((prevData) => ({
|
setArticleData((prevData) => ({
|
||||||
...prevData,
|
...prevData,
|
||||||
[language]: {
|
heading: {
|
||||||
heading: watch("heading") || "",
|
...prevData.heading,
|
||||||
body: watch("body") || "",
|
[language]: watch("heading") ?? ""
|
||||||
},
|
},
|
||||||
|
body: {
|
||||||
|
...prevData.body,
|
||||||
|
[language]: watch("body") ?? ""
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -240,10 +232,10 @@ export const ArticleEditModal = observer(() => {
|
|||||||
const mediaFile = mediaFiles[index];
|
const mediaFile = mediaFiles[index];
|
||||||
|
|
||||||
// If it's an existing media file (has mediaId), delete it from the server
|
// If it's an existing media file (has mediaId), delete it from the server
|
||||||
if (mediaFile.mediaId) {
|
if (mediaFile.media_id) {
|
||||||
try {
|
try {
|
||||||
await axiosInstance.delete(
|
await axiosInstance.delete(
|
||||||
`${import.meta.env.VITE_KRBL_API}/media/${mediaFile.mediaId}`
|
`${import.meta.env.VITE_KRBL_API}/media/${mediaFile.media_id}`
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error deleting media:", error);
|
console.error("Error deleting media:", error);
|
||||||
|
@ -13,7 +13,7 @@ export function MediaView({media} : Readonly<{media?: MediaData}>) {
|
|||||||
const token = localStorage.getItem(TOKEN_KEY);
|
const token = localStorage.getItem(TOKEN_KEY);
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{maxHeight: "300px", width: "100%", display: "flex", justifyContent: "center"}}
|
sx={{maxHeight: "300px", width: "100%", display: "flex", flexGrow: 1, justifyContent: "center"}}
|
||||||
>
|
>
|
||||||
{media?.media_type === 1 && (
|
{media?.media_type === 1 && (
|
||||||
<img
|
<img
|
||||||
|
@ -23,8 +23,6 @@ export const ArticleEdit = observer(() => {
|
|||||||
body: EVERY_LANGUAGE("")
|
body: EVERY_LANGUAGE("")
|
||||||
});
|
});
|
||||||
const { id: articleId } = useParams<{ id: string }>();
|
const { id: articleId } = useParams<{ id: string }>();
|
||||||
const [preview, setPreview] = useState("");
|
|
||||||
const [headingPreview, setHeadingPreview] = useState("");
|
|
||||||
const simpleMDEOptions = useMemo(
|
const simpleMDEOptions = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
placeholder: "Введите контент в формате Markdown...",
|
placeholder: "Введите контент в формате Markdown...",
|
||||||
@ -42,6 +40,7 @@ export const ArticleEdit = observer(() => {
|
|||||||
watch,
|
watch,
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
setValue,
|
setValue,
|
||||||
|
getValues,
|
||||||
} = useForm<{ heading: string; body: string }>({
|
} = useForm<{ heading: string; body: string }>({
|
||||||
refineCoreProps: META_LANGUAGE(language)
|
refineCoreProps: META_LANGUAGE(language)
|
||||||
});
|
});
|
||||||
@ -50,15 +49,21 @@ export const ArticleEdit = observer(() => {
|
|||||||
const headingContent = watch("heading");
|
const headingContent = watch("heading");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setValue("heading", articleData.heading[language] ?? "");
|
console.log(articleData)
|
||||||
setHeadingPreview(articleData.heading[language] ?? "");
|
}, [articleData])
|
||||||
setValue("body", articleData.body[language] ?? "");
|
|
||||||
setPreview(articleData.body[language] ?? "");
|
useEffect(() => {
|
||||||
}, [language, articleData, setValue]);
|
console.log("Trying to udpate")
|
||||||
|
//setHeadingPreview(articleData.heading[language] ?? "");
|
||||||
|
//setPreview(articleData.body[language] ?? "");
|
||||||
|
if(articleData.heading[language])
|
||||||
|
setValue("heading", articleData.heading[language]);
|
||||||
|
if(articleData.body[language])
|
||||||
|
setValue("body", articleData.body[language]);
|
||||||
|
}, [language]);
|
||||||
|
|
||||||
function updateTranslations(update: boolean = true) {
|
function updateTranslations(update: boolean = true) {
|
||||||
const newArticleData = {
|
const newArticleData = {
|
||||||
...articleData,
|
|
||||||
heading: {
|
heading: {
|
||||||
...articleData.heading,
|
...articleData.heading,
|
||||||
[language]: watch("heading") ?? "",
|
[language]: watch("heading") ?? "",
|
||||||
@ -75,25 +80,16 @@ export const ArticleEdit = observer(() => {
|
|||||||
const handleLanguageChange = (lang: Languages) => {
|
const handleLanguageChange = (lang: Languages) => {
|
||||||
updateTranslations();
|
updateTranslations();
|
||||||
setLanguageAction(lang);
|
setLanguageAction(lang);
|
||||||
|
console.log("Setting preview to", articleData.body[lang] ?? "")
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFormSubmit = handleSubmit((values: FieldValues) => {
|
const handleFormSubmit = handleSubmit((values: FieldValues) => {
|
||||||
const newTranslations = updateTranslations(false);
|
|
||||||
console.log(newTranslations);
|
|
||||||
return onFinish({
|
return onFinish({
|
||||||
translations: newTranslations
|
translations: updateTranslations(false)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
const { data: mediaData, refetch } = useList<MediaItem>({
|
||||||
setPreview(bodyContent ?? "");
|
|
||||||
}, [bodyContent]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setHeadingPreview(headingContent ?? "");
|
|
||||||
}, [headingContent]);
|
|
||||||
|
|
||||||
const { data: mediaData } = useList<MediaItem>({
|
|
||||||
resource: `article/${articleId}/media`,
|
resource: `article/${articleId}/media`,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -156,6 +152,7 @@ export const ArticleEdit = observer(() => {
|
|||||||
childResource="media"
|
childResource="media"
|
||||||
fields={mediaFields}
|
fields={mediaFields}
|
||||||
title="медиа"
|
title="медиа"
|
||||||
|
onUpdate={refetch}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
@ -191,7 +188,7 @@ export const ArticleEdit = observer(() => {
|
|||||||
mb: 3,
|
mb: 3,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{headingPreview}
|
{headingContent}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
{/* Markdown контент */}
|
{/* Markdown контент */}
|
||||||
@ -235,7 +232,7 @@ export const ArticleEdit = observer(() => {
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ReactMarkdown>{preview}</ReactMarkdown>
|
<ReactMarkdown>{bodyContent}</ReactMarkdown>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Привязанные медиа */}
|
{/* Привязанные медиа */}
|
||||||
@ -256,8 +253,10 @@ export const ArticleEdit = observer(() => {
|
|||||||
<Box
|
<Box
|
||||||
key={media.id}
|
key={media.id}
|
||||||
sx={{
|
sx={{
|
||||||
width: 120,
|
display: "flex",
|
||||||
height: 120,
|
width: "45%",
|
||||||
|
height: "45%",
|
||||||
|
aspectRatio: "1/1",
|
||||||
borderRadius: 1,
|
borderRadius: 1,
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
border: "1px solid",
|
border: "1px solid",
|
||||||
|
@ -3,7 +3,7 @@ import { Create, useAutocomplete } from "@refinedev/mui";
|
|||||||
import { useForm } from "@refinedev/react-hook-form";
|
import { useForm } from "@refinedev/react-hook-form";
|
||||||
import { Controller } from "react-hook-form";
|
import { Controller } from "react-hook-form";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { languageStore } from "../../store/LanguageStore";
|
import { languageStore, META_LANGUAGE } from "../../store/LanguageStore";
|
||||||
export const CarrierCreate = observer(() => {
|
export const CarrierCreate = observer(() => {
|
||||||
const { language } = languageStore;
|
const { language } = languageStore;
|
||||||
const {
|
const {
|
||||||
@ -13,13 +13,7 @@ export const CarrierCreate = observer(() => {
|
|||||||
control,
|
control,
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
} = useForm({
|
} = useForm({
|
||||||
refineCoreProps: {
|
refineCoreProps: META_LANGUAGE(language)
|
||||||
meta: {
|
|
||||||
headers: {
|
|
||||||
"Accept-Language": language,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const { autocompleteProps: cityAutocompleteProps } = useAutocomplete({
|
const { autocompleteProps: cityAutocompleteProps } = useAutocomplete({
|
||||||
|
@ -39,7 +39,7 @@ export const CarrierEdit = observer(() => {
|
|||||||
value,
|
value,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
...META_LANGUAGE(language)
|
...META_LANGUAGE("ru")
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -233,7 +233,8 @@ export const CarrierEdit = observer(() => {
|
|||||||
return options.filter((option) =>
|
return options.filter((option) =>
|
||||||
option.media_name
|
option.media_name
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.includes(inputValue.toLowerCase())
|
.includes(inputValue.toLowerCase()) &&
|
||||||
|
option.media_type == 3
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
renderInput={(params) => (
|
renderInput={(params) => (
|
||||||
|
@ -34,6 +34,23 @@ export const RouteCreate = () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { autocompleteProps: governorAppealAutocompleteProps } = useAutocomplete({
|
||||||
|
resource: "article",
|
||||||
|
|
||||||
|
onSearch: (value) => [
|
||||||
|
{
|
||||||
|
field: "heading",
|
||||||
|
operator: "contains",
|
||||||
|
value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "media_type",
|
||||||
|
operator: "contains",
|
||||||
|
value,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Create isLoading={formLoading} saveButtonProps={saveButtonProps}>
|
<Create isLoading={formLoading} saveButtonProps={saveButtonProps}>
|
||||||
<Box
|
<Box
|
||||||
@ -94,7 +111,7 @@ export const RouteCreate = () => {
|
|||||||
helperText={(errors as any)?.route_number?.message}
|
helperText={(errors as any)?.route_number?.message}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
fullWidth
|
fullWidth
|
||||||
InputLabelProps={{ shrink: true }}
|
slotProps={{inputLabel: {shrink: true}}}
|
||||||
type="text"
|
type="text"
|
||||||
label={"Номер маршрута *"}
|
label={"Номер маршрута *"}
|
||||||
name="route_number"
|
name="route_number"
|
||||||
@ -174,7 +191,7 @@ export const RouteCreate = () => {
|
|||||||
helperText={(errors as any)?.path?.message}
|
helperText={(errors as any)?.path?.message}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
fullWidth
|
fullWidth
|
||||||
InputLabelProps={{ shrink: true }}
|
slotProps={{inputLabel: {shrink: true}}}
|
||||||
type="text"
|
type="text"
|
||||||
label={"Координаты маршрута *"}
|
label={"Координаты маршрута *"}
|
||||||
name="path"
|
name="path"
|
||||||
@ -192,26 +209,54 @@ export const RouteCreate = () => {
|
|||||||
helperText={(errors as any)?.route_sys_number?.message}
|
helperText={(errors as any)?.route_sys_number?.message}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
fullWidth
|
fullWidth
|
||||||
InputLabelProps={{ shrink: true }}
|
slotProps={{inputLabel: {shrink: true}}}
|
||||||
type="number"
|
type="number"
|
||||||
label={"Системный номер маршрута *"}
|
label={"Системный номер маршрута *"}
|
||||||
name="route_sys_number"
|
name="route_sys_number"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextField
|
<Controller
|
||||||
{...register("governor_appeal", {
|
control={control}
|
||||||
// required: 'Это поле является обязательным',
|
|
||||||
setValueAs: (value) => Number(value),
|
|
||||||
})}
|
|
||||||
error={!!(errors as any)?.governor_appeal}
|
|
||||||
helperText={(errors as any)?.governor_appeal?.message}
|
|
||||||
margin="normal"
|
|
||||||
fullWidth
|
|
||||||
InputLabelProps={{ shrink: true }}
|
|
||||||
type="number"
|
|
||||||
label={"Обращение губернатора"}
|
|
||||||
name="governor_appeal"
|
name="governor_appeal"
|
||||||
/>
|
defaultValue={null}
|
||||||
|
render={({ field }) => (
|
||||||
|
<Autocomplete
|
||||||
|
{...governorAppealAutocompleteProps}
|
||||||
|
value={
|
||||||
|
governorAppealAutocompleteProps.options.find(
|
||||||
|
(option) => option.id === field.value
|
||||||
|
) ?? null
|
||||||
|
}
|
||||||
|
onChange={(_, value) => {
|
||||||
|
field.onChange(value?.id ?? "");
|
||||||
|
}}
|
||||||
|
getOptionLabel={(item) => {
|
||||||
|
return item ? item.heading : "";
|
||||||
|
}}
|
||||||
|
isOptionEqualToValue={(option, value) => {
|
||||||
|
return option.id === value?.id;
|
||||||
|
}}
|
||||||
|
filterOptions={(options, { inputValue }) => {
|
||||||
|
return options.filter((option) =>
|
||||||
|
option.heading
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(inputValue.toLowerCase())
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
renderInput={(params) => (
|
||||||
|
<TextField
|
||||||
|
{...params}
|
||||||
|
label="Обращение губернатора"
|
||||||
|
margin="normal"
|
||||||
|
variant="outlined"
|
||||||
|
error={!!errors.arms}
|
||||||
|
helperText={(errors as any)?.arms?.message}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
<TextField
|
<TextField
|
||||||
{...register("scale_min", {
|
{...register("scale_min", {
|
||||||
@ -222,7 +267,7 @@ export const RouteCreate = () => {
|
|||||||
helperText={(errors as any)?.scale_min?.message}
|
helperText={(errors as any)?.scale_min?.message}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
fullWidth
|
fullWidth
|
||||||
InputLabelProps={{ shrink: true }}
|
slotProps={{inputLabel: {shrink: true}}}
|
||||||
type="number"
|
type="number"
|
||||||
label={"Масштаб (мин)"}
|
label={"Масштаб (мин)"}
|
||||||
name="scale_min"
|
name="scale_min"
|
||||||
@ -237,7 +282,7 @@ export const RouteCreate = () => {
|
|||||||
helperText={(errors as any)?.scale_max?.message}
|
helperText={(errors as any)?.scale_max?.message}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
fullWidth
|
fullWidth
|
||||||
InputLabelProps={{ shrink: true }}
|
slotProps={{inputLabel: {shrink: true}}}
|
||||||
type="number"
|
type="number"
|
||||||
label={"Масштаб (макс)"}
|
label={"Масштаб (макс)"}
|
||||||
name="scale_max"
|
name="scale_max"
|
||||||
@ -252,7 +297,7 @@ export const RouteCreate = () => {
|
|||||||
helperText={(errors as any)?.rotate?.message}
|
helperText={(errors as any)?.rotate?.message}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
fullWidth
|
fullWidth
|
||||||
InputLabelProps={{ shrink: true }}
|
slotProps={{inputLabel: {shrink: true}}}
|
||||||
type="number"
|
type="number"
|
||||||
label={"Поворот"}
|
label={"Поворот"}
|
||||||
name="rotate"
|
name="rotate"
|
||||||
@ -267,7 +312,7 @@ export const RouteCreate = () => {
|
|||||||
helperText={(errors as any)?.center_latitude?.message}
|
helperText={(errors as any)?.center_latitude?.message}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
fullWidth
|
fullWidth
|
||||||
InputLabelProps={{ shrink: true }}
|
slotProps={{inputLabel: {shrink: true}}}
|
||||||
type="number"
|
type="number"
|
||||||
label={"Центр. широта"}
|
label={"Центр. широта"}
|
||||||
name="center_latitude"
|
name="center_latitude"
|
||||||
@ -282,7 +327,7 @@ export const RouteCreate = () => {
|
|||||||
helperText={(errors as any)?.center_longitude?.message}
|
helperText={(errors as any)?.center_longitude?.message}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
fullWidth
|
fullWidth
|
||||||
InputLabelProps={{ shrink: true }}
|
slotProps={{inputLabel: {shrink: true}}}
|
||||||
type="number"
|
type="number"
|
||||||
label={"Центр. долгота"}
|
label={"Центр. долгота"}
|
||||||
name="center_longitude"
|
name="center_longitude"
|
||||||
|
@ -19,8 +19,12 @@ import {
|
|||||||
vehicleFields,
|
vehicleFields,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
import { META_LANGUAGE, languageStore } from "@stores";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { LanguageSelector } from "@ui";
|
||||||
|
|
||||||
export const RouteEdit = () => {
|
export const RouteEdit = observer(() => {
|
||||||
|
const { language } = languageStore;
|
||||||
const {
|
const {
|
||||||
saveButtonProps,
|
saveButtonProps,
|
||||||
register,
|
register,
|
||||||
@ -29,7 +33,9 @@ export const RouteEdit = () => {
|
|||||||
refineCore: { queryResult },
|
refineCore: { queryResult },
|
||||||
setValue,
|
setValue,
|
||||||
watch,
|
watch,
|
||||||
} = useForm({});
|
} = useForm({
|
||||||
|
refineCoreProps: META_LANGUAGE(language)
|
||||||
|
});
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const { id: routeId } = useParams<{ id: string }>();
|
const { id: routeId } = useParams<{ id: string }>();
|
||||||
@ -53,6 +59,7 @@ export const RouteEdit = () => {
|
|||||||
value,
|
value,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
...META_LANGUAGE(language)
|
||||||
});
|
});
|
||||||
|
|
||||||
const { autocompleteProps: governorAppealAutocompleteProps } = useAutocomplete({
|
const { autocompleteProps: governorAppealAutocompleteProps } = useAutocomplete({
|
||||||
@ -69,7 +76,8 @@ export const RouteEdit = () => {
|
|||||||
operator: "contains",
|
operator: "contains",
|
||||||
value,
|
value,
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
|
...META_LANGUAGE(language)
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -82,6 +90,7 @@ export const RouteEdit = () => {
|
|||||||
sx={{ display: "flex", flexDirection: "column"}}
|
sx={{ display: "flex", flexDirection: "column"}}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
>
|
>
|
||||||
|
<LanguageSelector />
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="carrier_id"
|
name="carrier_id"
|
||||||
@ -393,4 +402,4 @@ export const RouteEdit = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
</Edit>
|
</Edit>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
@ -13,11 +13,15 @@ import MapIcon from '@mui/icons-material/Map';
|
|||||||
|
|
||||||
import { localeText } from "../../locales/ru/localeText";
|
import { localeText } from "../../locales/ru/localeText";
|
||||||
import { useLink } from "@refinedev/core";
|
import { useLink } from "@refinedev/core";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { languageStore, META_LANGUAGE } from "@stores";
|
||||||
|
|
||||||
export const RouteList = () => {
|
export const RouteList = observer(() => {
|
||||||
const Link = useLink();
|
const Link = useLink();
|
||||||
|
const { language } = languageStore;
|
||||||
const { dataGridProps } = useDataGrid({
|
const { dataGridProps } = useDataGrid({
|
||||||
resource: "route/",
|
resource: "route/",
|
||||||
|
meta: META_LANGUAGE(language)
|
||||||
});
|
});
|
||||||
|
|
||||||
const columns = React.useMemo<GridColDef[]>(
|
const columns = React.useMemo<GridColDef[]>(
|
||||||
@ -177,7 +181,8 @@ export const RouteList = () => {
|
|||||||
columns={columns}
|
columns={columns}
|
||||||
localeText={localeText}
|
localeText={localeText}
|
||||||
getRowId={(row: any) => row.id}
|
getRowId={(row: any) => row.id}
|
||||||
|
languageEnabled
|
||||||
/>
|
/>
|
||||||
</List>
|
</List>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
@ -11,8 +11,9 @@ import {
|
|||||||
vehicleFields,
|
vehicleFields,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
import { useNavigate, useParams } from "react-router";
|
import { useNavigate, useParams } from "react-router";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
|
|
||||||
export const RouteShow = () => {
|
export const RouteShow = observer(() => {
|
||||||
const { query } = useShow({});
|
const { query } = useShow({});
|
||||||
const { data, isLoading } = query;
|
const { data, isLoading } = query;
|
||||||
const record = data?.data;
|
const record = data?.data;
|
||||||
@ -115,4 +116,4 @@ export const RouteShow = () => {
|
|||||||
</Stack>
|
</Stack>
|
||||||
</Show>
|
</Show>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
@ -76,6 +76,7 @@ export const SightEdit = observer(() => {
|
|||||||
formState: { errors },
|
formState: { errors },
|
||||||
} = useForm({
|
} = useForm({
|
||||||
refineCoreProps: META_LANGUAGE(language),
|
refineCoreProps: META_LANGUAGE(language),
|
||||||
|
warnWhenUnsavedChanges: false
|
||||||
});
|
});
|
||||||
|
|
||||||
const getMedia = async (id?: string | number) => {
|
const getMedia = async (id?: string | number) => {
|
||||||
@ -119,6 +120,7 @@ export const SightEdit = observer(() => {
|
|||||||
}>();
|
}>();
|
||||||
|
|
||||||
const [tabValue, setTabValue] = useState(0);
|
const [tabValue, setTabValue] = useState(0);
|
||||||
|
|
||||||
const { autocompleteProps: mediaAutocompleteProps } = useAutocomplete({
|
const { autocompleteProps: mediaAutocompleteProps } = useAutocomplete({
|
||||||
resource: "media",
|
resource: "media",
|
||||||
onSearch: (value) => [
|
onSearch: (value) => [
|
||||||
@ -144,7 +146,8 @@ export const SightEdit = observer(() => {
|
|||||||
operator: "contains",
|
operator: "contains",
|
||||||
value,
|
value,
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -216,13 +219,6 @@ export const SightEdit = observer(() => {
|
|||||||
const watermarkLUContent = watch("watermark_lu");
|
const watermarkLUContent = watch("watermark_lu");
|
||||||
const watermarkRDContent = watch("watermark_rd");
|
const watermarkRDContent = watch("watermark_rd");
|
||||||
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// return () => {
|
|
||||||
// setLanguageAction("ru");
|
|
||||||
// };
|
|
||||||
// }, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCoordinatesPreview({
|
setCoordinatesPreview({
|
||||||
latitude: latitudeContent ?? "",
|
latitude: latitudeContent ?? "",
|
||||||
@ -290,7 +286,7 @@ export const SightEdit = observer(() => {
|
|||||||
media,
|
media,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, [leftArticleId]);
|
}, [leftArticleId, articleAutocompleteProps.loading]);
|
||||||
|
|
||||||
function updateTranslations(update: boolean = true) {
|
function updateTranslations(update: boolean = true) {
|
||||||
const newSightData = {
|
const newSightData = {
|
||||||
@ -621,18 +617,48 @@ export const SightEdit = observer(() => {
|
|||||||
Редактировать выбранную левую статью
|
Редактировать выбранную левую статью
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Link to="/article/create">
|
<>
|
||||||
<Button
|
<Typography
|
||||||
variant="outlined"
|
variant="h6"
|
||||||
size="large"
|
gutterBottom
|
||||||
|
px={2}
|
||||||
|
py={.5}
|
||||||
|
|
||||||
sx={{
|
sx={{
|
||||||
width: "100%",
|
color: "text.primary"
|
||||||
}}
|
}}
|
||||||
color="secondary"
|
|
||||||
>
|
>
|
||||||
Создать новую статью
|
Создать и прикрепить новую статью:
|
||||||
</Button>
|
</Typography>
|
||||||
</Link>
|
<CreateSightArticle
|
||||||
|
language={language}
|
||||||
|
parentId={sightId!}
|
||||||
|
parentResource="sight"
|
||||||
|
childResource="article"
|
||||||
|
title="статью"
|
||||||
|
left
|
||||||
|
setHeadingParent={(heading) => {
|
||||||
|
//console.log("Updating", heading)
|
||||||
|
setCreatingArticleHeading(heading);
|
||||||
|
}}
|
||||||
|
setBodyParent={(body) => {
|
||||||
|
setCreatingArticleBody(body);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
|
||||||
|
// <Link to="/article/create">
|
||||||
|
// <Button
|
||||||
|
// variant="outlined"
|
||||||
|
// size="large"
|
||||||
|
// sx={{
|
||||||
|
// width: "100%",
|
||||||
|
// }}
|
||||||
|
// color="secondary"
|
||||||
|
// >
|
||||||
|
// Создать новую статью
|
||||||
|
// </Button>
|
||||||
|
// </Link>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
@ -678,7 +704,7 @@ export const SightEdit = observer(() => {
|
|||||||
mb: 3,
|
mb: 3,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{leftArticleData?.heading}
|
{leftArticleId ? leftArticleData?.heading : creatingArticleHeading}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
{/* Адрес */}
|
{/* Адрес */}
|
||||||
@ -706,7 +732,7 @@ export const SightEdit = observer(() => {
|
|||||||
theme.palette.mode === "dark" ? "grey.300" : "grey.800",
|
theme.palette.mode === "dark" ? "grey.300" : "grey.800",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{leftArticleData?.body}
|
{leftArticleId ? leftArticleData?.body : creatingArticleBody}
|
||||||
</Box>
|
</Box>
|
||||||
</Typography>
|
</Typography>
|
||||||
</Paper>
|
</Paper>
|
||||||
@ -807,7 +833,7 @@ export const SightEdit = observer(() => {
|
|||||||
}}
|
}}
|
||||||
onClick={() => setArticleAdditionMode("creating")}
|
onClick={() => setArticleAdditionMode("creating")}
|
||||||
>
|
>
|
||||||
Создать новую статью
|
Создать и привязать новую статью
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
@ -870,7 +896,7 @@ export const SightEdit = observer(() => {
|
|||||||
parentResource="sight"
|
parentResource="sight"
|
||||||
childResource="article"
|
childResource="article"
|
||||||
title="статью"
|
title="статью"
|
||||||
left
|
//left
|
||||||
setHeadingParent={(heading) => {
|
setHeadingParent={(heading) => {
|
||||||
console.log("Updating", heading)
|
console.log("Updating", heading)
|
||||||
setCreatingArticleHeading(heading);
|
setCreatingArticleHeading(heading);
|
||||||
|
Loading…
Reference in New Issue
Block a user