Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
scripta
eScriptorium
Commits
c5773736
Commit
c5773736
authored
Aug 21, 2020
by
Robin Tissot
Browse files
Trying to make diplo panel work.
parent
42e1fcba
Changes
6
Hide whitespace changes
Inline
Side-by-side
app/apps/api/views.py
View file @
c5773736
...
...
@@ -268,6 +268,7 @@ class LineViewSet(ModelViewSet):
if
errors
:
return
Response
(
errors
,
status
=
status
.
HTTP_400_BAD_REQUEST
)
return
Response
(
response
)
# return Response(status=200, data=response)
...
...
app/apps/core/static/js/edit/components/diplo_line.js
View file @
c5773736
...
...
@@ -27,56 +27,47 @@ var diploLine = LineBase.extend({
}
},
methods
:
{
startEdit
(
ev
){
// if we are selecting text we don't want to start editing
// to be able to do multiline selection
if
(
document
.
getSelection
().
toString
())
{
return
true
;
}
this
.
$parent
.
setEditLine
(
this
.
line
);
this
.
$parent
.
$parent
.
blockShortcuts
=
true
;
},
stopEdit
(
ev
)
{
this
.
$parent
.
$parent
.
blockShortcuts
=
false
;
},
setContent
(
content
){
let
id
=
this
.
line
.
pk
;
if
(
this
.
line
.
currentTrans
.
content
!=
content
){
$
(
"
#
"
+
id
).
text
(
content
);
this
.
line
.
currentTrans
.
content
=
content
;
}
cleanSource
(
dirtyText
)
{
// cleanup html and possibly other tags (?)
var
tmp
=
document
.
createElement
(
"
DIV
"
);
tmp
.
innerHTML
=
dirtyText
;
let
clean
=
tmp
.
textContent
||
tmp
.
innerText
||
""
;
tmp
.
remove
();
return
clean
;
},
onPaste
(
e
){
onPaste
(
e
)
{
let
pastedData
=
e
.
clipboardData
.
getData
(
'
text/plain
'
);
let
pasted_data_split
=
pastedData
.
split
(
'
\n
'
);
if
(
pasted_data_split
.
length
<
2
)
{
return
if
(
pasted_data_split
.
length
==
1
)
{
// all of this just to call cleanSource on the data
let
paste
=
(
event
.
clipboardData
||
window
.
clipboardData
).
getData
(
'
text
'
);
paste
=
this
.
cleanSource
(
paste
);
const
selection
=
window
.
getSelection
();
if
(
!
selection
.
rangeCount
)
return
false
;
selection
.
deleteFromDocument
();
selection
.
getRangeAt
(
0
).
insertNode
(
document
.
createTextNode
(
paste
));
}
else
{
e
.
preventDefault
();
//remove the last line if it's empty
if
(
pasted_data_split
[
pasted_data_split
.
length
-
1
]
==
""
)
if
(
pasted_data_split
[
pasted_data_split
.
length
-
1
]
==
""
)
{
pasted_data_split
.
pop
();
}
let
index
=
this
.
$parent
.
$children
.
indexOf
(
this
);
for
(
let
i
=
1
;
i
<
pasted_data_split
.
length
;
i
++
)
{
if
(
this
.
$parent
.
$children
[
index
+
i
])
{
let
content
=
pasted_data_split
[
i
];
let
child
=
this
.
$parent
.
$children
[
index
+
i
];
child
.
setContent
(
content
);
}
else
{
let
content
=
pasted_data_split
.
slice
(
i
-
1
).
join
(
'
\n
'
);
let
child
=
this
.
$parent
.
$children
[
index
+
1
];
child
.
setContent
(
content
);
for
(
let
i
=
0
;
i
<
pasted_data_split
.
length
;
i
++
)
{
let
content
=
pasted_data_split
[
i
];
let
child
=
this
.
$parent
.
$children
[
index
+
i
];
if
(
child
)
{
child
.
$el
.
textContent
=
this
.
cleanSource
(
content
);
}
}
this
.
$parent
.
toggleSave
();
}
e
.
preventDefault
();
},
getContentOrFake
()
{
return
this
.
line
.
currentTrans
.
content
;
},
getRegion
(){
getRegion
()
{
return
this
.
$parent
.
part
.
regions
.
findIndex
(
r
=>
r
.
pk
==
this
.
line
.
region
);
}
}
...
...
app/apps/core/static/js/edit/components/diplo_panel.js
View file @
c5773736
var
timer
;
var
DiploPanel
=
BasePanel
.
extend
({
data
()
{
return
{
editLine
:
null
,
updatedLines
:
[],
createdLines
:
[],
movedLines
:[],
...
...
@@ -10,30 +9,28 @@ var DiploPanel = BasePanel.extend({
components
:
{
'
diploline
'
:
diploLine
,
},
mounted
(){
Vue
.
nextTick
(
function
()
{
var
vm
=
this
;
var
el
=
document
.
getElementById
(
'
list
'
);
sortable
=
Sortable
.
create
(
el
,
{
group
:
'
shared
'
,
multiDrag
:
true
,
multiDragKey
:
'
CTRL
'
,
selectedClass
:
"
selected
"
,
animation
:
150
,
onEnd
:
function
(
/**Event*/
evt
)
{
vm
.
onDragginEnd
(
evt
);
}
});
}.
bind
(
this
));
},
/*
mounted(){
*
Vue.nextTick(function() {
*
var vm = this ;
*
var el = document.getElementById('list');
*
sortable = Sortable.create(el, {
*
group: 'shared',
*
multiDrag: true,
*
multiDragKey : 'CTRL',
*
selectedClass: "selected",
*
animation: 150,
*
onEnd: function(evt) {
*
vm.onDragginEnd(evt);
*
}
*
});
*
}.bind(this));
* }, */
methods
:{
toggleSave
(){
clearTimeout
(
timer
);
timer
=
setTimeout
(
function
(){
this
.
save
();
}.
bind
(
this
),
2000
);
startEdit
(
ev
){
this
.
$parent
.
blockShortcuts
=
true
;
},
stopEdit
(
ev
)
{
this
.
$parent
.
blockShortcuts
=
false
;
},
onDragginEnd
(
ev
)
{
/*
...
...
@@ -57,99 +54,113 @@ var DiploPanel = BasePanel.extend({
this
.
moveLines
();
},
moveLines
(){
moveLines
()
{
if
(
this
.
movedLines
.
length
!=
0
){
this
.
$parent
.
$emit
(
'
line:move
'
,
this
.
movedLines
,
function
()
{
this
.
$parent
.
$emit
(
'
line:move
'
,
this
.
movedLines
,
function
()
{
this
.
movedLines
=
[];
}.
bind
(
this
));
}
},
save
(){
save
()
{
/*
if some lines are modified add them to updatedlines, new lines add them to createdLines then save
*/
if some lines are modified add them to updatedlines,
new lines add them to createdLines then save
*/
this
.
addToList
();
this
.
bulkUpdate
();
this
.
bulkCreate
();
},
updateEditLine
(
position
){
if
(
position
<
this
.
part
.
lines
.
length
&&
position
>=
0
)
{
this
.
setEditLine
(
this
.
part
.
lines
[
position
]);
let
nextLine
=
this
.
$children
[
position
];
nextLine
.
startEdit
();
this
.
setCursorPosition
(
"
[id='
"
+
this
.
editLine
.
pk
+
"
']
"
);
}
},
setHeight
()
{
this
.
$el
.
querySelector
(
'
.content-container
'
).
style
.
maxHeight
=
Math
.
round
(
this
.
part
.
image
.
size
[
1
]
*
this
.
ratio
)
+
'
px
'
;
},
onKeyDown
(
ev
){
let
index
=
this
.
part
.
lines
.
indexOf
(
this
.
editLine
);
//disable shortcuts
this
.
$parent
.
blockShortcuts
=
true
;
// click delete button if you are at the beggining of the line
// if(ev.keyCode==8 && this.getCursorPosition()==0){
// ev.preventDefault();
//
// this.updateEditLine(index -1);
// let idx = this.part.lines.indexOf(this.editLine);
// let child = this.$children[idx];
// let nextLine = this.part.lines[idx+1];
// let content = child.line.currentTrans.content + nextLine.currentTrans.content;
// child.setContent(content);
// this.addToUpdatedLines(child.line.currentTrans);
//
// for(let i=idx +1; i < this.part.lines.length; i++) {
//
// let child = this.$children[i];
// let nextLine = this.part.lines[i+1];
// let currentLine = child.line;
// if(nextLine){
//
// if(currentLine.currentTrans.pk){
// child.setContent(nextLine.currentTrans.content);
// this.addToUpdatedLines(currentLine.currentTrans);
//
// }
// else{
// child.setContent(nextLine.currentTrans.content);
// this.createdLines.push(currentLine.currentTrans);
// }
// }
// else {
// child.setContent("");
// this.addToUpdatedLines(child.line.currentTrans);
// }
// this.setCursorPosition("[id='"+ this.editLine.pk+ "']");
//
//
// }
// this.updateEditLine( -1);
//
//
// }
//click on enter button
if
(
ev
.
keyCode
==
13
){
ev
.
preventDefault
();
let
idx
=
this
.
part
.
lines
.
indexOf
(
this
.
editLine
);
if
(
idx
<
this
.
part
.
lines
.
length
-
1
){
this
.
updateEditLine
(
idx
+
1
);
}
focusNextLine
(
sel
,
line
)
{
if
(
line
.
nextSibling
)
{
let
range
=
document
.
createRange
();
range
.
setStart
(
line
.
nextSibling
,
0
);
range
.
collapse
(
false
);
sel
.
removeAllRanges
();
sel
.
addRange
(
range
);
}
if
(
ev
.
keyCode
==
8
){
this
.
toggleSave
();
},
focusPreviousLine
(
sel
,
line
)
{
if
(
line
.
previousSibling
)
{
let
range
=
document
.
createRange
();
range
.
setStart
(
line
.
previousSibling
,
0
);
sel
.
removeAllRanges
();
sel
.
addRange
(
range
);
}
},
setEditLine
(
l
)
{
this
.
editLine
=
l
;
onKeyPress
(
ev
)
{
// arrows needed to avoid skipping empty lines
if
(
ev
.
key
==
'
ArrowDown
'
&&
!
ev
.
shiftKey
)
{
let
sel
=
window
.
getSelection
();
let
div
=
sel
.
anchorNode
.
nodeType
==
Node
.
TEXT_NODE
?
sel
.
anchorNode
.
parentElement
:
sel
.
anchorNode
;
this
.
focusNextLine
(
sel
,
div
);
ev
.
preventDefault
();
}
else
if
(
ev
.
key
==
'
ArrowUp
'
&&
!
ev
.
shiftKey
)
{
let
sel
=
window
.
getSelection
();
let
div
=
sel
.
anchorNode
.
nodeType
==
Node
.
TEXT_NODE
?
sel
.
anchorNode
.
parentElement
:
sel
.
anchorNode
;
this
.
focusPreviousLine
(
sel
,
div
);
ev
.
preventDefault
();
}
else
if
(
ev
.
key
==
'
Enter
'
)
{
if
(
window
.
getSelection
)
{
const
selection
=
window
.
getSelection
();
let
range
=
selection
.
getRangeAt
(
0
);
// push text down
let
lineNode
=
range
.
endContainer
.
nodeType
==
Node
.
TEXT_NODE
?
range
.
endContainer
.
parentNode
:
range
.
endContainer
;
let
lines
=
lineNode
.
parentNode
.
childNodes
;
let
curIndex
=
Array
.
prototype
.
indexOf
.
call
(
lines
,
lineNode
);
let
nextText
=
lineNode
.
textContent
.
slice
(
range
.
endOffset
).
trim
();
this
.
$children
[
curIndex
].
$el
.
textContent
=
lineNode
.
textContent
.
slice
(
0
,
range
.
startOffset
).
trim
();
for
(
let
i
=
curIndex
+
1
;
i
<
lines
.
length
-
1
;
i
++
)
{
let
text
=
nextText
;
nextText
=
lines
[
i
].
textContent
;
this
.
$children
[
i
].
$el
.
textContent
=
text
;
}
// focus next line
this
.
focusNextLine
(
selection
,
lineNode
);
}
ev
.
preventDefault
();
}
else
if
(
ev
.
key
==
'
Backspace
'
)
{
const
selection
=
window
.
getSelection
();
let
range
=
selection
.
getRangeAt
(
0
);
if
(
range
.
startContainer
!=
range
.
endContainer
)
{
// override default behavior to avoid deleting entire lines
let
startLine
=
range
.
startContainer
.
nodeType
==
Node
.
TEXT_NODE
?
range
.
startContainer
.
parentNode
:
range
.
startContainer
;
let
endLine
=
range
.
endContainer
.
nodeType
==
Node
.
TEXT_NODE
?
range
.
endContainer
.
parentNode
:
range
.
endContainer
;
let
inRange
=
false
;
for
(
let
i
=
0
;
i
<
this
.
$children
.
length
;
i
++
)
{
let
line
=
this
.
$children
[
i
].
$el
;
if
(
line
==
startLine
)
{
line
.
textContent
=
line
.
textContent
.
slice
(
0
,
range
.
startOffset
);
inRange
=
true
;
}
else
if
(
line
==
endLine
)
{
line
.
textContent
=
line
.
textContent
.
slice
(
range
.
endOffset
);
break
;
}
else
if
(
inRange
)
{
line
.
textContent
=
''
;
}
}
ev
.
preventDefault
();
}
else
if
(
range
.
startOffset
==
0
&&
range
.
endOffset
==
0
)
{
// push text up
let
lineNode
=
range
.
startContainer
.
nodeType
==
Node
.
TEXT_NODE
?
range
.
startContainer
.
parentNode
:
range
.
startContainer
;
let
lines
=
lineNode
.
parentNode
.
childNodes
;
let
curIndex
=
Array
.
prototype
.
indexOf
.
call
(
lines
,
lineNode
);
if
(
curIndex
>
0
)
{
// append content to previous line
this
.
$children
[
curIndex
-
1
].
$el
.
textContent
+=
this
.
$children
[
curIndex
].
$el
.
textContent
;
for
(
let
i
=
curIndex
;
i
<
lines
.
length
-
1
;
i
++
)
{
this
.
$children
[
i
].
$el
.
textContent
=
this
.
$children
[
i
+
1
].
$el
.
textContent
;
}
this
.
$children
[
lines
.
length
-
1
].
$el
.
textContent
=
''
;
}
ev
.
preventDefault
();
}
}
},
bulkUpdate
(){
bulkUpdate
()
{
if
(
this
.
updatedLines
.
length
){
this
.
$parent
.
$emit
(
'
bulk_update:transcriptions
'
,
...
...
@@ -159,7 +170,7 @@ var DiploPanel = BasePanel.extend({
}.
bind
(
this
));
}
},
bulkCreate
(){
bulkCreate
()
{
if
(
this
.
createdLines
.
length
){
this
.
$parent
.
$emit
(
'
bulk_create:transcriptions
'
,
...
...
@@ -169,22 +180,24 @@ var DiploPanel = BasePanel.extend({
}.
bind
(
this
));
}
},
addToList
(){
addToList
()
{
/*
parse all lines if the content changed, add it to updated lines
*/
for
(
let
i
=
0
;
i
<
this
.
$children
.
length
;
i
++
)
{
*/
for
(
let
i
=
0
;
i
<
this
.
$children
.
length
;
i
++
)
{
let
currentLine
=
this
.
$children
[
i
];
if
(
currentLine
.
line
.
currentTrans
.
content
!=
currentLine
.
$refs
.
content
[
0
].
textContent
){
currentLine
.
line
.
currentTrans
.
content
=
currentLine
.
$refs
.
content
[
0
].
textContent
;
if
(
currentLine
.
line
.
currentTrans
.
pk
)
if
(
currentLine
.
line
.
currentTrans
.
content
!=
currentLine
.
$el
.
textContent
){
// TODO: sanitize text content?!
currentLine
.
line
.
currentTrans
.
content
=
currentLine
.
$el
.
textContent
;
if
(
currentLine
.
line
.
currentTrans
.
pk
)
{
this
.
addToUpdatedLines
(
currentLine
.
line
.
currentTrans
);
else
}
else
{
this
.
createdLines
.
push
(
currentLine
.
line
.
currentTrans
);
}
}
}
},
addToUpdatedLines
(
lt
){
addToUpdatedLines
(
lt
)
{
/*
if line already exists in updatedLines update its content on the list
*/
...
...
@@ -202,47 +215,6 @@ var DiploPanel = BasePanel.extend({
*/
this
.
setHeight
();
},
getCursorPosition
()
{
return
window
.
getSelection
().
getRangeAt
(
0
).
startOffset
;
},
setCursorPosition
(
id
)
{
const
textNode
=
document
.
querySelector
(
id
);
let
sel
=
window
.
getSelection
();
const
range
=
document
.
createRange
();
range
.
setStart
(
textNode
,
textNode
.
length
);
// Start at first character
range
.
setEnd
(
textNode
,
textNode
.
length
);
sel
.
removeAllRanges
();
sel
.
addRange
(
range
);
},
//return --> insert carriage return here and push rest of text of this line into the next line.
// If there is text in the next line push that line one down etc. If there is no text in the next line dont push further
carriage
(
ev
,
idx
){
ev
.
preventDefault
();
if
(
window
.
getSelection
)
{
let
selection
=
window
.
getSelection
(),
range
=
selection
.
getRangeAt
(
0
),
br
=
document
.
createElement
(
"
br
"
),
textNode
=
document
.
createTextNode
(
$
(
"
<div></div>
"
).
text
());
//Passing " " directly will not end up being shown correctly
range
.
deleteContents
();
range
.
insertNode
(
br
);
range
.
collapse
(
false
);
range
.
insertNode
(
textNode
);
range
.
selectNodeContents
(
textNode
);
selection
.
removeAllRanges
();
selection
.
addRange
(
range
);
let
child
=
this
.
$children
[
idx
+
1
];
let
target
=
selection
.
anchorNode
.
nextSibling
.
parentNode
;
let
html
=
target
.
innerHTML
;
let
after_break
=
html
.
substring
(
html
.
indexOf
(
'
br
'
)
+
3
);
child
.
setContent
(
after_break
+
child
.
line
.
currentTrans
.
content
);
target
.
innerHTML
=
html
.
substring
(
0
,
html
.
indexOf
(
'
<br
'
))
+
"
</div>
"
;
this
.
updateEditLine
(
idx
+
1
);
return
false
;
}
}
},
});
app/apps/core/static/js/edit/main.js
View file @
c5773736
...
...
@@ -171,7 +171,9 @@ var partVM = new Vue({
$alertsContainer
.
on
(
'
part:mask
'
,
function
(
ev
,
data
)
{
data
.
lines
.
forEach
(
function
(
lineData
)
{
let
line
=
this
.
part
.
lines
.
find
(
l
=>
l
.
pk
==
lineData
.
pk
);
line
.
mask
=
lineData
.
mask
;
if
(
line
)
{
// might have been deleted in the meantime
line
.
mask
=
lineData
.
mask
;
}
}.
bind
(
this
));
}.
bind
(
this
));
},
...
...
app/escriptorium/static/css/escriptorium.css
View file @
c5773736
...
...
@@ -590,24 +590,35 @@ i.panel-icon {
padding
:
10px
;
}
.table-row
{
/*border-right: 1px solid lightgrey;*/
padding-left
:
2%
;
padding-right
:
2%
;
#diplo-panel
.content-container
{
overflow-y
:
auto
;
}
#diplomatic-lines
{
counter-reset
:
line
;
}
#diplomatic-lines
div
.line-content
{
display
:
block
;
line-height
:
1.7rem
;
margin-bottom
:
0px
;
overflow-wrap
:
break-word
;
margin-left
:
50px
;
}
.line-order
,
.line-region
{
#diplomatic-lines
.line-content
:before
{
user-select
:
none
;
width
:
15%
;
text-align
:
center
;
border-right
:
1px
solid
lightgrey
;
counter-increment
:
line
;
content
:
counter
(
line
);
display
:
inline-block
;
border-right
:
1px
solid
#ddd
;
padding
:
0
.5em
;
margin-right
:
.5em
;
width
:
50px
;
margin-left
:
-50px
;
color
:
#888
;
}
.line-content
{
margin-bottom
:
0px
;
overflow-wrap
:
break-word
;
flex-basis
:
85%
;
}
.line-selected
{
background-color
:
#33A2FF
;
border
:
solid
#33A2FF
1px
;
...
...
app/escriptorium/templates/core/document_part_edit.html
View file @
c5773736
...
...
@@ -541,46 +541,41 @@
</keep-alive>
<keep-alive>
<DiploPanel
v-if=
"show.diplomatic"
v-bind:part=
"part"
ref=
"diploPanel"
inline-template
>
<div
class=
"col panel"
>
<div
class=
"tools"
>
<i
title=
"{% trans 'Transcription Panel' %}"
class=
"panel-icon fas fa-language"
></i>
</div>
<div
v-if=
"part"
id=
"diplomatic-lines"
contenteditable
@
keyup=
"toggleSave"
class=
"content-container {{ document.read_direction }}"
>
<div
id=
"list"
class=
"list-group"
>
<DiploPanel
id=
"diplo-panel"
v-bind:part=
"part"
v-if=
"show.diplomatic && part.loaded"
ref=
"diploPanel"
inline-template
>
<div
class=
"col panel"
>
<div
class=
"tools"
>
<i
title=
"{% trans 'Transcription Panel' %}"
class=
"panel-icon fas fa-language"
></i>
</div>
<div
class=
"content-container {{ document.read_direction }}"
>
<div
id=
"diplomatic-lines"
contenteditable=
"true"
@
keydown=
"onKeyPress"
@
focusin=
"startEdit"
@
focusout=
"stopEdit"
@
blur=
"save"
>
<diploline
v-for=
"line in part.lines"
v-bind:line=
"line"
v-bind:ratio=
"ratio"
v-bind:key=
"line.pk"
v-bind:key=
"
'DL' +
line.pk"
inline-template
>
<div
class=
"d-flex flex-row"
>
{#
<div
class =
"table-row line-region "
class=
"w-10"
contenteditable=
"false"
>
${showregion}
</div>
#}
<div
class =
"table-row line-order w-10"
contenteditable=
"false"
>
${line.order + 1}
</div>
<p
v-bind:id=
"line.pk"
v-if=
"line.currentTrans"
@
mouseup=
"startEdit"
@
focusout=
"stopEdit"
@
mouseover=
"showOverlay"
@
mouseleave=
"hideOverlay"
@
select=
"stopEdit"
{
#
@
paste=
"onPaste"
#
}
class=
"table-row line-content"
ref=
"content"
v-html=
"line.currentTrans.content"
></p>
</div>
<div
class=
"line-content"
v-if=
"line.currentTrans"
@
mouseover=
"showOverlay"
@
mouseleave=
"hideOverlay"
@
paste=
"onPaste"
ref=
"content"
v-html=
"line.currentTrans.content"
>
</div>
</diploline>
</div>
</div>
</div>
</DiploPanel>
</keep-alive>
</div>
</DiploPanel>
</keep-alive>
<div
class=
"col-sides"
>
{% if document.read_direction == 'rtl' %}
...
...
Write
Preview
Supports
Markdown
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