Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
lib
react-ag-qeditor
Commits
95adc509
Commit
95adc509
authored
May 19, 2026
by
Яков
Browse files
выбор загруженных
parent
70a43a9a
Changes
4
Show whitespace changes
Inline
Side-by-side
.idea/claudeCodeTabState.xml
View file @
95adc509
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
<value>
<value>
<TabSessionState>
<TabSessionState>
<option
name=
"provider"
value=
"claude"
/>
<option
name=
"provider"
value=
"claude"
/>
<option
name=
"sessionId"
value=
"
bca3c9d2-5b93-479f-
bd
5
6-
e8e8b8ddc1a3
"
/>
<option
name=
"sessionId"
value=
"
280f06de-8
bd6-
4fec-afa0-84fcb8360cf4
"
/>
<option
name=
"cwd"
value=
"$PROJECT_DIR$"
/>
<option
name=
"cwd"
value=
"$PROJECT_DIR$"
/>
<option
name=
"model"
value=
"claude-sonnet-4-6"
/>
<option
name=
"model"
value=
"claude-sonnet-4-6"
/>
<option
name=
"permissionMode"
value=
"bypassPermissions"
/>
<option
name=
"permissionMode"
value=
"bypassPermissions"
/>
...
...
package.json
View file @
95adc509
{
{
"name"
:
"react-ag-qeditor"
,
"name"
:
"react-ag-qeditor"
,
"version"
:
"1.1.4
3
"
,
"version"
:
"1.1.4
4
"
,
"description"
:
"WYSIWYG html editor"
,
"description"
:
"WYSIWYG html editor"
,
"author"
:
"atma"
,
"author"
:
"atma"
,
"license"
:
"
MIT
"
,
"license"
:
"
MIT
"
,
...
...
src/QEditor.jsx
View file @
95adc509
...
@@ -137,6 +137,8 @@ const QEditor = ({
...
@@ -137,6 +137,8 @@ const QEditor = ({
const
[
isUploading
,
setIsUploading
]
=
useState
(
false
)
const
[
isUploading
,
setIsUploading
]
=
useState
(
false
)
const
[
recordType
,
setRecordType
]
=
useState
({
video
:
true
})
const
[
recordType
,
setRecordType
]
=
useState
({
video
:
true
})
const
[
buttonLinkData
,
setButtonLinkData
]
=
useState
(
defaultButtonLinkData
)
const
[
buttonLinkData
,
setButtonLinkData
]
=
useState
(
defaultButtonLinkData
)
const
[
suggestedFiles
,
setSuggestedFiles
]
=
useState
([])
const
[
suggestedLoading
,
setSuggestedLoading
]
=
useState
(
false
)
let
formRef
=
useRef
(
null
);
let
formRef
=
useRef
(
null
);
// eslint-disable-next-line no-unused-vars
// eslint-disable-next-line no-unused-vars
...
@@ -176,6 +178,33 @@ const QEditor = ({
...
@@ -176,6 +178,33 @@ const QEditor = ({
}
}
},
[
focusFromTo
])
},
[
focusFromTo
])
const
SUGGEST_TYPES
=
[
'
image
'
,
'
interactiveImage
'
,
'
video
'
,
'
audio
'
,
'
file
'
]
const
SUGGEST_TYPE_MAP
=
{
image
:
'
image
'
,
interactiveImage
:
'
image
'
,
video
:
'
video
'
,
audio
:
'
audio
'
,
file
:
'
file
'
}
useEffect
(()
=>
{
if
(
!
modalIsOpen
||
!
uploadOptions
.
suggestUrl
||
!
SUGGEST_TYPES
.
includes
(
innerModalType
))
{
setSuggestedFiles
([])
return
}
let
cancelled
=
false
setSuggestedLoading
(
true
)
axios
.
get
(
uploadOptions
.
suggestUrl
,
{
params
:
{
type
:
SUGGEST_TYPE_MAP
[
innerModalType
]
}
})
.
then
(
response
=>
{
if
(
!
cancelled
&&
response
.
data
.
state
===
'
success
'
&&
Array
.
isArray
(
response
.
data
.
files
))
{
setSuggestedFiles
(
response
.
data
.
files
)
}
})
.
catch
(()
=>
{})
.
finally
(()
=>
{
if
(
!
cancelled
)
setSuggestedLoading
(
false
)
})
return
()
=>
{
cancelled
=
true
}
},
[
modalIsOpen
,
innerModalType
])
const
editWord
=
(
values
)
=>
{
const
editWord
=
(
values
)
=>
{
let
_values
=
values
;
let
_values
=
values
;
...
@@ -803,6 +832,63 @@ const QEditor = ({
...
@@ -803,6 +832,63 @@ const QEditor = ({
}
}
}
}
const
getSuggestionsSection
=
()
=>
{
if
(
!
uploadOptions
.
suggestUrl
||
!
SUGGEST_TYPES
.
includes
(
innerModalType
))
{
return
null
}
if
(
suggestedLoading
)
{
return
<
div
className
=
'atma-editor-suggest-loading'
>
Загрузка файлов...
</
div
>
}
if
(
suggestedFiles
.
length
===
0
)
{
return
null
}
const
isVideo
=
innerModalType
===
'
video
'
const
isAudio
=
innerModalType
===
'
audio
'
const
isFile
=
innerModalType
===
'
file
'
return
(
<
div
className
=
'atma-editor-suggest'
>
<
div
className
=
'atma-editor-suggest-title'
>
Ранее загруженные файлы
</
div
>
<
div
className
=
'atma-editor-suggest-list'
>
{
suggestedFiles
.
map
((
file
,
i
)
=>
{
const
uid
=
'
suggest_
'
+
file
.
path
const
isSelected
=
uploadedPaths
.
some
(
p
=>
p
.
uid
===
uid
)
const
thumbnail
=
isVideo
?
(
file
.
poster
||
file
.
path
+
'
.jpg
'
)
:
(
!
isAudio
&&
!
isFile
?
file
.
path
:
null
)
return
(
<
div
key
=
{
'
suggest
'
+
i
}
className
=
{
'
atma-editor-suggest-item
'
+
(
isSelected
?
'
selected
'
:
''
)
+
(
isFile
?
'
is-file
'
:
''
)
+
(
isAudio
?
'
is-audio
'
:
''
)
+
(
isVideo
?
'
is-video
'
:
''
)
}
style
=
{
thumbnail
?
{
backgroundImage
:
`url(
${
thumbnail
}
)`
}
:
{}
}
title
=
{
file
.
name
}
onClick
=
{
()
=>
{
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
>
</
div
>
)
})
}
</
div
>
</
div
>
)
}
const
getInnerModal
=
()
=>
{
const
getInnerModal
=
()
=>
{
switch
(
innerModalType
)
{
switch
(
innerModalType
)
{
case
'
iframe
'
:
case
'
iframe
'
:
...
@@ -831,7 +917,10 @@ const QEditor = ({
...
@@ -831,7 +917,10 @@ const QEditor = ({
)
)
case
'
audio
'
:
case
'
audio
'
:
return
(
return
(
<
Fragment
>
{
getUploader
({
accept
:
'
.wav, .mp3, .ogg
'
})
}
</
Fragment
>
<
Fragment
>
{
getSuggestionsSection
()
}
{
getUploader
({
accept
:
'
.wav, .mp3, .ogg
'
})
}
</
Fragment
>
)
)
case
'
iframe_pdf
'
:
case
'
iframe_pdf
'
:
return
(
return
(
...
@@ -852,14 +941,30 @@ const QEditor = ({
...
@@ -852,14 +941,30 @@ const QEditor = ({
</
Fragment
>
</
Fragment
>
)
)
case
'
video
'
:
case
'
video
'
:
return
<
Fragment
>
{
getUploader
({
accept
:
'
video/mp4,.mp4
'
})
}
</
Fragment
>
return
(
<
Fragment
>
{
getSuggestionsSection
()
}
{
getUploader
({
accept
:
'
video/mp4,.mp4
'
})
}
</
Fragment
>
)
case
'
image
'
:
case
'
image
'
:
return
<
Fragment
>
{
getUploader
({
accept
:
'
image/*
'
})
}
</
Fragment
>
return
(
<
Fragment
>
{
getSuggestionsSection
()
}
{
getUploader
({
accept
:
'
image/*
'
})
}
</
Fragment
>
)
case
'
interactiveImage
'
:
case
'
interactiveImage
'
:
return
<
Fragment
>
{
getUploader
({
accept
:
'
image/*
'
,
multiple
:
false
})
}
</
Fragment
>
return
(
<
Fragment
>
{
getSuggestionsSection
()
}
{
getUploader
({
accept
:
'
image/*
'
,
multiple
:
false
})
}
</
Fragment
>
)
case
'
file
'
:
case
'
file
'
:
return
(
return
(
<
Fragment
>
<
Fragment
>
{
getSuggestionsSection
()
}
{
getUploader
({
accept
:
'
*
'
,
afterParams
:
[
'
no_convert=1
'
]})
}
{
getUploader
({
accept
:
'
*
'
,
afterParams
:
[
'
no_convert=1
'
]})
}
</
Fragment
>
</
Fragment
>
)
)
...
...
src/index.scss
View file @
95adc509
...
@@ -830,6 +830,98 @@ body{
...
@@ -830,6 +830,98 @@ body{
}
}
}
}
&-suggest{
margin-bottom: 20px;
&-loading{
color: #656D77;
font-size: 13px;
margin-bottom: 16px;
}
&-title{
font-size: 13px;
color: #656D77;
margin-bottom: 10px;
}
&-list{
display: flex;
flex-wrap: wrap;
gap: 10px;
}
&-item{
position: relative;
width: 100px;
aspect-ratio: 16 / 9;
background-color: #e8eaed;
border-radius: 6px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
cursor: pointer;
border: 2px solid transparent;
transition: border-color 0.15s;
overflow: hidden;
&:hover{
border-color: #adb0b6;
}
&.selected{
border-color: #1790FF;
&::after{
content: '';
position: absolute;
top: 4px;
right: 4px;
width: 16px;
height: 16px;
border-radius: 50%;
background-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;
}
}
&.is-audio,
&.is-file{
aspect-ratio: auto;
width: auto;
max-width: 160px;
min-width: 80px;
height: auto;
background-image: none !important;
background-color: #F5F7FA;
display: flex;
align-items: center;
padding: 8px 10px;
}
&.is-video{
background-color: #1a1a1a;
}
&-name{
font-size: 11px;
color: #434A53;
display: none;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
&.is-audio &-name,
&.is-file &-name{
display: block;
}
}
}
&-btn{
&-btn{
font-size: 16px;
font-size: 16px;
-webkit-appearance: none;
-webkit-appearance: none;
...
...
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