Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
react-ag-qeditor
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lib
react-ag-qeditor
Commits
c79e85c3
Commit
c79e85c3
authored
Jun 27, 2025
by
Яков
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix drag and drop
parent
dd70d3d0
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
130 additions
and
70 deletions
+130
-70
QEditor.jsx
src/QEditor.jsx
+1
-1
DragAndDrop.js
src/extensions/DragAndDrop.js
+129
-69
No files found.
src/QEditor.jsx
View file @
c79e85c3
...
@@ -29,7 +29,7 @@ import Uploader from './components/Uploader'
...
@@ -29,7 +29,7 @@ import Uploader from './components/Uploader'
import
Video
from
'./extensions/Video'
import
Video
from
'./extensions/Video'
import
Iframe
from
'./extensions/Iframe'
import
Iframe
from
'./extensions/Iframe'
// import CustomLink from './extensions/CustomLink'
// import CustomLink from './extensions/CustomLink'
import
DragAndDrop
from
'./extensions/DragAndDrop'
import
{
DragAndDrop
}
from
'./extensions/DragAndDrop'
import
{
useReactMediaRecorder
}
from
'react-media-recorder'
import
{
useReactMediaRecorder
}
from
'react-media-recorder'
import
axios
from
'axios'
import
axios
from
'axios'
import
ReactStopwatch
from
'react-stopwatch'
import
ReactStopwatch
from
'react-stopwatch'
...
...
src/extensions/DragAndDrop.js
View file @
c79e85c3
import
{
Extension
}
from
"@tiptap/core"
;
import
{
Extension
}
from
'@tiptap/core'
;
import
{
Plugin
,
PluginKey
}
from
'prosemirror-state'
import
{
Plugin
,
PluginKey
}
from
'prosemirror-state'
;
import
axios
from
'axios'
import
{
EditorView
}
from
'prosemirror-view'
;
import
axios
from
'axios'
;
const
upload
=
async
(
file
)
=>
{
export
const
DragAndDrop
=
Extension
.
create
(
{
let
formData
=
new
FormData
();
name
:
'dragAndDrop'
,
addOptions
()
{
return
{
uploadUrl
:
''
,
// URL для загрузки файлов
uploadHandler
:
null
,
// Альтернативный обработчик загрузки
types
:
[
'image'
],
// Поддерживаемые типы файлов
headers
:
{},
// Дополнительные заголовки
};
},
addProseMirrorPlugins
()
{
if
(
!
this
.
options
.
uploadUrl
&&
!
this
.
options
.
uploadHandler
)
{
return
[];
}
const
isRealFile
=
(
item
)
=>
{
// Игнорируем текстовые форматы и специфичные для Word
if
(
item
.
type
.
startsWith
(
'text/'
)
||
item
.
type
.
startsWith
(
'application/x-mso'
)
||
item
.
type
===
'text/html'
||
item
.
type
===
'text/rtf'
)
{
return
false
;
}
// Разрешенные файловые типы
return
[
'image/'
,
'video/'
,
'audio/'
,
'application/octet-stream'
,
'application/pdf'
,
'application/zip'
].
some
(
type
=>
item
.
type
.
startsWith
(
type
));
};
const
uploadFile
=
async
(
file
)
=>
{
if
(
this
.
options
.
uploadHandler
)
{
return
await
this
.
options
.
uploadHandler
(
file
);
}
const
formData
=
new
FormData
();
formData
.
append
(
'file'
,
file
);
formData
.
append
(
'file'
,
file
);
const
headers
=
{
'Content-Type'
:
'multipart/form-data'
};
const
response
=
await
axios
.
post
(
global
.
uploadUrl
,
formData
,
{
headers
:
headers
}
);
const
headers
=
{
'Content-Type'
:
'multipart/form-data'
,
...
this
.
options
.
headers
};
const
response
=
await
axios
.
post
(
this
.
options
.
uploadUrl
,
formData
,
{
headers
}
);
if
(
!
response
.
data
)
throw
new
Error
(
'Upload failed'
);
return
response
.
data
.
file_path
;
return
response
.
data
.
file_path
;
};
};
const
handleUpload
=
async
(
file
,
view
,
pos
)
=>
{
try
{
const
filePath
=
await
uploadFile
(
file
);
if
(
!
filePath
)
return
;
const
{
state
}
=
view
;
const
{
tr
}
=
state
;
let
node
;
if
(
file
.
type
.
startsWith
(
'image/'
)
&&
this
.
options
.
types
.
includes
(
'image'
))
{
node
=
state
.
schema
.
nodes
.
image
?.
create
({
src
:
filePath
});
}
else
if
(
file
.
type
.
startsWith
(
'video/'
)
&&
this
.
options
.
types
.
includes
(
'video'
))
{
node
=
state
.
schema
.
nodes
.
video
?.
create
({
src
:
filePath
});
}
else
if
(
file
.
type
.
startsWith
(
'audio/'
)
&&
this
.
options
.
types
.
includes
(
'audio'
))
{
node
=
state
.
schema
.
nodes
.
audio
?.
create
({
src
:
filePath
});
}
if
(
node
)
{
view
.
dispatch
(
tr
.
insert
(
pos
,
node
));
}
}
catch
(
error
)
{
console
.
error
(
'Upload error:'
,
error
);
}
};
const
DragAndDrop
=
Extension
.
create
({
name
:
'customDragAndDrop'
,
addProseMirrorPlugins
()
{
return
[
return
[
new
Plugin
({
new
Plugin
({
key
:
new
PluginKey
(
'
customD
ragAndDrop'
),
key
:
new
PluginKey
(
'
d
ragAndDrop'
),
props
:
{
props
:
{
handleDOMEvents
:
{
handleDOMEvents
:
{
async
paste
(
view
,
event
)
{
drop
(
view
,
event
)
{
const
files
=
event
.
dataTransfer
?.
files
;
console
.
log
(
'Clipboard types:'
,
event
.
clipboardData
.
types
);
if
(
!
files
||
files
.
length
===
0
)
return
false
;
console
.
log
(
'HTML data length:'
,
event
.
clipboardData
.
getData
(
'text/html'
).
length
);
const
coordinates
=
view
.
posAtCoords
({
// let items = (event.clipboardData || event.originalEvent.clipboardData).items;
left
:
event
.
clientX
,
//
top
:
event
.
clientY
,
// for (let i = 0; i < items.length; i++){
// const { schema } = view.state;
// const image = items[i].getAsFile();
//
// if (!image) {
// return
// }
//
// // event.preventDefault();
// const imageSrc = await upload(image);
//
// const node = schema.nodes.image.create({
// src: imageSrc,
// });
// const transaction = view.state.tr.replaceSelectionWith(node);
// view.dispatch(transaction)
// }
},
async
drop
(
view
,
event
)
{
const
hasFiles
=
event
.
dataTransfer
.
files
.
length
>
0
;
// Другой способ достать текст
// console.log(event.dataTransfer.items[0].getAsString( (i) => {
// console.log(i)
// }));
// console.log(hasFiles)
if
(
hasFiles
)
{
// event.preventDefault();
const
images
=
event
.
dataTransfer
.
files
;
const
{
schema
}
=
view
.
state
;
const
coordinates
=
view
.
posAtCoords
({
left
:
event
.
clientX
,
top
:
event
.
clientY
});
for
(
let
i
=
0
;
i
<
images
.
length
;
i
++
)
{
const
imageSrc
=
await
upload
(
images
[
i
]);
if
(
imageSrc
)
{
const
node
=
schema
.
nodes
.
image
.
create
({
src
:
imageSrc
});
});
const
transaction
=
view
.
state
.
tr
.
insert
(
coordinates
.
pos
,
node
);
if
(
!
coordinates
)
return
false
;
view
.
dispatch
(
transaction
)
}
event
.
preventDefault
();
}
}
Array
.
from
(
files
).
forEach
(
file
=>
{
}
if
(
isRealFile
({
kind
:
'file'
,
type
:
file
.
type
}))
{
}
handleUpload
(
file
,
view
,
coordinates
.
pos
);
}
})
]
}
}
});
});
export
default
DragAndDrop
;
return
true
;
},
},
handlePaste
(
view
,
event
)
{
const
items
=
event
.
clipboardData
?.
items
;
if
(
!
items
)
return
false
;
// Проверяем наличие реальных файлов
const
files
=
Array
.
from
(
items
)
.
filter
(
item
=>
item
.
kind
===
'file'
&&
isRealFile
(
item
))
.
map
(
item
=>
item
.
getAsFile
())
.
filter
(
Boolean
);
if
(
files
.
length
===
0
)
return
false
;
event
.
preventDefault
();
const
{
state
}
=
view
;
const
pos
=
state
.
selection
.
$from
.
pos
;
files
.
forEach
(
file
=>
{
handleUpload
(
file
,
view
,
pos
);
});
return
true
;
},
},
}),
];
},
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment