Commit 5499f2c8 by Nikita

added remove iframe button

parent 6ce5f728
...@@ -31,6 +31,9 @@ import ReactStopwatch from 'react-stopwatch'; ...@@ -31,6 +31,9 @@ import ReactStopwatch from 'react-stopwatch';
import Audio from "./extensions/Audio"; import Audio from "./extensions/Audio";
import { isMobile } from 'react-device-detect'; import { isMobile } from 'react-device-detect';
import IframeModal from "./modals/IframeModal";
import IframeCustomModal from "./modals/IframeCustomModal";
import RemoveIframeModal from "./modals/RemoveIframeModal";
const initialBubbleItems = ['bold', 'italic', 'underline', 'strike', '|', 'colorText', 'highlight']; const initialBubbleItems = ['bold', 'italic', 'underline', 'strike', '|', 'colorText', 'highlight'];
...@@ -55,6 +58,7 @@ const QEditor = ({ ...@@ -55,6 +58,7 @@ const QEditor = ({
const [oldFocusFromTo, setOldFocusFromTo] = useState(null); const [oldFocusFromTo, setOldFocusFromTo] = useState(null);
const [isUploading, setIsUploading] = useState(false); const [isUploading, setIsUploading] = useState(false);
const [recordType, setRecordType] = useState({video: true}) const [recordType, setRecordType] = useState({video: true})
const [currentRemoveIframe, setCurrentRemoveIframe] = useState(null);
const getRgb = (hex) => { const getRgb = (hex) => {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
...@@ -495,29 +499,18 @@ const QEditor = ({ ...@@ -495,29 +499,18 @@ const QEditor = ({
const getInnerModal = () => { const getInnerModal = () => {
switch (innerModalType) { switch (innerModalType) {
case 'remove_iframe':
return <RemoveIframeModal />
case 'iframe': case 'iframe':
return ( return <IframeModal
<Fragment> embedContent={embedContent}
<input type="text" value={embedContent} placeholder={'https://'} setEmbedContent={setEmbedContent}
onInput={(e) => setEmbedContent(e.target.value) />
}/>
<ul className={'atma-editor-soc-video'}>
<li className={'youtube'}/>
<li className={'vimeo'}/>
{/* <li className={'vk'}/> */}
<li className={'ok'}/>
<li className={'rutube'}/>
</ul>
</Fragment>
)
case 'iframe_custom': case 'iframe_custom':
return ( return <IframeCustomModal
<Fragment> embedContent={embedContent}
<textarea style={{width: '100%', height: '100%'}} rows={18} value={embedContent} placeholder={'<iframe></iframe>'} setEmbedContent={setEmbedContent}
onInput={(e) => setEmbedContent(e.target.value)}
/> />
</Fragment>
)
case 'iframe_pptx': case 'iframe_pptx':
return ( return (
<Fragment>{getUploader({accept: 'application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.slideshow, application/vnd.openxmlformats-officedocument.presentationml.presentation', afterParams: ['no_convert=1']})}</Fragment> <Fragment>{getUploader({accept: 'application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.slideshow, application/vnd.openxmlformats-officedocument.presentationml.presentation', afterParams: ['no_convert=1']})}</Fragment>
...@@ -536,7 +529,6 @@ const QEditor = ({ ...@@ -536,7 +529,6 @@ const QEditor = ({
) )
case 'voicemessage': case 'voicemessage':
return ( return (
<>
<Fragment> <Fragment>
{ {
isMobile && isMobile &&
...@@ -577,7 +569,6 @@ const QEditor = ({ ...@@ -577,7 +569,6 @@ const QEditor = ({
</div> </div>
} }
</Fragment> </Fragment>
</>
) )
case 'screencust': case 'screencust':
return ( return (
...@@ -794,86 +785,35 @@ const QEditor = ({ ...@@ -794,86 +785,35 @@ const QEditor = ({
return null return null
} }
return ( const buttons = innerModalType === 'remove_iframe' ?
<div [
className="atma-editor-wrap"
style={style}
>
<div className="atma-editor">
<ToolBar
editor={editor}
{...{toolsOptions}}
{...{toolsLib}}
/>
<BubbleMenu typpyOptions={{followCursor: true,}} editor={editor} shouldShow={({...o}) => {
let items = [];
if (o.from !== o.to && editor.isActive('paragraph') && editor.isActive('image') === false && document.querySelectorAll('.selectedCell').length === 0) {
items = initialBubbleItems;
}
if (editor.isActive('image') === true) {
items = ['alignLeft', 'alignCenter', 'alignRight'];
}
setFocusFromTo([o.from, o.to].join(':'));
if (items.length > 0) {
setBubbleItems(items);
return true;
}
}} tippyOptions={{duration: 100}}>
<div className={"atma-editor-bubble"} onClick={e => e.stopPropagation()}>
{ {
colorsSelected !== null ? title: 'Отмена',
colors[colorsSelected].map((itemColor, i) => { className: ' atma-editor-cancel',
return (<div key={'colors' + colorsSelected + i} onClick: () => {
className={'qcolors' + (itemColor === 'none' ? ' unset' : '')} stopRecording();
style={{background: itemColor}} onClick={() => { unMuteAudio();
clearBlobUrl();
if (itemColor === 'none') { setUploaderUid(`uid${new Date()}`);
colorsSelected === 'color' ? setUploadedPaths([]);
editor.chain().focus().unsetHighlight().unsetColor().run() : setModalIsOpen(false);
editor.chain().focus().unsetColor().unsetHighlight().run();
} else {
colorsSelected === 'color' ?
editor.chain().focus().unsetHighlight().setColor(itemColor).run() :
editor.chain().focus().unsetColor().toggleHighlight({color: itemColor}).run();
}
setColorsSelected(null);
}}/>)
}) : bubbleItems.map((type, i) => {
if (type === '|') {
return (<div key={'bubbleSeparator' + i} className={'qseparator'}/>)
} else {
return (
<div
key={'bubbleItems' + i}
className={'qicon q' + type + (editor.isActive(type) ? ' active' : '')}
title={toolsLib[type] ? toolsLib[type].title : ''}
onClick={toolsLib[type].onClick}
/>
)
}
})
} }
</div> },
</BubbleMenu>
<EditorContent
editor={editor}
className={'atma-editor-content'}
/>
</div>
<EditorModal
isOpen={modalIsOpen}
title={modalTitle}
>
{ {
getInnerModal() title: 'Удалить',
className: ' atma-editor-complete',
onClick: () => {
currentRemoveIframe?.remove();
stopRecording();
unMuteAudio();
clearBlobUrl();
setUploaderUid(`uid${new Date()}`);
setUploadedPaths([]);
setModalIsOpen(false);
} }
{ },
buildActionsModal([ ] : [
{ {
title: 'Отмена', title: 'Отмена',
className: ' atma-editor-cancel', className: ' atma-editor-cancel',
...@@ -979,7 +919,7 @@ const QEditor = ({ ...@@ -979,7 +919,7 @@ const QEditor = ({
_url = `https://www.youtube.com/embed/${urlId}`; _url = `https://www.youtube.com/embed/${urlId}`;
break break
} }
editor.chain().focus().setIframe({src: _url}).run(); editor.chain().focus().setIframe({src: _url, setModalIsOpen, setInnerModalType, setModalTitle, setCurrentRemoveIframe}).run();
break break
case 'iframe_custom': case 'iframe_custom':
...@@ -1018,7 +958,88 @@ const QEditor = ({ ...@@ -1018,7 +958,88 @@ const QEditor = ({
}, },
disabled: isDisabledAction() disabled: isDisabledAction()
} }
]) ];
return (
<div
className="atma-editor-wrap"
style={style}
>
<div className="atma-editor">
<ToolBar
editor={editor}
{...{toolsOptions}}
{...{toolsLib}}
/>
<BubbleMenu typpyOptions={{followCursor: true,}} editor={editor} shouldShow={({...o}) => {
let items = [];
if (o.from !== o.to && editor.isActive('paragraph') && editor.isActive('image') === false && document.querySelectorAll('.selectedCell').length === 0) {
items = initialBubbleItems;
}
if (editor.isActive('image') === true) {
items = ['alignLeft', 'alignCenter', 'alignRight'];
}
setFocusFromTo([o.from, o.to].join(':'));
if (items.length > 0) {
setBubbleItems(items);
return true;
}
}} tippyOptions={{duration: 100}}>
<div className={"atma-editor-bubble"} onClick={e => e.stopPropagation()}>
{
colorsSelected !== null ?
colors[colorsSelected].map((itemColor, i) => {
return (<div key={'colors' + colorsSelected + i}
className={'qcolors' + (itemColor === 'none' ? ' unset' : '')}
style={{background: itemColor}} onClick={() => {
if (itemColor === 'none') {
colorsSelected === 'color' ?
editor.chain().focus().unsetHighlight().unsetColor().run() :
editor.chain().focus().unsetColor().unsetHighlight().run();
} else {
colorsSelected === 'color' ?
editor.chain().focus().unsetHighlight().setColor(itemColor).run() :
editor.chain().focus().unsetColor().toggleHighlight({color: itemColor}).run();
}
setColorsSelected(null);
}}/>)
}) : bubbleItems.map((type, i) => {
if (type === '|') {
return (<div key={'bubbleSeparator' + i} className={'qseparator'}/>)
} else {
return (
<div
key={'bubbleItems' + i}
className={'qicon q' + type + (editor.isActive(type) ? ' active' : '')}
title={toolsLib[type] ? toolsLib[type].title : ''}
onClick={toolsLib[type].onClick}
/>
)
}
})
}
</div>
</BubbleMenu>
<EditorContent
editor={editor}
className={'atma-editor-content'}
/>
</div>
<EditorModal
isOpen={modalIsOpen}
title={modalTitle}
>
{
getInnerModal()
}
{
buildActionsModal(buttons)
} }
</EditorModal> </EditorModal>
</div> </div>
......
...@@ -21,6 +21,18 @@ const Iframe = Node.create({ ...@@ -21,6 +21,18 @@ const Iframe = Node.create({
console.log(this) console.log(this)
}, },
}, },
"setInnerModalType" : {
default: null
},
"setModalIsOpen" : {
default: null
},
"setModalTitle" : {
default: null
},
"setCurrentRemoveIframe" : {
default: null
}
} }
}, },
...@@ -38,21 +50,35 @@ const Iframe = Node.create({ ...@@ -38,21 +50,35 @@ const Iframe = Node.create({
addNodeView() { addNodeView() {
return ({ editor, node, ...a }) => { return ({ editor, node, ...a }) => {
const container = document.createElement('div');
// div.className = 'aspect-w-16 aspect-h-9' + (editor.isEditable ? ' cursor-pointer' : '');
const iframe = document.createElement('iframe'); const iframe = document.createElement('iframe');
if (editor.isEditable) {
iframe.className = 'pointer-events-none';
}
iframe.src = node.attrs.src; iframe.src = node.attrs.src;
iframe.frameBorder = node.attrs.frameborder;
iframe.allowfullscreen = node.attrs.allowfullscreen; iframe.allowfullscreen = node.attrs.allowfullscreen;
iframe.style = 'width:1280px;height:auto;aspect-ratio: 16 / 9;'; iframe.classList.add('customIframe');
// div.append(video);
const closeBtn = document.createElement('button');
closeBtn.textContent = 'X';
closeBtn.classList.add('closeBtn');
closeBtn.addEventListener('click', function () {
try {
node.attrs.setModalTitle('Вы уверены, что хотите удалить?');
node.attrs.setInnerModalType('remove_iframe');
node.attrs.setModalIsOpen(true);
node.attrs.setCurrentRemoveIframe(container);
} catch {
container.remove();
}
});
// if (editor.isEditable) {
// container.classList.add('pointer-events-none');
// }
container.append(closeBtn, iframe);
return { return {
dom: iframe, dom: container,
} }
} }
}, },
...@@ -62,7 +88,7 @@ const Iframe = Node.create({ ...@@ -62,7 +88,7 @@ const Iframe = Node.create({
setIframe: (options) => ({ tr, dispatch }) => { setIframe: (options) => ({ tr, dispatch }) => {
const { selection } = tr const { selection } = tr
const node = this.type.create(options) const node = this.type.create(options)
//
if (dispatch) { if (dispatch) {
tr.replaceRangeWith(selection.from, selection.to, node) tr.replaceRangeWith(selection.from, selection.to, node)
} }
......
...@@ -1022,4 +1022,25 @@ body{ ...@@ -1022,4 +1022,25 @@ body{
.qseparator{ .qseparator{
width: 16px; width: 16px;
} }
.closeBtn {
position: relative;
display: flex;
justify-content: end;
border-radius: 50%;
border: none;
background-color: #2677e3;
color: #fff;
font-size: 0.5rem;
padding: 4px 6px;
top: 10px;
cursor: pointer;
right: 8px;
}
.customIframe {
width:1280px;
height:auto;
aspect-ratio: 16 / 9;
}
} }
import React, { Fragment } from "react";
export default function IframeCustomModal ({embedContent, setEmbedContent}) {
return (
<Fragment>
<textarea
style={{width: '100%', height: '100%'}}
rows={18}
value={embedContent}
placeholder={'<iframe></iframe>'}
onInput={(e) => setEmbedContent(e.target.value)}
/>
</Fragment>
)
}
import React, { Fragment } from "react";
export default function IframeModal ({embedContent, setEmbedContent}) {
return (
<Fragment>
<input type="text" value={embedContent} placeholder={'https://'}
onInput={(e) => setEmbedContent(e.target.value)
}/>
<ul className={'atma-editor-soc-video'}>
<li className={'youtube'}/>
<li className={'vimeo'}/>
{/* <li className={'vk'}/> */}
<li className={'ok'}/>
<li className={'rutube'}/>
</ul>
</Fragment>
)
}
import React, { Fragment } from "react";
export default function RemoveIframeModal(){
return (
<Fragment>
</Fragment>
)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment