underline
This commit is contained in:
@ -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>
|
||||
)
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
{/* Привязанные медиа */}
|
||||
|
@ -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}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
@ -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",
|
||||
|
Reference in New Issue
Block a user