underline

This commit is contained in:
Spynder
2025-05-20 00:09:57 +03:00
parent d9bbe4f234
commit 7c363f1730
8 changed files with 468 additions and 188 deletions

View File

@ -1,6 +1,6 @@
import {styled} from '@mui/material/styles'
import zIndex from '@mui/material/styles/zIndex'
import SimpleMDE, {SimpleMDEReactProps} from 'react-simplemde-editor'
import SimpleMDE, {SimpleMDEReactProps, default as SimpleMDEDefault} from 'react-simplemde-editor'
const StyledMarkdownEditor = styled('div')(({theme}) => ({
'& .editor-toolbar': {
@ -63,10 +63,46 @@ const StyledMarkdownEditor = styled('div')(({theme}) => ({
'& .guide': {
display: 'none',
},
}))
}));
export const MarkdownEditor = (props: SimpleMDEReactProps) => (
<StyledMarkdownEditor className="my-markdown-editor" sx={{marginTop: 1.5, marginBottom: 3}}>
<SimpleMDE {...props} />
</StyledMarkdownEditor>
)
export const MarkdownEditor = (props: SimpleMDEReactProps) => {
if(props.options)
props.options.toolbar = [
"bold",
"italic",
"strikethrough",
{
name: "Underline",
action: (editor: any) => {
const cm = editor.codemirror;
let output = '';
const selectedText = cm.getSelection();
const text = selectedText ?? 'placeholder';
output = '<u>' + text + '</u>';
cm.replaceSelection(output);
},
className: "fa fa-underline", // Look for a suitable icon
title: "Underline (Ctrl/Cmd-Alt-U)",
},
"heading",
"quote",
"unordered-list",
"ordered-list",
"link",
"image",
"code",
"table",
"horizontal-rule",
"preview",
"fullscreen",
"guide"
]
return (
<StyledMarkdownEditor className="my-markdown-editor" sx={{marginTop: 1.5, marginBottom: 3}}>
<SimpleMDE {...props}/>
</StyledMarkdownEditor>
)
}

View File

@ -9,6 +9,7 @@ import "easymde/dist/easymde.min.css";
import { LanguageSelector } from "@ui";
import { observer } from "mobx-react-lite";
import { EVERY_LANGUAGE, Languages, languageStore, META_LANGUAGE } from "@stores";
import rehypeRaw from "rehype-raw";
const MemoizedSimpleMDE = React.memo(MarkdownEditor);
@ -208,7 +209,7 @@ export const ArticleCreate = observer(() => {
},
}}
>
<ReactMarkdown>{preview}</ReactMarkdown>
<ReactMarkdown rehypePlugins={[rehypeRaw]}>{preview}</ReactMarkdown>
</Box>
</Paper>
</Box>

View File

