Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
GuiΩ
ActivitesMentales_Django
Commits
04ded918
Commit
04ded918
authored
May 24, 2022
by
GuiΩ
Browse files
feat(QuestionList): multiple questions can be move together
parent
28c86411
Changes
4
Hide whitespace changes
Inline
Side-by-side
src/components/Home.vue
View file @
04ded918
...
...
@@ -38,7 +38,7 @@
#question-selector
theme-tree#theme-selector(
:selection_ids="selection_theme_id"
@selection-changed="setCurrentTheme
(
$event[0])")/
@selection-changed="
$store.dispatch('themes/
setCurrentTheme
',
$event[0])")/
#question-column
button(data-testid="newQuestion" @click="$refs.questionEditor.edit()") Nouvelle question
#question-list-container
...
...
src/components/QuestionList.vue
View file @
04ded918
...
...
@@ -18,10 +18,10 @@ Events:
drop-context-menu(ref="rightContextMenu")
div(
v-if="editable(questionSel)"
@click="$emit('question-edit', {question_id: questionSel.id}); $refs.rightContextMenu.close()"
v-if="editable(questionSel
[0]
)"
@click="$emit('question-edit', {question_id: questionSel
[0]
.id}); $refs.rightContextMenu.close()"
) Modifier
div(@click="$emit('question-duplicate', {question_id: questionSel.id}); $refs.rightContextMenu.close()") Dupliquer
div(@click="$emit('question-duplicate', {question_id: questionSel
[0]
.id}); $refs.rightContextMenu.close()") Dupliquer
div(@click="$refs.rightContextMenu.close()") Annuler
div
...
...
@@ -31,12 +31,15 @@ Events:
ref="questions"
:index="index"
:question_id="question_id"
@hideDrop="hideDrop"
@showDrop="showDrop"
@drop-context-menu="dropContextMenu"
:selected="questionSel.indexOf(question_id)>=0"
@click="onQuestionClick($event)"
@dblclick="onQuestionDblClick($event)"
@dragStart="onDragStart($event)"
@hideDrop="onHideDrop"
@showDrop="onShowDrop"
@drop-context-menu="onDropContextMenu"
@question-drop="$emit('question-drop', $event)"
@question-edit="$emit('question-edit', $event)"
@show-question-tooltip="$emit('show-question-tooltip', $event)")/
@question-edit="$emit('question-edit', $event)")/
</
template
>
<
script
>
...
...
@@ -59,7 +62,7 @@ export default {
scores
:
{},
dropEvent
:
null
,
dropIndex
:
0
,
questionSel
:
null
,
questionSel
:
[]
,
}
},
computed
:
{
...
...
@@ -69,54 +72,118 @@ export default {
question_ids
()
{
// list des questions à afficher
return
this
.
$store
.
getters
[
"
questions/currQuestionsIds
"
]
},
selLength
()
{
return
this
.
questionSel
.
length
;
}
},
methods
:
{
isSelected
(
question_id
)
{
return
question_id
in
this
.
questionSel
;
},
editable
(
question
)
{
return
(
question
&&
question
.
editable
)
||
permissions
.
includes
(
'
Validateur
'
)
},
dropContextMenu
(
event
)
{
/**
* init dataTransfer for a drag
*/
onDragStart
(
event
)
{
let
question
=
event
.
question
if
(
this
.
questionSel
.
indexOf
(
question
.
id
)
<
0
)
this
.
questionSel
=
[
question
.
id
];
if
(
question
.
avalider
||
permissions
.
includes
(
'
Validateur
'
))
event
.
dataTransfer
.
effectAllowed
=
'
copyMove
'
;
else
if
(
!
question
.
avalider
)
event
.
dataTransfer
.
effectAllowed
=
'
move
'
;
else
event
.
dataTransfer
.
effectAllowed
=
'
copy
'
;
event
.
dataTransfer
.
setData
(
'
question_id
'
,
question
.
id
);
event
.
dataTransfer
.
setData
(
'
index
'
,
event
.
index
);
},
onDropContextMenu
(
event
)
{
this
.
dropEvent
=
event
.
dropEvent
;
this
.
dropIndex
=
event
.
dropIndex
;
this
.
$refs
.
dropContextMenu
.
show
(
event
.
dropEvent
)
},
s
howDrop
()
{
onS
howDrop
()
{
this
.
$el
.
style
.
background
=
'
#f99
'
;
},
h
ideDrop
()
{
onH
ideDrop
()
{
this
.
$el
.
style
.
background
=
''
;
},
onQuestionClick
(
event
)
{
if
(
event
.
shiftKey
&&
permissions
.
includes
(
'
Validateur
'
))
{
if
(
this
.
selLength
)
{
let
first
=
this
.
$store
.
getters
[
'
questions/indexInTheme
'
](
this
.
questionSel
[
this
.
questionSel
.
length
-
1
],
this
.
theme_id
);
let
last
=
this
.
$store
.
getters
[
'
questions/indexInTheme
'
](
event
.
question_id
,
this
.
theme_id
);
let
inc
=
1
;
if
(
last
<
first
)
inc
=
-
1
;
for
(
let
i
=
first
+
inc
;
i
*
inc
<=
last
*
inc
;
i
+=
inc
)
{
let
question_id
=
this
.
$refs
.
questions
[
i
].
question
.
id
;
if
(
this
.
questionSel
.
indexOf
(
question_id
)
<
0
)
this
.
questionSel
.
push
(
question_id
);
}
}
}
else
if
(
event
.
ctrlKey
&&
permissions
.
includes
(
'
Validateur
'
))
{
let
index
=
this
.
questionSel
.
indexOf
(
event
.
question_id
);
if
(
index
>=
0
)
{
this
.
questionSel
.
splice
(
index
,
1
);
}
else
{
this
.
questionSel
.
push
(
event
.
question_id
);
}
}
else
this
.
questionSel
=
[
event
.
question_id
];
if
((
!
event
.
ctrlKey
&&
!
event
.
shiftKey
)
||
!
permissions
.
includes
(
'
Validateur
'
)
)
this
.
$emit
(
'
show-question-tooltip
'
,
event
)
},
onQuestionDblClick
(
event
)
{
this
.
questionSel
=
[
event
.
question_id
];
},
changePosition
()
{
const
indexSource
=
this
.
dropEvent
.
dataTransfer
.
getData
(
'
index
'
);
const
positionDest
=
this
.
$refs
.
questions
[
this
.
dropIndex
].
question
.
getPositionInTheme
(
this
.
theme_id
);
this
.
$el
.
style
.
cursor
=
'
wait
'
let
newPosition
;
let
newPosition
=
[]
// on unordered question =>
after la
st unodered
// on unordered question =>
beforse fir
st unodered
if
(
positionDest
===
null
)
{
const
firstOrdered
=
this
.
findFirstOrdered
();
if
(
firstOrdered
)
{
newPosition
=
firstOrdered
.
question
.
getPositionInTheme
(
this
.
theme_id
)
-
128
;
for
(
let
i
=
this
.
selLength
-
1
;
i
>=
0
;
i
--
)
{
newPosition
[
i
]
=
firstOrdered
.
question
.
getPositionInTheme
(
this
.
theme_id
)
-
(
i
+
1
)
*
128
;
}
}
else
{
newPosition
=
0
for
(
let
i
=
0
;
i
<
this
.
selLength
;
i
++
)
{
newPosition
[
i
]
=
i
*
128
;
}
}
}
else
if
(
this
.
dropIndex
<
indexSource
)
{
// before the actual position
if
(
this
.
dropIndex
===
0
||
!
this
.
$refs
.
questions
[
this
.
dropIndex
-
1
].
question
.
getPositionInTheme
(
this
.
theme_id
))
// before the first ordored question
newPosition
=
this
.
$refs
.
questions
[
this
.
dropIndex
].
question
.
getPositionInTheme
(
this
.
theme_id
)
-
128
;
else
newPosition
=
(
this
.
$refs
.
questions
[
this
.
dropIndex
].
question
.
getPositionInTheme
(
this
.
theme_id
)
+
this
.
$store
.
getters
[
'
questions/question
'
](
this
.
question_ids
[
this
.
dropIndex
-
1
])
.
getPositionInTheme
(
this
.
theme_id
))
/
2
;
for
(
let
i
=
this
.
selLength
-
1
;
i
>=
0
;
i
--
)
{
newPosition
[
i
]
=
this
.
$refs
.
questions
[
this
.
dropIndex
].
question
.
getPositionInTheme
(
this
.
theme_id
)
-
(
i
+
1
)
*
128
;
}
else
{
let
gap
=
this
.
$refs
.
questions
[
this
.
dropIndex
].
question
.
getPositionInTheme
(
this
.
theme_id
)
-
this
.
$store
.
getters
[
'
questions/question
'
](
this
.
question_ids
[
this
.
dropIndex
-
1
]).
getPositionInTheme
(
this
.
theme_id
);
for
(
let
i
=
0
;
i
<
this
.
selLength
;
i
++
)
{
newPosition
[
i
]
=
this
.
$refs
.
questions
[
this
.
dropIndex
-
1
].
question
.
getPositionInTheme
(
this
.
theme_id
)
+
(
i
+
1
)
*
gap
/
(
this
.
selLength
+
1
)
}
}
}
else
if
(
this
.
dropIndex
>
indexSource
)
{
// after the actual position
if
(
this
.
dropIndex
===
this
.
question_ids
.
length
-
1
)
{
newPosition
=
this
.
$refs
.
questions
[
this
.
dropIndex
].
question
.
getPositionInTheme
(
this
.
theme_id
)
+
128
// after the last question
for
(
let
i
=
0
;
i
<
this
.
selLength
;
i
++
)
{
newPosition
[
i
]
=
this
.
$refs
.
questions
[
this
.
dropIndex
].
question
.
getPositionInTheme
(
this
.
theme_id
)
+
128
*
(
i
+
1
)
// after the last question
}
}
else
{
console
.
log
(
this
.
$refs
.
questions
[
this
.
dropIndex
].
question
.
id
,
this
.
$store
.
getters
[
'
questions/question
'
](
this
.
question_ids
[
this
.
dropIndex
+
1
]).
getPositionInTheme
(
this
.
theme_id
))
newPosition
=
(
this
.
$refs
.
questions
[
this
.
dropIndex
].
question
.
getPositionInTheme
(
this
.
theme_id
)
+
this
.
$store
.
getters
[
'
questions/question
'
](
this
.
question_ids
[
this
.
dropIndex
+
1
]).
getPositionInTheme
(
this
.
theme_id
))
/
2
let
gap
=
this
.
$store
.
getters
[
'
questions/question
'
](
this
.
question_ids
[
this
.
dropIndex
+
1
]).
getPositionInTheme
(
this
.
theme_id
)
-
this
.
$refs
.
questions
[
this
.
dropIndex
].
question
.
getPositionInTheme
(
this
.
theme_id
);
for
(
let
i
=
0
;
i
<
this
.
selLength
;
i
++
)
{
newPosition
[
i
]
=
this
.
$refs
.
questions
[
this
.
dropIndex
].
question
.
getPositionInTheme
(
this
.
theme_id
)
+
(
i
+
1
)
*
gap
/
(
this
.
selLength
+
1
)
}
}
}
else
{
// on itself (probably a bug)
consol
.
warn
(
'
drop on itself
'
)
...
...
@@ -124,12 +191,24 @@ export default {
this
.
endDrop
()
return
;
}
this
.
$store
.
dispatch
(
'
questions/changeQuestionPosition
'
,
{
question_id
:
this
.
dropEvent
.
dataTransfer
.
getData
(
'
question_id
'
),
newValues
:
{
theme_id
:
this
.
theme_id
,
position
:
newPosition
}
})
.
then
(()
=>
this
.
$el
.
style
.
cursor
=
''
)
.
catch
(()
=>
this
.
$el
.
style
.
cursor
=
''
)
this
.
questionSel
.
sort
((
a
,
b
)
=>
{
let
posa
=
this
.
$store
.
getters
[
'
questions/question
'
](
a
).
getPositionInTheme
(
this
.
theme_id
);
let
posb
=
this
.
$store
.
getters
[
'
questions/question
'
](
b
).
getPositionInTheme
(
this
.
theme_id
);
if
(
posa
<
posb
)
return
-
1
;
else
if
(
posb
<
posa
)
return
1
;
else
return
0
;
});
let
promises
=
[]
for
(
let
i
=
0
;
i
<
this
.
selLength
;
i
++
)
{
promises
.
push
(
this
.
$store
.
dispatch
(
'
questions/changeQuestionPosition
'
,
{
question_id
:
this
.
questionSel
[
i
],
newValues
:
{
theme_id
:
this
.
theme_id
,
position
:
newPosition
[
i
]}
}));
}
Promise
.
all
(
promises
).
then
(()
=>
this
.
$el
.
style
.
cursor
=
''
);
this
.
endDrop
()
},
endDrop
()
{
...
...
@@ -169,7 +248,7 @@ export default {
return
this
.
$refs
.
questions
[
index
]
},
showContextMenu
(
event
,
question
)
{
this
.
questionSel
=
question
;
this
.
questionSel
=
[
question
.
id
]
;
this
.
$refs
.
rightContextMenu
.
show
(
event
);
}
},
...
...
src/components/QuestionListNode.vue
View file @
04ded918
<
template
lang=
"pug"
>
.question(:data-testid="'question_' + question_id")
.question(:data-testid="'question_' + question_id"
:class="{selected:selected}"
)
score(
v-for="(score, index) in scores"
:key="index"
...
...
@@ -14,8 +14,8 @@
:position="position"
:src="('../static/thumbs/' + question.thumb_name)"
draggable
@click="
c
lick($event, question_id)"
@dblclick="
questionEdit
(question)"
@click="
onC
lick($event, question_id)"
@dblclick="
onDblClick
(question
_id
)"
@dragenter.prevent="onDragOver($event, index)"
@dragover.prevent
@dragleave.prevent="onDragLeave($event, index)"
...
...
@@ -36,6 +36,7 @@ export default {
props
:
{
question_id
:
Number
,
index
:
Number
,
selected
:
Boolean
},
computed
:
{
question
()
{
...
...
@@ -54,35 +55,33 @@ export default {
data
()
{
return
{
nClick
:
0
,
clickTimeout
:
3
00
,
clickTimeout
:
2
00
,
clickTimer
:
null
,
}
},
methods
:
{
c
lick
(
event
,
question_id
)
{
onC
lick
(
event
,
question_id
)
{
this
.
nClick
++
if
(
this
.
nClick
===
1
)
{
this
.
clickTimer
=
setTimeout
(
()
=>
{
this
.
$emit
(
'
show-question-tooltip
'
,
{
event
:
event
,
question_id
:
question_id
})
this
.
clickTimer
=
setTimeout
(()
=>
{
event
.
question_id
=
question_id
this
.
$emit
(
'
click
'
,
event
)
this
.
nClick
=
0
},
this
.
clickTimeout
);
}
else
{
clearTimeout
(
this
.
clickTimer
);
this
.
nClick
=
0
;
}
},
onDblClick
(
event
,
question_id
){
clearTimeout
(
this
.
clickTimer
);
this
.
nClick
=
0
;
this
.
$emit
(
'
dblclick
'
,
event
)
},
/**
* init dataTransfer for a drag
*/
dragStart
(
event
,
index
,
question
)
{
if
(
question
.
avalider
||
permissions
.
includes
(
'
Validateur
'
))
event
.
dataTransfer
.
effectAllowed
=
'
copyMove
'
;
else
if
(
!
question
.
avalider
)
event
.
dataTransfer
.
effectAllowed
=
'
move
'
;
else
event
.
dataTransfer
.
effectAllowed
=
'
copy
'
;
event
.
dataTransfer
.
setData
(
'
question_id
'
,
question
.
id
);
event
.
dataTransfer
.
setData
(
'
index
'
,
index
);
event
.
question
=
question
;
event
.
index
=
index
;
this
.
$emit
(
'
dragStart
'
,
event
);
},
onDragOver
(
dragEvent
,
indexDest
)
{
const
questionPoseeSource_id
=
dragEvent
.
dataTransfer
.
getData
(
'
questionPosee_id
'
)
...
...
@@ -154,6 +153,9 @@ export default {
}
},
questionEdit
(
question
)
{
clearTimeout
(
this
.
clickTimer
);
this
.
nClick
=
0
;
this
.
$emit
(
'
d
'
,
{
question_id
:
question
.
id
})
if
(
question
.
editable
||
permissions
.
includes
(
'
Validateur
'
))
this
.
$emit
(
'
question-edit
'
,
{
question_id
:
question
.
id
})
},
...
...
@@ -169,6 +171,9 @@ export default {
padding
:
0
;
margin
:
0
;
}
.question.selected
{
background-color
:
rgba
(
255
,
150
,
150
,
.8
);
}
img
.editable
{
background
:
rgba
(
100
,
100
,
100
,
.8
);
...
...
src/store/modules/questions.js
View file @
04ded918
...
...
@@ -39,6 +39,13 @@ const getters = {
questionSaveStatus
:
(
state
)
=>
{
return
state
.
questionSaveStatus
.
status
},
indexInTheme
:
(
state
,
getters
,
rootState
)
=>
(
question_id
,
theme_id
)
=>
{
for
(
let
i
=
0
;
i
<
rootState
.
themes
.
themes
[
theme_id
].
questions
.
length
;
i
++
)
{
if
(
rootState
.
themes
.
themes
[
theme_id
].
questions
[
i
]
===
question_id
)
return
i
;
}
return
-
1
;
}
}
// mutations
...
...
@@ -175,4 +182,4 @@ function getQuestionPositionInTheme(theme_id) {
}
}
return
null
;
}
\ No newline at end of file
}
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