Skip to content

Commit 19877cc

Browse files
timedin-demickenordin
authored andcommitted
fix: extract question list to seperate component, add 'insert question' to conditional
Signed-off-by: TimedIn <git@timedin.net>
1 parent bdc1666 commit 19877cc

3 files changed

Lines changed: 435 additions & 277 deletions

File tree

src/components/Questions/QuestionConditional.vue

Lines changed: 93 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -151,107 +151,46 @@
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')">
@@ -309,6 +248,7 @@
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'
330270
import IconSwapVertical from '@material-symbols/svg-400/outlined/swap_vert.svg?raw'
331271
import axios from '@nextcloud/axios'
332272
import { showError } from '@nextcloud/dialogs'
273+
import { emit } from '@nextcloud/event-bus'
333274
import { generateOcsUrl } from '@nextcloud/router'
334-
import { VueDraggable as Draggable } from 'vue-draggable-plus'
335275
import NcActionButton from '@nextcloud/vue/components/NcActionButton'
336276
import NcActions from '@nextcloud/vue/components/NcActions'
337277
import NcButton from '@nextcloud/vue/components/NcButton'
@@ -344,6 +284,7 @@ import QuestionDate from './QuestionDate.vue'
344284
import QuestionDropdown from './QuestionDropdown.vue'
345285
import QuestionFile from './QuestionFile.vue'
346286
import QuestionLinearScale from './QuestionLinearScale.vue'
287+
import QuestionList from './QuestionList.vue'
347288
import QuestionLong from './QuestionLong.vue'
348289
import QuestionMultiple from './QuestionMultiple.vue'
349290
import 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

Comments
 (0)