Commit 07c74710 authored by Яков's avatar Яков
Browse files

верстка

parent a53a9695
{ {
"name": "react-ag-qeditor", "name": "react-ag-qeditor",
"version": "1.1.45", "version": "1.1.46",
"description": "WYSIWYG html editor", "description": "WYSIWYG html editor",
"author": "atma", "author": "atma",
"license": "MIT", "license": "MIT",
......
...@@ -181,13 +181,15 @@ const QEditor = ({ ...@@ -181,13 +181,15 @@ const QEditor = ({
} }
}, [focusFromTo]) }, [focusFromTo])
const SUGGEST_TYPES = ['image', 'interactiveImage', 'video', 'audio', 'file'] const SUGGEST_TYPES = ['image', 'interactiveImage', 'video', 'audio', 'file', 'iframe_pdf', 'iframe_pptx']
const SUGGEST_TYPE_MAP = { const SUGGEST_TYPE_MAP = {
image: 'image', image: 'image',
interactiveImage: 'image', interactiveImage: 'image',
video: 'video', video: 'video',
audio: 'audio', audio: 'audio',
file: 'file' file: 'file',
iframe_pdf: 'pdf',
iframe_pptx: 'pptx'
} }
useEffect(() => { useEffect(() => {
...@@ -861,8 +863,23 @@ const QEditor = ({ ...@@ -861,8 +863,23 @@ const QEditor = ({
} }
const isVideo = innerModalType === 'video' const isVideo = innerModalType === 'video'
const isAudio = innerModalType === 'audio' const isAudio = innerModalType === 'audio'
const isFile = innerModalType === 'file' const isFileType = innerModalType === 'file' || innerModalType === 'iframe_pdf' || innerModalType === 'iframe_pptx'
const totalPages = Math.ceil(suggestTotal / SUGGEST_LIMIT) const totalPages = Math.ceil(suggestTotal / SUGGEST_LIMIT)
const toggleSelect = (file, uid) => {
const isSelected = uploadedPaths.some(p => p.uid === uid)
if (isSelected) {
setUploadedPaths(uploadedPaths.filter(p => p.uid !== uid))
} else {
setUploadedPaths([...uploadedPaths, {
path: file.path,
uid,
name: file.name,
size: file.size
}])
}
}
return ( return (
<div className='atma-editor-suggest'> <div className='atma-editor-suggest'>
<div className='atma-editor-suggest-title'>Ранее загруженные файлы</div> <div className='atma-editor-suggest-title'>Ранее загруженные файлы</div>
...@@ -870,33 +887,42 @@ const QEditor = ({ ...@@ -870,33 +887,42 @@ const QEditor = ({
{suggestedFiles.map((file, i) => { {suggestedFiles.map((file, i) => {
const uid = 'suggest_' + file.path const uid = 'suggest_' + file.path
const isSelected = uploadedPaths.some(p => p.uid === uid) const isSelected = uploadedPaths.some(p => p.uid === uid)
const thumbnail = isVideo
? (file.poster || file.path + '.jpg') if (isVideo) {
: (!isAudio && !isFile ? file.path : null) return (
<div
key={'suggest' + i}
className={'atma-editor-suggest-item is-video' + (isSelected ? ' selected' : '')}
>
<video
src={file.path}
controls
className='atma-editor-suggest-video'
title={file.name}
/>
<button
type='button'
className='atma-editor-suggest-select-btn'
title={isSelected ? 'Снять выбор' : 'Выбрать'}
onClick={() => toggleSelect(file, uid)}
/>
</div>
)
}
const thumbnail = !isAudio && !isFileType ? file.path : null
return ( return (
<div <div
key={'suggest' + i} key={'suggest' + i}
className={ className={
'atma-editor-suggest-item' + 'atma-editor-suggest-item' +
(isSelected ? ' selected' : '') + (isSelected ? ' selected' : '') +
(isFile ? ' is-file' : '') + (isFileType ? ' is-file' : '') +
(isAudio ? ' is-audio' : '') + (isAudio ? ' is-audio' : '')
(isVideo ? ' is-video' : '')
} }
style={thumbnail ? { backgroundImage: `url(${thumbnail})` } : {}} style={thumbnail ? { backgroundImage: `url(${thumbnail})` } : {}}
title={file.name} title={file.name}
onClick={() => { onClick={() => toggleSelect(file, uid)}
if (isSelected) {
setUploadedPaths(uploadedPaths.filter(p => p.uid !== uid))
} else {
setUploadedPaths([...uploadedPaths, {
path: file.path,
uid,
name: file.name,
size: file.size
}])
}
}}
> >
<span className='atma-editor-suggest-item-name'>{file.name}</span> <span className='atma-editor-suggest-item-name'>{file.name}</span>
</div> </div>
...@@ -945,6 +971,7 @@ const QEditor = ({ ...@@ -945,6 +971,7 @@ const QEditor = ({
case 'iframe_pptx': case 'iframe_pptx':
return ( return (
<Fragment> <Fragment>
{getSuggestionsSection()}
{getUploader({ {getUploader({
accept: accept:
'application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.slideshow, application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.slideshow, application/vnd.openxmlformats-officedocument.presentationml.presentation',
...@@ -962,6 +989,7 @@ const QEditor = ({ ...@@ -962,6 +989,7 @@ const QEditor = ({
case 'iframe_pdf': case 'iframe_pdf':
return ( return (
<Fragment> <Fragment>
{getSuggestionsSection()}
{getUploader({ {getUploader({
accept: 'application/pdf', accept: 'application/pdf',
afterParams: ['no_convert=1'] afterParams: ['no_convert=1']
...@@ -1342,6 +1370,8 @@ const QEditor = ({ ...@@ -1342,6 +1370,8 @@ const QEditor = ({
switch (innerModalType) { switch (innerModalType) {
case 'video': case 'video':
case 'image': case 'image':
case 'iframe_pdf':
case 'iframe_pptx':
if (uploadOptions.url === null || uploadedPaths.length === 0) { if (uploadOptions.url === null || uploadedPaths.length === 0) {
isDisabled = true isDisabled = true
} }
......
...@@ -3,100 +3,64 @@ import React, { Fragment, useState } from 'react'; ...@@ -3,100 +3,64 @@ import React, { Fragment, useState } from 'react';
const toolsInit = { const toolsInit = {
'all': [ 'all': [
{ { type: 'g', items: ['undo', 'redo'] },
type: 'g', { type: 'g', items: ['|'] },
items: [
'undo', // Aa▼ — стиль текста
'redo' { type: 's', toggle: true, items: ['paragraph', 'h2', 'h3', 'h4'] },
]
}, // Lists▼ — списки
{ { type: 's', toggle: false, items: ['bulletList', 'orderedList', 'insertToggleBlock'] },
type: 's',
toggle: true,
items: [
'paragraph',
'h2',
'h3',
'h4'
]
},
{
type: 'g',
items: [
'bulletList',
'orderedList',
'blockquote',
'codeBlock',
'hr',
]
},
{
type: 's',
toggle: true,
items: [
'alignLeft',
'alignCenter',
'alignRight',
]
},
{
type: 'g',
items: [
'emoji',
'link',
'buttonLink',
'file',
'image',
'interactiveImage',
'video',
'iframe',
'iframe_pptx',
'iframe_pdf',
'pdf',
'audio',
'iframe_custom',
'insertToggleBlock'
]
},
{
type: 'g',
items: [
'clearMarks',
'hardBreak',
]
},
// ≡▼ — выравнивание
{ type: 's', toggle: true, items: ['alignLeft', 'alignCenter', 'alignRight'] },
// strike
{ type: 'g', items: ['strike'] },
// Table▼
{ {
type: 's', type: 's',
toggle: false, toggle: false,
items: [ items: [
'insertTable', 'insertTable', '|',
'|', 'addRowBefore', 'addRowAfter', 'deleteRow', '|',
'addRowBefore', 'addColumnBefore', 'addColumnAfter', 'deleteColumn', '|',
'addRowAfter', 'toggleHeaderCell', '|',
'deleteRow', 'mergeOrSplit', 'deleteTable', '|',
'|',
'addColumnBefore',
'addColumnAfter',
'deleteColumn',
'|',
'toggleHeaderCell',
'|',
'mergeOrSplit',
'deleteTable',
'|',
'toggleTableBorders' 'toggleTableBorders'
] ]
}, },
{
type: 'g', { type: 'g', items: ['emoji'] },
items: [ { type: 'g', items: ['clearMarks'] },
'voicemessage', { type: 'g', items: ['codeBlock'] },
'webcamera',
'screencust', // ─── разделитель ───
'export_pdf', { type: 'g', items: ['|'] },
]
}, // Image▼ — изображение / интерактивное
{ type: 's', toggle: false, items: ['image', 'interactiveImage'] },
// Video▼ — загрузить / по ссылке
{ type: 's', toggle: false, items: ['video', 'iframe'] },
{ type: 'g', items: ['audio'] },
{ type: 'g', items: ['voicemessage'] },
{ type: 'g', items: ['webcamera'] },
{ type: 'g', items: ['screencust'] },
// ─── разделитель ───
{ type: 'g', items: ['|'] },
// Docs▼ — pptx / pdf / pdf->text
{ type: 's', toggle: false, items: ['iframe_pptx', 'iframe_pdf', 'pdf'] },
// Link▼ — ссылка / кнопка-ссылка
{ type: 's', toggle: false, items: ['link', 'buttonLink'] },
{ type: 'g', items: ['file'] },
{ type: 'g', items: ['iframe_custom'] },
], ],
'text': [ 'text': [
{ {
...@@ -304,10 +268,24 @@ const ToolBar = ({ editor, toolsLib = [], toolsOptions }) => { ...@@ -304,10 +268,24 @@ const ToolBar = ({ editor, toolsLib = [], toolsOptions }) => {
} }
const isThickSep = (section) =>
section.type === 'g' && section.items.length === 1 && section.items[0] === '|'
const getItems = () => { const getItems = () => {
let toolItems = []; let toolItems = [];
toolbarItems.map((section, i) => { toolbarItems.map((section, i) => {
const prevSection = toolbarItems[i - 1]
const needThinSep = i > 0
&& !isThickSep(section)
&& prevSection && !isThickSep(prevSection)
if (needThinSep) {
toolItems.push(
<div key={`thin-sep-${i}`} className="atma-editor-toolbar-thin-sep" />
)
}
let gItems = []; let gItems = [];
if(section.type === 'g'){ if(section.type === 'g'){
section.items.map((gKey, idx)=>{ section.items.map((gKey, idx)=>{
......
...@@ -257,22 +257,35 @@ body{ ...@@ -257,22 +257,35 @@ body{
box-shadow: 0 -3px 0 3px #ffffff; box-shadow: 0 -3px 0 3px #ffffff;
padding: 6px; padding: 6px;
z-index: 10; z-index: 10;
grid-gap: 7.5px;
&-g{ &-g{
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center;
&:after{ .qseparator{
content: ''; width: 1px;
display: inline-block; height: 18px;
width: 20px; background-color: #CCD1D9;
margin: 0 6px;
flex-shrink: 0;
} }
} }
&-thin-sep{
width: 1px;
height: 18px;
background-color: rgba(0, 0, 0, 0.06);
flex-shrink: 0;
align-self: center;
}
&-s{ &-s{
$this: &; $this: &;
position: relative; position: relative;
padding-right: 5px; padding-right: 5px;
margin-right: 9px; margin-right: 0;
.qseparator{ .qseparator{
display: block; display: block;
...@@ -597,8 +610,8 @@ body{ ...@@ -597,8 +610,8 @@ body{
background: #fff; background: #fff;
transform: translate(0, -50%); transform: translate(0, -50%);
border-radius: 8px; border-radius: 8px;
max-width: 90%; //max-width: 90%;
min-width: 560px; max-width: 646px;
padding: 48px; padding: 48px;
max-height: 900px; max-height: 900px;
overflow-y: scroll; overflow-y: scroll;
...@@ -711,7 +724,7 @@ body{ ...@@ -711,7 +724,7 @@ body{
&-uploader{ &-uploader{
&-drop{ &-drop{
display: flex; display: flex;
width: 490px; width: 550px;
height: 154px; height: 154px;
background-color: #F5F7FA; background-color: #F5F7FA;
border-radius: 16px; border-radius: 16px;
...@@ -902,7 +915,23 @@ body{ ...@@ -902,7 +915,23 @@ body{
} }
&.is-video{ &.is-video{
background-color: #1a1a1a; width: 240px;
aspect-ratio: 16 / 9;
background-color: #000;
background-image: none !important;
cursor: default;
&:hover{
box-shadow: 0 0 0 2px transparent;
}
&.selected{
box-shadow: 0 0 0 2px #1790FF;
&::after{
display: none;
}
}
} }
&-name{ &-name{
...@@ -921,6 +950,41 @@ body{ ...@@ -921,6 +950,41 @@ body{
} }
} }
&-video{
display: block;
width: 100%;
height: 100%;
object-fit: contain;
}
&-select-btn{
position: absolute;
top: 6px;
right: 6px;
width: 22px;
height: 22px;
border-radius: 50%;
border: 2px solid rgba(255,255,255,0.8);
background-color: rgba(0,0,0,0.35);
cursor: pointer;
padding: 0;
transition: background-color 0.15s, border-color 0.15s;
z-index: 1;
&:hover{
background-color: rgba(0,0,0,0.55);
border-color: #fff;
}
.selected &{
background-color: #1790FF;
border-color: #1790FF;
background-image: url('data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%228%22%20height%3D%226%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M1%203l2%202%204-4%22%20stroke%3D%22%23fff%22%20stroke-width%3D%221.5%22%20fill%3D%22none%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%2F%3E%3C%2Fsvg%3E');
background-repeat: no-repeat;
background-position: center;
}
}
&-pagination{ &-pagination{
display: flex; display: flex;
align-items: center; align-items: center;
...@@ -1362,10 +1426,6 @@ body{ ...@@ -1362,10 +1426,6 @@ body{
} }
} }
.qseparator{
width: 16px;
}
.closeBtn { .closeBtn {
position: relative; position: relative;
display: flex; display: flex;
......
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