151151
152152 <!-- Subquestions for this branch -->
153153 <div class =" branch__subquestions" >
154- <ul class =" branch__subquestions-list" >
155- <Draggable
156- v-model =" branches [branchIndex ].subQuestions "
157- :animation =" 200 "
158- tag="transition-group"
159- :componentData =" {
160- name: isDragging
161- ? ' no-external-transition-on-drag'
162- : ' question-list' ,
163- } "
164- handle=".question__drag-handle "
165- @change =" onQuestionOrderChange (branchIndex )"
166- @start =" isDragging = true "
167- @end =" isDragging = false " >
168- <li
169- v-for =" (
170- subQuestion, subIndex
171- ) in branch.subQuestions"
172- :key =" subQuestion.id"
173- class =" subquestion" >
174- <component
175- :is ="
176- getSubQuestionComponentName(
177- subQuestion.type,
178- )
179- "
180- v-bind =" subQuestion"
181- :canMoveDown ="
182- subIndex
183- < branch.subQuestions.length - 1
184- "
185- :canMoveUp =" subIndex > 0"
186- :formId =" formId"
187- :index =" subIndex + index + 1"
188- :maxStringLengths =" maxStringLengths"
189- :answerType ="
190- getSubQuestionAnswerTypeConfig(
191- subQuestion.type,
192- )
193- "
194- @update:text ="
195- updateSubQuestion(
196- branch.id,
197- subQuestion.id,
198- 'text',
199- $event,
200- )
201- "
202- @update:description ="
203- updateSubQuestion(
204- branch.id,
205- subQuestion.id,
206- 'description',
207- $event,
208- )
209- "
210- @update:isRequired ="
211- updateSubQuestion(
212- branch.id,
213- subQuestion.id,
214- 'isRequired',
215- $event,
216- )
217- "
218- @update:extraSettings ="
219- updateSubQuestion(
220- branch.id,
221- subQuestion.id,
222- 'extraSettings',
223- $event,
224- )
225- "
226- @update:options ="
227- updateSubQuestion(
228- branch.id,
229- subQuestion.id,
230- 'options',
231- $event,
232- )
233- "
234- @delete ="
235- deleteSubQuestion(
236- branch.id,
237- subQuestion.id,
238- )
239- "
240- @clone ="
241- cloneSubQuestion(
242- branch.id,
243- subQuestion.id,
244- )
245- "
246- @moveDown ="
247- onMoveDown(subIndex, branchIndex)
248- "
249- @moveUp ="
250- onMoveUp(subIndex, branchIndex)
251- " />
252- </li >
253- </Draggable >
254- </ul >
154+ <QuestionList
155+ v-model =" branches [branchIndex ].subQuestions "
156+ :getComponent =" getSubQuestionComponent "
157+ :getAnswerType =" getSubQuestionAnswerType "
158+ :maxStringLengths =" maxStringLengths "
159+ :baseIndex =" index "
160+ :animation =" 200 "
161+ :formId =" formId "
162+ :showInsert =" true "
163+ :insertMenuName =" t (' forms' , ' Insert subquestion' )"
164+ :answerTypesFilter =" subQuestionAnswerTypesFilter "
165+ :hasSubtypes =" hasSubtypes "
166+ :isLoadingQuestions =" isLoadingQuestions "
167+ @updateProperty ="
168+ (idx , prop , val ) =>
169+ updateSubQuestion (
170+ branch .id ,
171+ branches [branchIndex ].subQuestions [idx ]
172+ .id ,
173+ prop ,
174+ val ,
175+ )
176+ "
177+ @clone ="
178+ (question ) =>
179+ cloneSubQuestion (branch .id , question .id )
180+ "
181+ @delete ="
182+ (question ) =>
183+ deleteSubQuestion (branch .id , question .id )
184+ "
185+ @moveDown =" (idx ) => onMoveDown (idx , branchIndex ) "
186+ @moveUp =" (idx ) => onMoveUp (idx , branchIndex ) "
187+ @orderChange =" onQuestionOrderChange (branchIndex )"
188+ @dragStart =" isDragging = true "
189+ @dragEnd =" isDragging = false "
190+ @addQuestion ="
191+ (type , subtype , position ) =>
192+ addSubQuestion (branch .id , type , position )
193+ " />
255194
256195 <!-- Add subquestion button -->
257196 <NcActions :aria-label =" t (' forms' , ' Add subquestion' )" >
309248 </div >
310249 </div >
311250 </div >
251+ <slot name =" insert" />
312252 </Question >
313253</template >
314254
@@ -330,8 +270,8 @@ import IconTextLong from '@material-symbols/svg-400/outlined/subject.svg?raw'
330270import IconSwapVertical from ' @material-symbols/svg-400/outlined/swap_vert.svg?raw'
331271import axios from ' @nextcloud/axios'
332272import { showError } from ' @nextcloud/dialogs'
273+ import { emit } from ' @nextcloud/event-bus'
333274import { generateOcsUrl } from ' @nextcloud/router'
334- import { VueDraggable as Draggable } from ' vue-draggable-plus'
335275import NcActionButton from ' @nextcloud/vue/components/NcActionButton'
336276import NcActions from ' @nextcloud/vue/components/NcActions'
337277import NcButton from ' @nextcloud/vue/components/NcButton'
@@ -344,6 +284,7 @@ import QuestionDate from './QuestionDate.vue'
344284import QuestionDropdown from ' ./QuestionDropdown.vue'
345285import QuestionFile from ' ./QuestionFile.vue'
346286import QuestionLinearScale from ' ./QuestionLinearScale.vue'
287+ import QuestionList from ' ./QuestionList.vue'
347288import QuestionLong from ' ./QuestionLong.vue'
348289import QuestionMultiple from ' ./QuestionMultiple.vue'
349290import QuestionRanking from ' ./QuestionRanking.vue'
@@ -372,7 +313,6 @@ export default {
372313
373314 components: {
374315 BranchConditionEditor,
375- Draggable,
376316 NcActionButton,
377317 NcActions,
378318 NcButton,
@@ -383,6 +323,7 @@ export default {
383323 QuestionDropdown,
384324 QuestionFile,
385325 QuestionLinearScale,
326+ QuestionList,
386327 QuestionLong,
387328 QuestionMultiple,
388329 QuestionShort,
@@ -413,6 +354,7 @@ export default {
413354 data () {
414355 return {
415356 isDragging: false ,
357+ isLoadingQuestions: false ,
416358 triggerValues: [],
417359 subQuestionValues: {},
418360 }
@@ -560,6 +502,46 @@ export default {
560502 return this .extraSettings ? .branches || []
561503 },
562504
505+ /**
506+ * Get component reference for subquestion (used with :is in QuestionList)
507+ * Returns the actual component object, not a string name,
508+ * so it works in QuestionList's scope.
509+ */
510+ getSubQuestionComponent () {
511+ return (question ) => QUESTION_COMPONENTS [question .type ]
512+ },
513+
514+ /**
515+ * Get answer type config for subquestion (used with :answerType in QuestionList)
516+ * Takes a question object and returns the answer type config.
517+ */
518+ getSubQuestionAnswerType () {
519+ return (question ) => this .buildAnswerTypeConfig (question .type )
520+ },
521+
522+ /**
523+ * Build answerTypes filter for subquestion insert menu
524+ * Filters out 'conditional' to prevent recursion
525+ */
526+ subQuestionAnswerTypesFilter () {
527+ const filter = {}
528+ for (const sqType of this .subQuestionTypesList ) {
529+ filter[sqType .type ] = {
530+ icon: sqType .icon ,
531+ label: sqType .label ,
532+ }
533+ }
534+ return filter
535+ },
536+
537+ /**
538+ * Check if an answer type has subtypes
539+ */
540+ hasSubtypes () {
541+ return (answer ) =>
542+ answer && answer .subtypes && Object .keys (answer .subtypes ).length > 0
543+ },
544+
563545 activeBranches () {
564546 if (! this .triggerValues || this .triggerValues .length === 0 ) {
565547 return null
@@ -821,7 +803,7 @@ export default {
821803 return t (' forms' , ' Branch {number}' , { number: index + 1 })
822804 },
823805
824- async addSubQuestion (branchId , type ) {
806+ async addSubQuestion (branchId , type , position = null ) {
825807 const branch = this .branches .find ((b ) => b .id === branchId)
826808 if (! branch) return
827809
@@ -840,10 +822,16 @@ export default {
840822 const newQuestion = OcsResponse2Data (response)
841823
842824 const branchIndex = this .branches .findIndex ((b ) => b .id === branchId)
825+ const newSubQuestions = [... (branch .subQuestions || [])]
826+ if (position !== null ) {
827+ newSubQuestions .splice (position, 0 , newQuestion)
828+ } else {
829+ newSubQuestions .push (newQuestion)
830+ }
843831 const newBranches = [... this .branches ]
844832 newBranches[branchIndex] = {
845833 ... branch,
846- subQuestions: [ ... ( branch . subQuestions || []), newQuestion] ,
834+ subQuestions: newSubQuestions ,
847835 }
848836 this .onExtraSettingsChange ({ branches: newBranches })
849837 } catch (error) {
@@ -1228,16 +1216,6 @@ export default {
12281216 padding- left: 16px ;
12291217 border- left: 3px solid var (-- color- primary- element- light);
12301218 }
1231-
1232- & __subquestions- list {
1233- list- style: none;
1234- padding: 0 ;
1235- margin: 0 ;
1236- }
1237- }
1238-
1239- .subquestion {
1240- margin- bottom: 8px ;
12411219}
12421220
12431221.active - subquestions {
0 commit comments