Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wiki-js
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
wiki-js
Commits
5d155028
Commit
5d155028
authored
Jun 07, 2017
by
NGPixel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor: editor-file.vue -> image + localization
parent
c38ba72b
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
130 additions
and
972 deletions
+130
-972
README.md
README.md
+1
-1
editor-file.js
client/js/components/editor-file.js
+0
-361
editor-file.vue
client/js/components/editor-file.vue
+112
-14
editor-image.js
client/js/components/editor-image.js
+0
-407
editor.component.js
client/js/components/editor.component.js
+2
-2
editor-file.js
client/js/store/modules/editor-file.js
+5
-2
browser.json
server/locales/en/browser.json
+9
-1
editor-file.pug
server/views/modals/editor-file.pug
+0
-80
editor-image.pug
server/views/modals/editor-image.pug
+0
-104
create.pug
server/views/pages/create.pug
+1
-0
No files found.
README.md
View file @
5d155028
...
...
@@ -48,7 +48,7 @@ Current and upcoming milestones *(major features only, see the [changelog](https
### Beta 12
> *Planned for early June release*
![
Progress
](
http://progressed.io/bar/
8
5
)
![
Progress
](
http://progressed.io/bar/
9
5
)
-
[
x
]
Anchor with Copy to clipboard function
-
[
x
]
Full UI Localization
...
...
client/js/components/editor-file.js
deleted
100644 → 0
View file @
c38ba72b
'use strict'
import
$
from
'jquery'
import
Vue
from
'vue'
import
_
from
'lodash'
import
'jquery-contextmenu'
import
'jquery-simple-upload'
module
.
exports
=
(
alerts
,
mde
,
mdeModalOpenState
,
socket
)
=>
{
let
vueFile
=
new
Vue
({
el
:
'#modal-editor-file'
,
data
:
{
isLoading
:
false
,
isLoadingText
:
''
,
newFolderName
:
''
,
newFolderShow
:
false
,
newFolderError
:
false
,
folders
:
[],
currentFolder
:
''
,
currentFile
:
''
,
files
:
[],
uploadSucceeded
:
false
,
postUploadChecks
:
0
,
renameFileShow
:
false
,
renameFileId
:
''
,
renameFileFilename
:
''
,
deleteFileShow
:
false
,
deleteFileId
:
''
,
deleteFileFilename
:
''
},
methods
:
{
open
:
()
=>
{
mdeModalOpenState
=
true
// eslint-disable-line no-undef
$
(
'#modal-editor-file'
).
addClass
(
'is-active'
)
vueFile
.
refreshFolders
()
},
cancel
:
(
ev
)
=>
{
mdeModalOpenState
=
false
// eslint-disable-line no-undef
$
(
'#modal-editor-file'
).
removeClass
(
'is-active'
)
},
// -------------------------------------------
// INSERT LINK TO FILE
// -------------------------------------------
selectFile
:
(
fileId
)
=>
{
vueFile
.
currentFile
=
fileId
},
insertFileLink
:
(
ev
)
=>
{
if
(
mde
.
codemirror
.
doc
.
somethingSelected
())
{
mde
.
codemirror
.
execCommand
(
'singleSelection'
)
}
let
selFile
=
_
.
find
(
vueFile
.
files
,
[
'_id'
,
vueFile
.
currentFile
])
selFile
.
normalizedPath
=
(
selFile
.
folder
===
'f:'
)
?
selFile
.
filename
:
selFile
.
folder
.
slice
(
2
)
+
'/'
+
selFile
.
filename
selFile
.
titleGuess
=
_
.
startCase
(
selFile
.
basename
)
let
fileText
=
'['
+
selFile
.
titleGuess
+
'](/uploads/'
+
selFile
.
normalizedPath
+
' "'
+
selFile
.
titleGuess
+
'")'
mde
.
codemirror
.
doc
.
replaceSelection
(
fileText
)
vueFile
.
cancel
()
},
// -------------------------------------------
// NEW FOLDER
// -------------------------------------------
newFolder
:
(
ev
)
=>
{
vueFile
.
newFolderName
=
''
vueFile
.
newFolderError
=
false
vueFile
.
newFolderShow
=
true
_
.
delay
(()
=>
{
$
(
'#txt-editor-file-newfoldername'
).
focus
()
},
400
)
},
newFolderDiscard
:
(
ev
)
=>
{
vueFile
.
newFolderShow
=
false
},
newFolderCreate
:
(
ev
)
=>
{
let
regFolderName
=
new
RegExp
(
'^[a-z0-9][a-z0-9-]*[a-z0-9]$'
)
vueFile
.
newFolderName
=
_
.
kebabCase
(
_
.
trim
(
vueFile
.
newFolderName
))
if
(
_
.
isEmpty
(
vueFile
.
newFolderName
)
||
!
regFolderName
.
test
(
vueFile
.
newFolderName
))
{
vueFile
.
newFolderError
=
true
return
}
vueFile
.
newFolderDiscard
()
vueFile
.
isLoadingText
=
'Creating new folder...'
vueFile
.
isLoading
=
true
Vue
.
nextTick
(()
=>
{
socket
.
emit
(
'uploadsCreateFolder'
,
{
foldername
:
vueFile
.
newFolderName
},
(
data
)
=>
{
vueFile
.
folders
=
data
vueFile
.
currentFolder
=
vueFile
.
newFolderName
vueFile
.
files
=
[]
vueFile
.
isLoading
=
false
})
})
},
// -------------------------------------------
// RENAME FILE
// -------------------------------------------
renameFile
:
()
=>
{
let
c
=
_
.
find
(
vueFile
.
files
,
[
'_id'
,
vueFile
.
renameFileId
])
vueFile
.
renameFileFilename
=
c
.
basename
||
''
vueFile
.
renameFileShow
=
true
_
.
delay
(()
=>
{
$
(
'#txt-editor-renamefile'
).
focus
()
_
.
defer
(()
=>
{
$
(
'#txt-editor-file-rename'
).
select
()
})
},
400
)
},
renameFileDiscard
:
()
=>
{
vueFile
.
renameFileShow
=
false
},
renameFileGo
:
()
=>
{
vueFile
.
renameFileDiscard
()
vueFile
.
isLoadingText
=
'Renaming file...'
vueFile
.
isLoading
=
true
Vue
.
nextTick
(()
=>
{
socket
.
emit
(
'uploadsRenameFile'
,
{
uid
:
vueFile
.
renameFileId
,
folder
:
vueFile
.
currentFolder
,
filename
:
vueFile
.
renameFileFilename
},
(
data
)
=>
{
if
(
data
.
ok
)
{
vueFile
.
waitChangeComplete
(
vueFile
.
files
.
length
,
false
)
}
else
{
vueFile
.
isLoading
=
false
alerts
.
pushError
(
'Rename error'
,
data
.
msg
)
}
})
})
},
// -------------------------------------------
// MOVE FILE
// -------------------------------------------
moveFile
:
(
uid
,
fld
)
=>
{
vueFile
.
isLoadingText
=
'Moving file...'
vueFile
.
isLoading
=
true
Vue
.
nextTick
(()
=>
{
socket
.
emit
(
'uploadsMoveFile'
,
{
uid
,
folder
:
fld
},
(
data
)
=>
{
if
(
data
.
ok
)
{
vueFile
.
loadFiles
()
}
else
{
vueFile
.
isLoading
=
false
alerts
.
pushError
(
'Rename error'
,
data
.
msg
)
}
})
})
},
// -------------------------------------------
// DELETE FILE
// -------------------------------------------
deleteFileWarn
:
(
show
)
=>
{
if
(
show
)
{
let
c
=
_
.
find
(
vueFile
.
files
,
[
'_id'
,
vueFile
.
deleteFileId
])
vueFile
.
deleteFileFilename
=
c
.
filename
||
'this file'
}
vueFile
.
deleteFileShow
=
show
},
deleteFileGo
:
()
=>
{
vueFile
.
deleteFileWarn
(
false
)
vueFile
.
isLoadingText
=
'Deleting file...'
vueFile
.
isLoading
=
true
Vue
.
nextTick
(()
=>
{
socket
.
emit
(
'uploadsDeleteFile'
,
{
uid
:
vueFile
.
deleteFileId
},
(
data
)
=>
{
vueFile
.
loadFiles
()
})
})
},
// -------------------------------------------
// LOAD FROM REMOTE
// -------------------------------------------
selectFolder
:
(
fldName
)
=>
{
vueFile
.
currentFolder
=
fldName
vueFile
.
loadFiles
()
},
refreshFolders
:
()
=>
{
vueFile
.
isLoadingText
=
'Fetching folders list...'
vueFile
.
isLoading
=
true
vueFile
.
currentFolder
=
''
vueFile
.
currentImage
=
''
Vue
.
nextTick
(()
=>
{
socket
.
emit
(
'uploadsGetFolders'
,
{
},
(
data
)
=>
{
vueFile
.
folders
=
data
vueFile
.
loadFiles
()
})
})
},
loadFiles
:
(
silent
)
=>
{
if
(
!
silent
)
{
vueFile
.
isLoadingText
=
'Fetching files...'
vueFile
.
isLoading
=
true
}
return
new
Promise
((
resolve
,
reject
)
=>
{
Vue
.
nextTick
(()
=>
{
socket
.
emit
(
'uploadsGetFiles'
,
{
folder
:
vueFile
.
currentFolder
},
(
data
)
=>
{
vueFile
.
files
=
data
if
(
!
silent
)
{
vueFile
.
isLoading
=
false
}
vueFile
.
attachContextMenus
()
resolve
(
true
)
})
})
})
},
waitChangeComplete
:
(
oldAmount
,
expectChange
)
=>
{
expectChange
=
(
_
.
isBoolean
(
expectChange
))
?
expectChange
:
true
vueFile
.
postUploadChecks
++
vueFile
.
isLoadingText
=
'Processing...'
Vue
.
nextTick
(()
=>
{
vueFile
.
loadFiles
(
true
).
then
(()
=>
{
if
((
vueFile
.
files
.
length
!==
oldAmount
)
===
expectChange
)
{
vueFile
.
postUploadChecks
=
0
vueFile
.
isLoading
=
false
}
else
if
(
vueFile
.
postUploadChecks
>
5
)
{
vueFile
.
postUploadChecks
=
0
vueFile
.
isLoading
=
false
alerts
.
pushError
(
'Unable to fetch updated listing'
,
'Try again later'
)
}
else
{
_
.
delay
(()
=>
{
vueFile
.
waitChangeComplete
(
oldAmount
,
expectChange
)
},
1500
)
}
})
})
},
// -------------------------------------------
// IMAGE CONTEXT MENU
// -------------------------------------------
attachContextMenus
:
()
=>
{
let
moveFolders
=
_
.
map
(
vueFile
.
folders
,
(
f
)
=>
{
return
{
name
:
(
f
!==
''
)
?
f
:
'/ (root)'
,
icon
:
'fa-folder'
,
callback
:
(
key
,
opt
)
=>
{
let
moveFileId
=
_
.
toString
(
$
(
opt
.
$trigger
).
data
(
'uid'
))
let
moveFileDestFolder
=
_
.
nth
(
vueFile
.
folders
,
key
)
vueFile
.
moveFile
(
moveFileId
,
moveFileDestFolder
)
}
}
})
$
.
contextMenu
(
'destroy'
,
'.editor-modal-file-choices > figure'
)
$
.
contextMenu
({
selector
:
'.editor-modal-file-choices > figure'
,
appendTo
:
'.editor-modal-file-choices'
,
position
:
(
opt
,
x
,
y
)
=>
{
$
(
opt
.
$trigger
).
addClass
(
'is-contextopen'
)
let
trigPos
=
$
(
opt
.
$trigger
).
position
()
let
trigDim
=
{
w
:
$
(
opt
.
$trigger
).
width
()
/
5
,
h
:
$
(
opt
.
$trigger
).
height
()
/
2
}
opt
.
$menu
.
css
({
top
:
trigPos
.
top
+
trigDim
.
h
,
left
:
trigPos
.
left
+
trigDim
.
w
})
},
events
:
{
hide
:
(
opt
)
=>
{
$
(
opt
.
$trigger
).
removeClass
(
'is-contextopen'
)
}
},
items
:
{
rename
:
{
name
:
'Rename'
,
icon
:
'fa-edit'
,
callback
:
(
key
,
opt
)
=>
{
vueFile
.
renameFileId
=
_
.
toString
(
opt
.
$trigger
[
0
].
dataset
.
uid
)
vueFile
.
renameFile
()
}
},
move
:
{
name
:
'Move to...'
,
icon
:
'fa-folder-open-o'
,
items
:
moveFolders
},
delete
:
{
name
:
'Delete'
,
icon
:
'fa-trash'
,
callback
:
(
key
,
opt
)
=>
{
vueFile
.
deleteFileId
=
_
.
toString
(
opt
.
$trigger
[
0
].
dataset
.
uid
)
vueFile
.
deleteFileWarn
(
true
)
}
}
}
})
}
}
})
$
(
'#btn-editor-file-upload input'
).
on
(
'change'
,
(
ev
)
=>
{
let
curFileAmount
=
vueFile
.
files
.
length
$
(
ev
.
currentTarget
).
simpleUpload
(
'/uploads/file'
,
{
name
:
'binfile'
,
data
:
{
folder
:
vueFile
.
currentFolder
},
limit
:
20
,
expect
:
'json'
,
maxFileSize
:
0
,
init
:
(
totalUploads
)
=>
{
vueFile
.
uploadSucceeded
=
false
vueFile
.
isLoadingText
=
'Preparing to upload...'
vueFile
.
isLoading
=
true
},
progress
:
(
progress
)
=>
{
vueFile
.
isLoadingText
=
'Uploading...'
+
Math
.
round
(
progress
)
+
'%'
},
success
:
(
data
)
=>
{
if
(
data
.
ok
)
{
let
failedUpls
=
_
.
filter
(
data
.
results
,
[
'ok'
,
false
])
if
(
failedUpls
.
length
)
{
_
.
forEach
(
failedUpls
,
(
u
)
=>
{
alerts
.
pushError
(
'Upload error'
,
u
.
msg
)
})
if
(
failedUpls
.
length
<
data
.
results
.
length
)
{
alerts
.
push
({
title
:
'Some uploads succeeded'
,
message
:
'Files that are not mentionned in the errors above were uploaded successfully.'
})
vueFile
.
uploadSucceeded
=
true
}
}
else
{
vueFile
.
uploadSucceeded
=
true
}
}
else
{
alerts
.
pushError
(
'Upload error'
,
data
.
msg
)
}
},
error
:
(
error
)
=>
{
alerts
.
pushError
(
'Upload error'
,
error
.
message
)
},
finish
:
()
=>
{
if
(
vueFile
.
uploadSucceeded
)
{
vueFile
.
waitChangeComplete
(
curFileAmount
,
true
)
}
else
{
vueFile
.
isLoading
=
false
}
}
})
})
return
vueFile
}
client/js/components/editor-file.vue
View file @
5d155028
...
...
@@ -7,7 +7,7 @@
transition(name='modal-content')
.modal-content.is-expanded(v-show='isShown')
header.is-green
span
{{
$t
(
'editor.fil
etitle'
)
}}
span
{{
(
mode
===
'file'
)
?
$t
(
'editor.filetitle'
)
:
$t
(
'editor.imag
etitle'
)
}}
p.modal-notify(:class='{ "is-active": isLoading }')
span
{{
isLoadingText
}}
i
...
...
@@ -17,9 +17,12 @@
span
{{
$t
(
'editor.newfolder'
)
}}
a.button#btn-editor-file-upload
i.icon-cloud-upload
span
{{
$t
(
'editor.fil
eupload'
)
}}
span
{{
(
mode
===
'file'
)
?
$t
(
'editor.fileupload'
)
:
$t
(
'editor.imag
eupload'
)
}}
label
input(type='file', multiple, :disabled='isLoading', ref='editorFileUploadInput')
a.button(v-if='mode === "image"', @click='fetchFromUrl')
i.icon-cloud-download
span Fetch from URL
section.is-gapless
.columns.is-stretched
.column.is-one-quarter.modal-sidebar.is-green(style={'max-width':'350px'})
...
...
@@ -29,7 +32,15 @@
a(@click='selectFolder(fld)', :class='{ "is-active": currentFolder === fld }')
i.icon-folder2
span /
{{
fld
}}
.column.editor-modal-file-choices
.model-sidebar-header(v-if='mode === "image"') Alignment
.model-sidebar-content(v-if='mode === "image"')
p.control.is-fullwidth
select(v-model='currentAlign')
option(value='left')
{{
$t
(
'editor.imagealignleft'
)
}}
option(value='center')
{{
$t
(
'editor.imagealigncenter'
)
}}
option(value='right')
{{
$t
(
'editor.imagealignright'
)
}}
option(value='logo')
{{
$t
(
'editor.imagealignlogo'
)
}}
.column.editor-modal-choices.editor-modal-file-choices(v-if='mode === "file"')
figure(v-for='fl in files', :class='{ "is-active": currentFile === fl._id }', @click='selectFile(fl._id)', :data-uid='fl._id')
i(class='icon-file')
span: strong
{{
fl
.
filename
}}
...
...
@@ -38,9 +49,17 @@
em(v-show='files.length < 1')
i.icon-marquee-minus
|
{{
$t
(
'editor.filefolderempty'
)
}}
.column.editor-modal-choices.editor-modal-image-choices(v-if='mode === "image"')
figure(v-for='img in files', v-bind:class='{ "is-active": currentFile === img._id }', v-on:click='selectFile(img._id)', v-bind:data-uid='img._id')
img(v-bind:src='"/uploads/t/" + img._id + ".png"')
span: strong
{{
img
.
basename
}}
span
{{
filesize
(
img
.
filesize
)
}}
em(v-show='files.length < 1')
i.icon-marquee-minus
|
{{
$t
(
'editor.filefolderempty'
)
}}
footer
a.button.is-grey.is-outlined(@click='cancel')
{{
$t
(
'editor.discard'
)
}}
a.button.is-green(@click='insertFileLink')
{{
$t
(
'editor.fil
einsert'
)
}}
a.button.is-green(@click='insertFileLink')
{{
(
mode
===
'file'
)
?
$t
(
'editor.fileinsert'
)
:
$t
(
'editor.imag
einsert'
)
}}
transition(:duration="400")
.modal.is-superimposed(v-show='newFolderShow')
...
...
@@ -60,6 +79,23 @@
a.button.is-light-blue(@click='newFolderCreate')
{{
$t
(
'modal.create'
)
}}
transition(:duration="400")
.modal.is-superimposed(v-show='fetchFromUrlShow')
transition(name='modal-background')
.modal-background(v-show='fetchFromUrlShow')
.modal-container
transition(name='modal-content')
.modal-content(v-show='fetchFromUrlShow')
header.is-light-blue Fetch Image from URL
section
label.label Enter full URL path to the image:
p.control.is-fullwidth
input.input(type='text', placeholder='http://www.example.com/some-image.png', v-model='fetchFromUrlURL', ref='editorFileFetchInput', @keyup.enter='fetchFromUrlGo', @keyup.esc='fetchFromUrlDiscard')
span.help.is-danger.is-hidden This URL path is invalid!
footer
a.button.is-grey.is-outlined(v-on:click='fetchFromUrlDiscard') Discard
a.button.is-light-blue(v-on:click='fetchFromUrlGo') Fetch
transition(:duration="400")
.modal.is-superimposed(v-show='renameFileShow')
transition(name='modal-background')
.modal-background(v-show='renameFileShow')
...
...
@@ -101,9 +137,12 @@
newFolderName
:
''
,
newFolderShow
:
false
,
newFolderError
:
false
,
fetchFromUrlURL
:
''
,
fetchFromUrlShow
:
false
,
folders
:
[],
currentFolder
:
''
,
currentFile
:
''
,
currentAlign
:
'left'
,
files
:
[],
uploadSucceeded
:
false
,
postUploadChecks
:
0
,
...
...
@@ -118,6 +157,9 @@
computed
:
{
isShown
()
{
return
this
.
$store
.
state
.
editorFile
.
shown
},
mode
()
{
return
this
.
$store
.
state
.
editorFile
.
mode
}
},
methods
:
{
...
...
@@ -145,13 +187,30 @@
selFile
.
normalizedPath
=
(
selFile
.
folder
===
'f:'
)
?
selFile
.
filename
:
selFile
.
folder
.
slice
(
2
)
+
'/'
+
selFile
.
filename
selFile
.
titleGuess
=
this
.
_
.
startCase
(
selFile
.
basename
)
let
fileText
=
'['
+
selFile
.
titleGuess
+
'](/uploads/'
+
selFile
.
normalizedPath
+
' "'
+
selFile
.
titleGuess
+
'")'
let
textToInsert
=
''
if
(
this
.
mode
===
'image'
)
{
textToInsert
=
'!['
+
selFile
.
titleGuess
+
'](/uploads/'
+
selFile
.
normalizedPath
+
' "'
+
selFile
.
titleGuess
+
'")'
switch
(
this
.
currentAlign
)
{
case
'center'
:
textToInsert
+=
'{.align-center}'
break
case
'right'
:
textToInsert
+=
'{.align-right}'
break
case
'logo'
:
textToInsert
+=
'{.pagelogo}'
break
}
}
else
{
textToInsert
=
'['
+
selFile
.
titleGuess
+
'](/uploads/'
+
selFile
.
normalizedPath
+
' "'
+
selFile
.
titleGuess
+
'")'
}
this
.
$store
.
dispatch
(
'editor/insert'
,
fileTex
t
)
this
.
$store
.
dispatch
(
'editor/insert'
,
textToInser
t
)
this
.
$store
.
dispatch
(
'alert'
,
{
style
:
'blue'
,
icon
:
'paper'
,
msg
:
this
.
$t
(
'editor.fil
esuccess'
)
msg
:
(
this
.
mode
===
'file'
)
?
this
.
$t
(
'editor.filesuccess'
)
:
this
.
$t
(
'editor.imag
esuccess'
)
})
this
.
cancel
()
},
...
...
@@ -200,6 +259,41 @@
},
// -------------------------------------------
// FETCH FROM URL
// -------------------------------------------
fetchFromUrl
()
{
let
self
=
this
this
.
fetchFromUrlURL
=
''
this
.
fetchFromUrlShow
=
true
this
.
_
.
delay
(()
=>
{
self
.
$refs
.
editorFileFetchInput
.
focus
()
},
400
)
},
fetchFromUrlDiscard
()
{
this
.
fetchFromUrlShow
=
false
},
fetchFromUrlGo
()
{
let
self
=
this
this
.
fetchFromUrlDiscard
()
this
.
isLoadingText
=
'Fetching image...'
this
.
isLoading
=
true
this
.
$nextTick
(()
=>
{
socket
.
emit
(
'uploadsFetchFileFromURL'
,
{
folder
:
self
.
currentFolder
,
fetchUrl
:
self
.
fetchFromUrlURL
},
(
data
)
=>
{
if
(
data
.
ok
)
{
self
.
waitChangeComplete
(
self
.
files
.
length
,
true
)
}
else
{
self
.
isLoading
=
false
self
.
$store
.
dispatch
(
'alert'
,
{
style
:
'red'
,
icon
:
'square-cross'
,
msg
:
self
.
$t
(
'editor.fileuploaderror'
,
{
err
:
data
.
msg
})
})
}
})
})
},
// -------------------------------------------
// RENAME FILE
// -------------------------------------------
...
...
@@ -325,7 +419,8 @@
}
return
new
Promise
((
resolve
,
reject
)
=>
{
self
.
$nextTick
(()
=>
{
socket
.
emit
(
'uploadsGetFiles'
,
{
folder
:
self
.
currentFolder
},
(
data
)
=>
{
let
loadAction
=
(
self
.
mode
===
'image'
)
?
'uploadsGetImages'
:
'uploadsGetFiles'
socket
.
emit
(
loadAction
,
{
folder
:
self
.
currentFolder
},
(
data
)
=>
{
self
.
files
=
data
if
(
!
silent
)
{
self
.
isLoading
=
false
...
...
@@ -384,10 +479,10 @@
}
})
$
.
contextMenu
(
'destroy'
,
'.editor-modal-
file-
choices > figure'
)
$
.
contextMenu
(
'destroy'
,
'.editor-modal-choices > figure'
)
$
.
contextMenu
({
selector
:
'.editor-modal-
file-
choices > figure'
,
appendTo
:
'.editor-modal-
file-
choices'
,
selector
:
'.editor-modal-choices > figure'
,
appendTo
:
'.editor-modal-choices'
,
position
:
(
opt
,
x
,
y
)
=>
{
$
(
opt
.
$trigger
).
addClass
(
'is-contextopen'
)
let
trigPos
=
$
(
opt
.
$trigger
).
position
()
...
...
@@ -427,16 +522,19 @@
upload
()
{
let
self
=
this
let
curFileAmount
=
this
.
files
.
length
let
uplUrl
=
(
self
.
mode
===
'image'
)
?
'/uploads/img'
:
'/uploads/file'
$
(
this
.
$refs
.
editorFileUploadInput
).
simpleUpload
(
'/uploads/file'
,
{
$
(
this
.
$refs
.
editorFileUploadInput
).
simpleUpload
(
uplUrl
,
{
name
:
'binfile'
,
name
:
(
self
.
mode
===
'image'
)
?
'imgfile'
:
'binfile'
,
data
:
{
folder
:
self
.
currentFolder
},
limit
:
20
,
expect
:
'json'
,
maxFileSize
:
0
,
allowedExts
:
(
self
.
mode
===
'image'
)
?
[
'jpg'
,
'jpeg'
,
'gif'
,
'png'
,
'webp'
]
:
undefined
,
allowedTypes
:
(
self
.
mode
===
'image'
)
?
[
'image/png'
,
'image/jpeg'
,
'image/gif'
,
'image/webp'
]
:
undefined
,
maxFileSize
:
(
self
.
mode
===
'image'
)
?
3145728
:
0
,
// max 3 MB
init
:
(
totalUploads
)
=>
{
self
.
uploadSucceeded
=
false
...
...
client/js/components/editor-image.js
deleted
100644 → 0
View file @
c38ba72b
'use strict'
import
$
from
'jquery'
import
Vue
from
'vue'
import
_
from
'lodash'
import
'jquery-contextmenu'
import
'jquery-simple-upload'
module
.
exports
=
(
alerts
,
mde
,
mdeModalOpenState
,
socket
)
=>
{
let
vueImage
=
new
Vue
({
el
:
'#modal-editor-image'
,
data
:
{
isLoading
:
false
,
isLoadingText
:
''
,
newFolderName
:
''
,
newFolderShow
:
false
,
newFolderError
:
false
,
fetchFromUrlURL
:
''
,
fetchFromUrlShow
:
false
,
folders
:
[],
currentFolder
:
''
,
currentImage
:
''
,
currentAlign
:
'left'
,
images
:
[],
uploadSucceeded
:
false
,
postUploadChecks
:
0
,
renameImageShow
:
false
,
renameImageId
:
''
,
renameImageFilename
:
''
,
deleteImageShow
:
false
,
deleteImageId
:
''
,
deleteImageFilename
:
''
},
methods
:
{
open
:
()
=>
{
mdeModalOpenState
=
true
$
(
'#modal-editor-image'
).
addClass
(
'is-active'
)
vueImage
.
refreshFolders
()
},
cancel
:
(
ev
)
=>
{
mdeModalOpenState
=
false
$
(
'#modal-editor-image'
).
removeClass
(
'is-active'
)
},
// -------------------------------------------
// INSERT IMAGE
// -------------------------------------------
selectImage
:
(
imageId
)
=>
{
vueImage
.
currentImage
=
imageId
},
insertImage
:
(
ev
)
=>
{
console
.
log
(
mde
)
if
(
mde
.
codemirror
.
doc
.
somethingSelected
())
{
mde
.
codemirror
.
execCommand
(
'singleSelection'
)
}
let
selImage
=
_
.
find
(
vueImage
.
images
,
[
'_id'
,
vueImage
.
currentImage
])
selImage
.
normalizedPath
=
(
selImage
.
folder
===
'f:'
)
?
selImage
.
filename
:
selImage
.
folder
.
slice
(
2
)
+
'/'
+
selImage
.
filename
selImage
.
titleGuess
=
_
.
startCase
(
selImage
.
basename
)
let
imageText
=
'!['
+
selImage
.
titleGuess
+
'](/uploads/'
+
selImage
.
normalizedPath
+
' "'
+
selImage
.
titleGuess
+
'")'
switch
(
vueImage
.
currentAlign
)
{
case
'center'
:
imageText
+=
'{.align-center}'
break
case
'right'
:
imageText
+=
'{.align-right}'
break
case
'logo'
:
imageText
+=
'{.pagelogo}'
break
}
mde
.
codemirror
.
doc
.
replaceSelection
(
imageText
)
vueImage
.
cancel
()
},
// -------------------------------------------
// NEW FOLDER
// -------------------------------------------
newFolder
:
(
ev
)
=>
{
vueImage
.
newFolderName
=
''
vueImage
.
newFolderError
=
false
vueImage
.
newFolderShow
=
true
_
.
delay
(()
=>
{
$
(
'#txt-editor-image-newfoldername'
).
focus
()
},
400
)
},
newFolderDiscard
:
(
ev
)
=>
{
vueImage
.
newFolderShow
=
false
},
newFolderCreate
:
(
ev
)
=>
{
let
regFolderName
=
new
RegExp
(
'^[a-z0-9][a-z0-9-]*[a-z0-9]$'
)
vueImage
.
newFolderName
=
_
.
kebabCase
(
_
.
trim
(
vueImage
.
newFolderName
))
if
(
_
.
isEmpty
(
vueImage
.
newFolderName
)
||
!
regFolderName
.
test
(
vueImage
.
newFolderName
))
{
vueImage
.
newFolderError
=
true
return
}
vueImage
.
newFolderDiscard
()
vueImage
.
isLoadingText
=
'Creating new folder...'
vueImage
.
isLoading
=
true
Vue
.
nextTick
(()
=>
{
socket
.
emit
(
'uploadsCreateFolder'
,
{
foldername
:
vueImage
.
newFolderName
},
(
data
)
=>
{
vueImage
.
folders
=
data
vueImage
.
currentFolder
=
vueImage
.
newFolderName
vueImage
.
images
=
[]
vueImage
.
isLoading
=
false
})
})
},
// -------------------------------------------
// FETCH FROM URL
// -------------------------------------------
fetchFromUrl
:
(
ev
)
=>
{
vueImage
.
fetchFromUrlURL
=
''
vueImage
.
fetchFromUrlShow
=
true
_
.
delay
(()
=>
{
$
(
'#txt-editor-image-fetchurl'
).
focus
()
},
400
)
},
fetchFromUrlDiscard
:
(
ev
)
=>
{
vueImage
.
fetchFromUrlShow
=
false
},
fetchFromUrlGo
:
(
ev
)
=>
{
vueImage
.
fetchFromUrlDiscard
()
vueImage
.
isLoadingText
=
'Fetching image...'
vueImage
.
isLoading
=
true
Vue
.
nextTick
(()
=>
{
socket
.
emit
(
'uploadsFetchFileFromURL'
,
{
folder
:
vueImage
.
currentFolder
,
fetchUrl
:
vueImage
.
fetchFromUrlURL
},
(
data
)
=>
{
if
(
data
.
ok
)
{
vueImage
.
waitChangeComplete
(
vueImage
.
images
.
length
,
true
)
}
else
{
vueImage
.
isLoading
=
false
alerts
.
pushError
(
'Upload error'
,
data
.
msg
)
}
})
})
},
// -------------------------------------------
// RENAME IMAGE
// -------------------------------------------
renameImage
:
()
=>
{
let
c
=
_
.
find
(
vueImage
.
images
,
[
'_id'
,
vueImage
.
renameImageId
])
vueImage
.
renameImageFilename
=
c
.
basename
||
''
vueImage
.
renameImageShow
=
true
_
.
delay
(()
=>
{
$
(
'#txt-editor-image-rename'
).
focus
()
_
.
defer
(()
=>
{
$
(
'#txt-editor-image-rename'
).
select
()
})
},
400
)
},
renameImageDiscard
:
()
=>
{
vueImage
.
renameImageShow
=
false
},
renameImageGo
:
()
=>
{
vueImage
.
renameImageDiscard
()
vueImage
.
isLoadingText
=
'Renaming image...'
vueImage
.
isLoading
=
true
Vue
.
nextTick
(()
=>
{
socket
.
emit
(
'uploadsRenameFile'
,
{
uid
:
vueImage
.
renameImageId
,
folder
:
vueImage
.
currentFolder
,
filename
:
vueImage
.
renameImageFilename
},
(
data
)
=>
{
if
(
data
.
ok
)
{
vueImage
.
waitChangeComplete
(
vueImage
.
images
.
length
,
false
)
}
else
{
vueImage
.
isLoading
=
false
alerts
.
pushError
(
'Rename error'
,
data
.
msg
)
}
})
})
},
// -------------------------------------------
// MOVE IMAGE
// -------------------------------------------
moveImage
:
(
uid
,
fld
)
=>
{
vueImage
.
isLoadingText
=
'Moving image...'
vueImage
.
isLoading
=
true
Vue
.
nextTick
(()
=>
{
socket
.
emit
(
'uploadsMoveFile'
,
{
uid
,
folder
:
fld
},
(
data
)
=>
{
if
(
data
.
ok
)
{
vueImage
.
loadImages
()
}
else
{
vueImage
.
isLoading
=
false
alerts
.
pushError
(
'Rename error'
,
data
.
msg
)
}
})
})
},
// -------------------------------------------
// DELETE IMAGE
// -------------------------------------------
deleteImageWarn
:
(
show
)
=>
{
if
(
show
)
{
let
c
=
_
.
find
(
vueImage
.
images
,
[
'_id'
,
vueImage
.
deleteImageId
])
vueImage
.
deleteImageFilename
=
c
.
filename
||
'this image'
}
vueImage
.
deleteImageShow
=
show
},
deleteImageGo
:
()
=>
{
vueImage
.
deleteImageWarn
(
false
)
vueImage
.
isLoadingText
=
'Deleting image...'
vueImage
.
isLoading
=
true
Vue
.
nextTick
(()
=>
{
socket
.
emit
(
'uploadsDeleteFile'
,
{
uid
:
vueImage
.
deleteImageId
},
(
data
)
=>
{
vueImage
.
loadImages
()
})
})
},
// -------------------------------------------
// LOAD FROM REMOTE
// -------------------------------------------
selectFolder
:
(
fldName
)
=>
{
vueImage
.
currentFolder
=
fldName
vueImage
.
loadImages
()
},
refreshFolders
:
()
=>
{
vueImage
.
isLoadingText
=
'Fetching folders list...'
vueImage
.
isLoading
=
true
vueImage
.
currentFolder
=
''
vueImage
.
currentImage
=
''
Vue
.
nextTick
(()
=>
{
socket
.
emit
(
'uploadsGetFolders'
,
{
},
(
data
)
=>
{
vueImage
.
folders
=
data
vueImage
.
loadImages
()
})
})
},
loadImages
:
(
silent
)
=>
{
if
(
!
silent
)
{
vueImage
.
isLoadingText
=
'Fetching images...'
vueImage
.
isLoading
=
true
}
return
new
Promise
((
resolve
,
reject
)
=>
{
Vue
.
nextTick
(()
=>
{
socket
.
emit
(
'uploadsGetImages'
,
{
folder
:
vueImage
.
currentFolder
},
(
data
)
=>
{
vueImage
.
images
=
data
if
(
!
silent
)
{
vueImage
.
isLoading
=
false
}
vueImage
.
attachContextMenus
()
resolve
(
true
)
})
})
})
},
waitChangeComplete
:
(
oldAmount
,
expectChange
)
=>
{
expectChange
=
(
_
.
isBoolean
(
expectChange
))
?
expectChange
:
true
vueImage
.
postUploadChecks
++
vueImage
.
isLoadingText
=
'Processing...'
Vue
.
nextTick
(()
=>
{
vueImage
.
loadImages
(
true
).
then
(()
=>
{
if
((
vueImage
.
images
.
length
!==
oldAmount
)
===
expectChange
)
{
vueImage
.
postUploadChecks
=
0
vueImage
.
isLoading
=
false
}
else
if
(
vueImage
.
postUploadChecks
>
5
)
{
vueImage
.
postUploadChecks
=
0
vueImage
.
isLoading
=
false
alerts
.
pushError
(
'Unable to fetch updated listing'
,
'Try again later'
)
}
else
{
_
.
delay
(()
=>
{
vueImage
.
waitChangeComplete
(
oldAmount
,
expectChange
)
},
1500
)
}
})
})
},
// -------------------------------------------
// IMAGE CONTEXT MENU
// -------------------------------------------
attachContextMenus
:
()
=>
{
let
moveFolders
=
_
.
map
(
vueImage
.
folders
,
(
f
)
=>
{
return
{
name
:
(
f
!==
''
)
?
f
:
'/ (root)'
,
icon
:
'fa-folder'
,
callback
:
(
key
,
opt
)
=>
{
let
moveImageId
=
_
.
toString
(
$
(
opt
.
$trigger
).
data
(
'uid'
))
let
moveImageDestFolder
=
_
.
nth
(
vueImage
.
folders
,
key
)
vueImage
.
moveImage
(
moveImageId
,
moveImageDestFolder
)
}
}
})
$
.
contextMenu
(
'destroy'
,
'.editor-modal-image-choices > figure'
)
$
.
contextMenu
({
selector
:
'.editor-modal-image-choices > figure'
,
appendTo
:
'.editor-modal-image-choices'
,
position
:
(
opt
,
x
,
y
)
=>
{
$
(
opt
.
$trigger
).
addClass
(
'is-contextopen'
)
let
trigPos
=
$
(
opt
.
$trigger
).
position
()
let
trigDim
=
{
w
:
$
(
opt
.
$trigger
).
width
()
/
2
,
h
:
$
(
opt
.
$trigger
).
height
()
/
2
}
opt
.
$menu
.
css
({
top
:
trigPos
.
top
+
trigDim
.
h
,
left
:
trigPos
.
left
+
trigDim
.
w
})
},
events
:
{
hide
:
(
opt
)
=>
{
$
(
opt
.
$trigger
).
removeClass
(
'is-contextopen'
)
}
},
items
:
{
rename
:
{
name
:
'Rename'
,
icon
:
'fa-edit'
,
callback
:
(
key
,
opt
)
=>
{
vueImage
.
renameImageId
=
_
.
toString
(
opt
.
$trigger
[
0
].
dataset
.
uid
)
vueImage
.
renameImage
()
}
},
move
:
{
name
:
'Move to...'
,
icon
:
'fa-folder-open-o'
,
items
:
moveFolders
},
delete
:
{
name
:
'Delete'
,
icon
:
'fa-trash'
,
callback
:
(
key
,
opt
)
=>
{
vueImage
.
deleteImageId
=
_
.
toString
(
opt
.
$trigger
[
0
].
dataset
.
uid
)
vueImage
.
deleteImageWarn
(
true
)
}
}
}
})
}
}
})
$
(
'#btn-editor-image-upload input'
).
on
(
'change'
,
(
ev
)
=>
{
let
curImageAmount
=
vueImage
.
images
.
length
$
(
ev
.
currentTarget
).
simpleUpload
(
'/uploads/img'
,
{
name
:
'imgfile'
,
data
:
{
folder
:
vueImage
.
currentFolder
},
limit
:
20
,
expect
:
'json'
,
allowedExts
:
[
'jpg'
,
'jpeg'
,
'gif'
,
'png'
,
'webp'
],
allowedTypes
:
[
'image/png'
,
'image/jpeg'
,
'image/gif'
,
'image/webp'
],
maxFileSize
:
3145728
,
// max 3 MB
init
:
(
totalUploads
)
=>
{
vueImage
.
uploadSucceeded
=
false
vueImage
.
isLoadingText
=
'Preparing to upload...'
vueImage
.
isLoading
=
true
},
progress
:
(
progress
)
=>
{
vueImage
.
isLoadingText
=
'Uploading...'
+
Math
.
round
(
progress
)
+
'%'
},
success
:
(
data
)
=>
{
if
(
data
.
ok
)
{
let
failedUpls
=
_
.
filter
(
data
.
results
,
[
'ok'
,
false
])
if
(
failedUpls
.
length
)
{
_
.
forEach
(
failedUpls
,
(
u
)
=>
{
alerts
.
pushError
(
'Upload error'
,
u
.
msg
)
})
if
(
failedUpls
.
length
<
data
.
results
.
length
)
{
alerts
.
push
({
title
:
'Some uploads succeeded'
,
message
:
'Files that are not mentionned in the errors above were uploaded successfully.'
})
vueImage
.
uploadSucceeded
=
true
}
}
else
{
vueImage
.
uploadSucceeded
=
true
}
}
else
{
alerts
.
pushError
(
'Upload error'
,
data
.
msg
)
}
},
error
:
(
error
)
=>
{
alerts
.
pushError
(
error
.
message
,
this
.
upload
.
file
.
name
)
},
finish
:
()
=>
{
if
(
vueImage
.
uploadSucceeded
)
{
vueImage
.
waitChangeComplete
(
curImageAmount
,
true
)
}
else
{
vueImage
.
isLoading
=
false
}
}
})
})
return
vueImage
}
client/js/components/editor.component.js
View file @
5d155028
...
...
@@ -127,7 +127,7 @@ export default {
{
name
:
'image'
,
action
:
(
editor
)
=>
{
self
.
$store
.
dispatch
(
'editor
Image/open'
)
self
.
$store
.
dispatch
(
'editor
File/open'
,
{
mode
:
'image'
}
)
},
className
:
'icon-image'
,
title
:
'Insert Image'
...
...
@@ -135,7 +135,7 @@ export default {
{
name
:
'file'
,
action
:
(
editor
)
=>
{
self
.
$store
.
dispatch
(
'editorFile/open'
)
self
.
$store
.
dispatch
(
'editorFile/open'
,
{
mode
:
'file'
}
)
},
className
:
'icon-paper'
,
title
:
'Insert File'
...
...
client/js/store/modules/editor-file.js
View file @
5d155028
...
...
@@ -3,15 +3,18 @@
export
default
{
namespaced
:
true
,
state
:
{
shown
:
false
shown
:
false
,
mode
:
'image'
},
getters
:
{},
mutations
:
{
shownChange
:
(
state
,
shownState
)
=>
{
state
.
shown
=
shownState
}
shownChange
:
(
state
,
shownState
)
=>
{
state
.
shown
=
shownState
},
modeChange
:
(
state
,
modeState
)
=>
{
state
.
mode
=
modeState
}
},
actions
:
{
open
({
commit
},
opts
)
{
commit
(
'shownChange'
,
true
)
commit
(
'modeChange'
,
opts
.
mode
)
wikijs
.
$emit
(
'editorFile/init'
)
},
close
({
commit
})
{
commit
(
'shownChange'
,
false
)
}
...
...
server/locales/en/browser.json
View file @
5d155028
...
...
@@ -23,11 +23,19 @@
"filerenameaction"
:
"Rename"
,
"filesuccess"
:
"File link has been inserted."
,
"filetitle"
:
"Insert File"
,
"fileupload"
:
"Upload File"
,
"fileupload"
:
"Upload File
(s)
"
,
"fileuploaderror"
:
"Upload Error: {{err}}"
,
"fileuploadsuccess"
:
"File(s) uploaded successfully."
,
"folders"
:
"Folders"
,
"foldersloading"
:
"Fetching folders list..."
,
"imagetitle"
:
"Insert Image"
,
"imageinsert"
:
"Insert Image"
,
"imagesuccess"
:
"Image has been inserted."
,
"imageupload"
:
"Upload Image(s)"
,
"imagealignleft"
:
"Left (default)"
,
"imagealigncenter"
:
"Centered"
,
"imagealignright"
:
"Right"
,
"imagealignlogo"
:
"Page Logo"
,
"newfolder"
:
"New Folder"
,
"videoanymp4file"
:
"Any standard MP4 file"
,
"videoinsert"
:
"Insert Video"
,
...
...
server/views/modals/editor-file.pug
deleted
100644 → 0
View file @
c38ba72b
.modal#modal-editor-file
.modal-background
.modal-container
.modal-content.is-expanded
header.is-green
span Insert File
p.modal-notify(v-bind:class='{ "is-active": isLoading }')
span {{ isLoadingText }}
i
.modal-toolbar.is-green
a.button(v-on:click='newFolder')
i.fa.fa-folder
span New Folder
a.button#btn-editor-file-upload
i.fa.fa-upload
span Upload File
label
input(type='file', multiple)
section.is-gapless
.columns.is-stretched
.column.is-one-quarter.modal-sidebar.is-green(style={'max-width':'350px'})
.model-sidebar-header Folders
ul.model-sidebar-list
li(v-for='fld in folders')
a(v-on:click='selectFolder(fld)', v-bind:class='{ "is-active": currentFolder === fld }')
i.icon-folder2
span / {{ fld }}
.column.editor-modal-file-choices
figure(v-for='fl in files', v-bind:class='{ "is-active": currentFile === fl._id }', v-on:click='selectFile(fl._id)', v-bind:data-uid='fl._id')
i(class='icon-file')
span: strong {{ fl.filename }}
span {{ fl.mime }}
span {{ fl.filesize | filesize }}
em(v-show='files.length < 1')
i.icon-marquee-minus
| This folder is empty.
footer
a.button.is-grey.is-outlined(v-on:click='cancel') Discard
a.button.is-green(v-on:click='insertFileLink') Insert Link to File
.modal.is-superimposed(v-bind:class='{ "is-active": newFolderShow }')
.modal-background
.modal-container
.modal-content
header.is-light-blue New Folder
section
label.label Enter the new folder name:
p.control.is-fullwidth
input.input#txt-editor-file-newfoldername(type='text', placeholder='folder name', v-model='newFolderName', v-on:keyup.enter='newFolderCreate', v-on:keyup.esc='newFolderDiscard')
span.help.is-danger(v-show='newFolderError') This folder name is invalid!
footer
a.button.is-grey.is-outlined(v-on:click='newFolderDiscard') Discard
a.button.is-light-blue(v-on:click='newFolderCreate') Create
.modal.is-superimposed(v-bind:class='{ "is-active": renameFileShow }')
.modal-background
.modal-container
.modal-content
header.is-indigo Rename File
section
label.label Enter the new filename (without the extension) of the file:
p.control.is-fullwidth
input.input#txt-editor-file-rename(type='text', placeholder='filename', v-model='renameFileFilename')
span.help.is-danger.is-hidden This filename is invalid!
footer
a.button.is-grey.is-outlined(v-on:click='renameFileDiscard') Discard
a.button.is-light-blue(v-on:click='renameFileGo') Rename
.modal.is-superimposed(v-bind:class='{ "is-active": deleteFileShow }')
.modal-background
.modal-container
.modal-content
header.is-red Delete file?
section
span Are you sure you want to delete #[strong {{deleteFileFilename}}]?
footer
a.button.is-grey.is-outlined(v-on:click='deleteFileWarn(false)') Discard
a.button.is-red(v-on:click='deleteFileGo') Delete
server/views/modals/editor-image.pug
deleted
100644 → 0
View file @
c38ba72b
.modal#modal-editor-image
.modal-background
.modal-container
.modal-content.is-expanded
header.is-green
span Insert Image
p.modal-notify(v-bind:class='{ "is-active": isLoading }')
span {{ isLoadingText }}
i
.modal-toolbar.is-green
a.button(v-on:click='newFolder')
i.fa.fa-folder
span New Folder
a.button#btn-editor-image-upload
i.fa.fa-upload
span Upload Image
label
input(type='file', multiple)
a.button(v-on:click='fetchFromUrl')
i.fa.fa-download
span Fetch from URL
section.is-gapless
.columns.is-stretched
.column.is-one-quarter.modal-sidebar.is-green(style={'max-width':'350px'})
.model-sidebar-header Folders
ul.model-sidebar-list
li(v-for='fld in folders')
a(v-on:click='selectFolder(fld)', v-bind:class='{ "is-active": currentFolder === fld }')
i.icon-folder2
span / {{ fld }}
.model-sidebar-header Alignment
.model-sidebar-content
p.control.is-fullwidth
select(v-model='currentAlign')
option(value='left') Left (default)
option(value='center') Centered
option(value='right') Right
option(value='logo') Page Logo
.column.editor-modal-image-choices
figure(v-for='img in images', v-bind:class='{ "is-active": currentImage === img._id }', v-on:click='selectImage(img._id)', v-bind:data-uid='img._id')
img(v-bind:src='"/uploads/t/" + img._id + ".png"')
span: strong {{ img.basename }}
span {{ img.filesize | filesize }}
em(v-show='images.length < 1')
i.icon-marquee-minus
| This folder is empty.
footer
a.button.is-grey.is-outlined(v-on:click='cancel') Discard
a.button.is-green(v-on:click='insertImage') Insert Image
.modal.is-superimposed(v-bind:class='{ "is-active": newFolderShow }')
.modal-background
.modal-container
.modal-content
header.is-light-blue New Folder
section
label.label Enter the new folder name:
p.control.is-fullwidth
input.input#txt-editor-image-newfoldername(type='text', placeholder='folder name', v-model='newFolderName', v-on:keyup.enter='newFolderCreate', v-on:keyup.esc='newFolderDiscard')
span.help.is-danger(v-show='newFolderError') This folder name is invalid!
footer
a.button.is-grey.is-outlined(v-on:click='newFolderDiscard') Discard
a.button.is-light-blue(v-on:click='newFolderCreate') Create
.modal.is-superimposed(v-bind:class='{ "is-active": fetchFromUrlShow }')
.modal-background
.modal-container
.modal-content
header.is-light-blue Fetch Image from URL
section
label.label Enter full URL path to the image:
p.control.is-fullwidth
input.input#txt-editor-image-fetchurl(type='text', placeholder='http://www.example.com/some-image.png', v-model='fetchFromUrlURL')
span.help.is-danger.is-hidden This URL path is invalid!
footer
a.button.is-grey.is-outlined(v-on:click='fetchFromUrlDiscard') Discard
a.button.is-light-blue(v-on:click='fetchFromUrlGo') Fetch
.modal.is-superimposed(v-bind:class='{ "is-active": renameImageShow }')
.modal-background
.modal-container
.modal-content
header.is-indigo Rename Image
section
label.label Enter the new filename (without the extension) of the image:
p.control.is-fullwidth
input.input#txt-editor-image-rename(type='text', placeholder='filename', v-model='renameImageFilename')
span.help.is-danger.is-hidden This filename is invalid!
footer
a.button.is-grey.is-outlined(v-on:click='renameImageDiscard') Discard
a.button.is-light-blue(v-on:click='renameImageGo') Rename
.modal.is-superimposed(v-bind:class='{ "is-active": deleteImageShow }')
.modal-background
.modal-container
.modal-content
header.is-red Delete image?
section
span Are you sure you want to delete #[strong {{deleteImageFilename}}]?
footer
a.button.is-grey.is-outlined(v-on:click='deleteImageWarn(false)') Discard
a.button.is-red(v-on:click='deleteImageGo') Delete
server/views/pages/create.pug
View file @
5d155028
...
...
@@ -18,6 +18,7 @@ block content
.editor-area
textarea(ref='editorTextArea', v-pre)= pageData.markdown
editor-file
editor-video
editor-codeblock
modal-discard-page(mode='create', current-path=pageData.meta.path)
...
...
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