@ -13,6 +13,8 @@ import "easymde/dist/easymde.min.css";
import { EVERY_LANGUAGE, Languages, languageStore, META_LANGUAGE } from "@stores";
import { observer } from "mobx-react-lite";
import { LanguageSelector, MediaView } from "@ui";
import rehypeRaw from "rehype-raw";
const MemoizedSimpleMDE = React.memo(MarkdownEditor);
export const ArticleEdit = observer(() => {
@ -48,6 +50,10 @@ export const ArticleEdit = observer(() => {
const bodyContent = watch("body");
const headingContent = watch("heading");
useEffect(() => {
console.log(bodyContent)
}, [bodyContent])
useEffect(() => {
console.log(articleData)
}, [articleData])
@ -232,7 +238,7 @@ export const ArticleEdit = observer(() => {
},
}}
>
<ReactMarkdown>{bodyContent}</ReactMarkdown>
<ReactMarkdown rehypePlugins={[rehypeRaw]}>{bodyContent}</ReactMarkdown>
</Box>
{/* Привязанные медиа */}

View File

@ -3,6 +3,7 @@ import { Create, useAutocomplete } from "@refinedev/mui";
import { useForm } from "@refinedev/react-hook-form";
import { Controller, FieldValues } from "react-hook-form";
import React, { useState, useEffect } from "react";
import { ArticleItem, articleFields } from "./types";
import { TOKEN_KEY } from "@providers";
import { observer } from "mobx-react-lite";
import { EVERY_LANGUAGE, Languages, languageStore, cityStore } from "@stores";
@ -504,40 +505,47 @@ export const SightCreate = observer(() => {
<Controller
control={control}
name="preview_article"
name="preview_media"
defaultValue={null}
render={({ field }) => (
<Autocomplete
{...articleAutocompleteProps}
{...mediaAutocompleteProps}
value={
articleAutocompleteProps.options.find(
mediaAutocompleteProps.options.find(
(option) => option.id === field.value
) ?? null
) || null
}
onChange={(_, value) => {
field.onChange(value?.id ?? "");
console.log(value, _)
field.onChange(value?.id || "");
}}
getOptionLabel={(item) => {
return item ? item.heading : "";
return item ? item.media_name : "";
}}
isOptionEqualToValue={(option, value) => {
return option.id === value?.id;
}}
filterOptions={(options, { inputValue }) => {
return options.filter((option) =>
option.heading
.toLowerCase()
.includes(inputValue.toLowerCase())
return options.filter(
(option) =>
option.media_name
.toLowerCase()
.includes(inputValue.toLowerCase()) &&
[1,2,5,6].includes(option.media_type)
);
}}
renderInput={(params) => (
<TextField
{...params}
onClick={() => {
//setPreviewSelected(true);
//setSelectedMediaIndex(-1);
}}
label="Медиа-предпросмотр"
margin="normal"
variant="outlined"
error={!!errors.preview_article}
helperText={(errors as any)?.preview_article?.message}
error={!!errors.arms}
helperText={(errors as any)?.arms?.message}
/>
)}
/>

View File

@ -207,10 +207,24 @@ export const SightEdit = observer(() => {
const selectedMedia = mediaAutocompleteProps.options.find(
(option) => option.id === previewMediaId
);
console.log("Triggering", previewMediaId)
if(!selectedMedia) return;
setMediaFile(selectedMedia);
}
}, [previewMediaId]);
}, [previewMediaId, mediaAutocompleteProps.options]);
// useEffect(() => {
// const selectedWatermarkLU = mediaAutocompleteProps.options.find(
// (option) => option.id === watermarkLUContent
// );
// setWatermarkLUPreview(
// selectedWatermarkLU
// ? `${import.meta.env.VITE_KRBL_MEDIA}${
// selectedWatermarkLU.id
// }/download?token=${localStorage.getItem(TOKEN_KEY)}`
// : null
// );
// }, [watermarkLUContent, ]);
const addressContent = watch("address");
const latitudeContent = watch("latitude");
@ -397,6 +411,55 @@ export const SightEdit = observer(() => {
name="name"
/>
<Box sx={{display: "none"}}>
<Controller
control={control}
name="preview_media"
defaultValue={null}
render={({ field }) => (
<Autocomplete
{...mediaAutocompleteProps}
value={
mediaAutocompleteProps.options.find(
(option) => option.id === field.value
) || null
}
onChange={(_, value) => {
field.onChange(value?.id || "");
}}
getOptionLabel={(item) => {
return item ? item.media_name : "";
}}
isOptionEqualToValue={(option, value) => {
return option.id === value?.id;
}}
filterOptions={(options, { inputValue }) => {
return options.filter(
(option) =>
option.media_name
.toLowerCase()
.includes(inputValue.toLowerCase())
);
}}
renderInput={(params) => (
<TextField
{...params}
onClick={() => {
//setPreviewSelected(true);
//setSelectedMediaIndex(-1);
}}
label="Медиа-предпросмотр"
margin="normal"
variant="outlined"
error={!!errors.arms}
helperText={(errors as any)?.arms?.message}
/>
)}
/>
)}
/>
</Box>
<input
type="hidden"
{...register("longitude", {
@ -754,52 +817,53 @@ export const SightEdit = observer(() => {
<Box component="form" sx={{ flex: 1, display: "flex", flexDirection: "column" }} autoComplete="off">
<Controller
control={control}
name="preview_media"
defaultValue={null}
render={({ field }) => (
<Autocomplete
{...mediaAutocompleteProps}
value={
mediaAutocompleteProps.options.find(
(option) => option.id === field.value
) || null
}
onChange={(_, value) => {
field.onChange(value?.id || "");
}}
getOptionLabel={(item) => {
return item ? item.media_name : "";
}}
isOptionEqualToValue={(option, value) => {
return option.id === value?.id;
}}
filterOptions={(options, { inputValue }) => {
return options.filter(
(option) =>
option.media_name
.toLowerCase()
.includes(inputValue.toLowerCase()) &&
[1,2,5,6].includes(option.media_type)
);
}}
renderInput={(params) => (
<TextField
{...params}
onClick={() => {
//setPreviewSelected(true);
//setSelectedMediaIndex(-1);
}}
label="Медиа-предпросмотр"
margin="normal"
variant="outlined"
error={!!errors.arms}
helperText={(errors as any)?.arms?.message}
/>
)}
/>
)}
/>
control={control}
name="preview_media"
defaultValue={null}
render={({ field }) => (
<Autocomplete
{...mediaAutocompleteProps}
value={
mediaAutocompleteProps.options.find(
(option) => option.id === field.value
) || null
}
onChange={(_, value) => {
console.log(value, _)
field.onChange(value?.id || "");
}}
getOptionLabel={(item) => {
return item ? item.media_name : "";
}}
isOptionEqualToValue={(option, value) => {
return option.id === value?.id;
}}
filterOptions={(options, { inputValue }) => {
return options.filter(
(option) =>
option.media_name
.toLowerCase()
.includes(inputValue.toLowerCase()) &&
[1,2,5,6].includes(option.media_type)
);
}}
renderInput={(params) => (
<TextField
{...params}
onClick={() => {
//setPreviewSelected(true);
//setSelectedMediaIndex(-1);
}}
label="Медиа-предпросмотр"
margin="normal"
variant="outlined"
error={!!errors.arms}
helperText={(errors as any)?.arms?.message}
/>
)}
/>
)}
/>
</Box>
<LanguageSelector action={handleLanguageChange} />
<Box sx={{ mt: 3 }}>
@ -971,13 +1035,13 @@ export const SightEdit = observer(() => {
{
<Box
sx={{
mt: 0,
mb: 0,
//mt: "auto",
flexGrow: 1,
mb: 0,
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
height: "250px",
//height: "250px",
overflowY: "auto",
}}
>
@ -1059,7 +1123,7 @@ export const SightEdit = observer(() => {
</Typography>
</Box>
)}
<Box>
<Box sx={{mt: "auto"}}>
<Box
sx={{
display: "flex",