Skip to content

Commit

Permalink
Merge pull request #869 from traPtitech/questionnaires/newtab=questions
Browse files Browse the repository at this point in the history
/questionnaires/new?tab=questions の実装 #500
  • Loading branch information
ryoha000 authored May 24, 2022
2 parents 2d75f26 + 76ba92a commit 4302ddf
Show file tree
Hide file tree
Showing 15 changed files with 397 additions and 152 deletions.
9 changes: 6 additions & 3 deletions src/assets/mdi.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
mdiChevronDown,
mdiChevronUp,
mdiChevronRight,
mdiMagnify,
mdiOpenInNew,
mdiHelpCircleOutline,
Expand All @@ -14,18 +15,19 @@ import {
mdiCheck,
mdiLoading,
mdiTrashCanOutline,
mdiAlertOutline
mdiAlertOutline,
mdiPlusCircleOutline
} from '@mdi/js'

const mdi = new Map<string, string>([
['chevron-down', mdiChevronDown],
['chevron-up', mdiChevronUp],
['chevron-right', mdiChevronRight],
['magnify', mdiMagnify],
['open-in-new', mdiOpenInNew],
['help-circle-outline', mdiHelpCircleOutline],
['menu', mdiMenu],
['close', mdiClose],
['chevron-down', mdiChevronDown],
['eye-closed', mdiEyeOff],
['eye', mdiEye],
['clipboard', mdiClipboard],
Expand All @@ -34,7 +36,8 @@ const mdi = new Map<string, string>([
['check', mdiCheck],
['loading', mdiLoading],
['trash-can-outline', mdiTrashCanOutline],
['alert', mdiAlertOutline]
['alert', mdiAlertOutline],
['plus-circle-outline', mdiPlusCircleOutline]
])

export default mdi
11 changes: 7 additions & 4 deletions src/components/NewQuestionnaire/AddQuestionButtons.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<template>
<button>
<button @click="isAppeared = !isAppeared">
新しい質問を追加
<Icon name="chevron-down" />
<Icon v-if="isAppeared" name="chevron-down" />
<Icon v-if="!isAppeared" name="chevron-right" />
</button>
<div>
<div v-if="isAppeared">
<button
v-for="(questionType, key) in questionTypes"
:key="key"
Expand All @@ -14,7 +15,7 @@
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { defineComponent, ref } from 'vue'
import Icon from '/@/components/UI/Icon.vue'
import { questionTypes } from './use/utils'
Expand All @@ -28,10 +29,12 @@ export default defineComponent({
add: (key: string) => true
},
setup(props, context) {
const isAppeared = ref(false)
const add = (key: string) => {
context.emit('add', key)
}
return {
isAppeared,
add,
questionTypes
}
Expand Down
11 changes: 3 additions & 8 deletions src/components/NewQuestionnaire/Forms/ChoiceElement.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
<template>
<div>
<Icon name="chevron-up" />
<Icon name="chevron-down" />
</div>
<input v-if="!isRadio" type="checkbox" value="true" />
<input v-if="isRadio" type="radio" value="true" />
<QuestionInput v-model="labelRef" />
<Icon name="delete" @click="deleteChoice" />
<input :type="[isRadio ? 'radio' : 'checkbox']" value="true" />
<QuestionInput v-model="labelRef" :model-value="label" />
<Icon name="trash-can-outline" @click="deleteChoice" />
</template>

<script lang="ts">
Expand Down
58 changes: 39 additions & 19 deletions src/components/NewQuestionnaire/Forms/ChoiceForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@
@update:required="updateQuestionRequired"
>
<div>
<div v-for="(label, i) in questionData.options" :key="i">
<div v-for="(label, i) in choiceQuestions" :key="i">
<QuestionUpdown
:index="i"
:max="choiceQuestions.length"
@swap="swapChoice"
/>
<ChoiceElement
:label="label"
:index="i"
Expand All @@ -17,18 +22,19 @@
</div>
</div>
<div>
<span @click="addChoice">
<span :class="$style.newchoice" @click="addChoice">
<Icon name="plus-circle-outline" />新しい選択肢を追加
</span>
</div>
</QuestionForm>
</template>

<script lang="ts">
import { defineComponent, PropType } from 'vue'
import { defineComponent, PropType, computed } from 'vue'
import QuestionForm from './QuestionForm.vue'
import ChoiceElement from './ChoiceElement.vue'
import Icon from '../../UI/Icon.vue'
import QuestionUpdown from './QuestionUpdown.vue'
import { CheckboxQuestion } from '../use/utils'
import { updateQuestionData } from '../use/updateQuestionData'
Expand All @@ -37,13 +43,10 @@ export default defineComponent({
components: {
QuestionForm,
ChoiceElement,
QuestionUpdown,
Icon
},
props: {
index: {
type: Number,
required: true
},
questionData: {
type: Object as PropType<CheckboxQuestion>,
required: true
Expand All @@ -55,9 +58,10 @@ export default defineComponent({
},
emits: {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
update: (question: CheckboxQuestion, index: number) => true
update: (question: CheckboxQuestion) => true
},
setup(props, context) {
const choiceQuestions = computed(() => props.questionData.options)
const updateChoiceQuestionData = updateQuestionData<CheckboxQuestion>(
props,
context
Expand All @@ -70,30 +74,46 @@ export default defineComponent({
}
const updateChoice = (label: string, index: number) => {
const newOptions = [...props.questionData.options]
newOptions[index] = label
updateChoiceQuestionData('options', newOptions)
const tmp = [...choiceQuestions.value]
tmp[index] = label
updateChoiceQuestionData('options', tmp)
}
const deleteChoice = (label: string, index: number) => {
const newOptions = [...props.questionData.options]
newOptions.splice(index, 1)
updateChoiceQuestionData('options', newOptions)
const deleteChoice = (index: number) => {
const tmp = [...choiceQuestions.value]
tmp.splice(index, 1)
updateChoiceQuestionData('options', tmp)
}
const addChoice = () => {
const newOptions = [...props.questionData.options]
newOptions.push('')
updateChoiceQuestionData('options', newOptions)
const tmp = [...choiceQuestions.value]
tmp.push('')
updateChoiceQuestionData('options', tmp)
}
const swapChoice = (index1: number, index2: number) => {
const tmp = [...choiceQuestions.value]
const mom = tmp[index1]
tmp[index1] = tmp[index2]
tmp[index2] = mom
updateChoiceQuestionData('options', tmp)
}
return {
choiceQuestions,
updateQuestionName,
updateQuestionRequired,
updateChoice,
deleteChoice,
addChoice
addChoice,
swapChoice
}
}
})
</script>

<style lang="scss" module>
.newchoice {
cursor: pointer;
}
</style>
81 changes: 47 additions & 34 deletions src/components/NewQuestionnaire/Forms/LinearScaleForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,49 @@
@update:required="updateQuestionRequired"
>
<div>
<Select v-model="rangeMin" :contents="['0', '1']" />
<Select
:model-value="rangeMin"
:contents="['0', '1']"
@update:model-value="
modelValue => updateLinearScale('scale_min', Number(modelValue))
"
/>
to
<Select
v-model="rangeMax"
:model-value="rangeMax"
:contents="['2', '3', '4', '5', '6', '7', '8', '9', '10']"
@update:model-value="
modelValue => updateLinearScale('scale_max', Number(modelValue))
"
/>
</div>
<div>
<div>
{{ questionData.scale_min }}
<QuestionInput v-model="labelMin" :is-number="false" />
<QuestionInput
:model-value="labelLeft"
:is-number="false"
@update:model-value="
modelValue => updateLinearScale('scale_label_left', modelValue)
"
/>
</div>
<div>
{{ questionData.scale_max }}
<QuestionInput v-model="labelMax" :is-number="false" />
<QuestionInput
:model-value="labelRight"
:is-number="false"
@update:model-value="
modelValue => updateLinearScale('scale_label_right', modelValue)
"
/>
</div>
</div>
</QuestionForm>
</template>

<script lang="ts">
import { defineComponent, PropType, ref, watch } from 'vue'
import { defineComponent, PropType, computed } from 'vue'
import QuestionForm from './QuestionForm.vue'
import Select from '../../UI/Select.vue'
import QuestionInput from '../../UI/QuestionInput.vue'
Expand All @@ -38,22 +59,18 @@ export default defineComponent({
name: 'ChoiceForm',
components: {
QuestionForm,
QuestionInput,
Select
Select,
QuestionInput
},
props: {
index: {
type: Number,
required: true
},
questionData: {
type: Object as PropType<LinearScaleQuestion>,
required: true
}
},
emits: {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
update: (question: LinearScaleQuestion, index: number) => true
update: (question: LinearScaleQuestion) => true
},
setup(props, context) {
const updateLinearScaleQuestionData =
Expand All @@ -65,34 +82,30 @@ export default defineComponent({
updateLinearScaleQuestionData('is_required', required)
}
const rangeMin = ref(props.questionData.scale_min + '')
const rangeMax = ref(props.questionData.scale_max + '')
const labelMin = ref(props.questionData.scale_label_left)
const labelMax = ref(props.questionData.scale_label_right)
watch(rangeMin, rangeMinValue =>
updateLinearScaleQuestionData('scale_min', Number(rangeMinValue))
)
const rangeMin = computed(() => String(props.questionData.scale_min))
const rangeMax = computed(() => String(props.questionData.scale_max))
const labelLeft = computed(() => props.questionData.scale_label_left)
const labelRight = computed(() => props.questionData.scale_label_right)
watch(rangeMax, rangeMaxValue =>
updateLinearScaleQuestionData('scale_max', Number(rangeMaxValue))
)
watch(labelMin, labelMinValue =>
updateLinearScaleQuestionData('scale_label_left', labelMinValue)
)
watch(labelMax, labelMaxValue =>
updateLinearScaleQuestionData('scale_label_right', labelMaxValue)
)
const updateLinearScale = (
type:
| 'scale_min'
| 'scale_max'
| 'scale_label_left'
| 'scale_label_right',
value: string | number
) => {
updateLinearScaleQuestionData(type, value)
}
return {
rangeMin,
rangeMax,
labelMin,
labelMax,
labelLeft,
labelRight,
updateQuestionBody,
updateQuestionRequired
updateQuestionRequired,
updateLinearScale
}
}
})
Expand Down
40 changes: 40 additions & 0 deletions src/components/NewQuestionnaire/Forms/QuestionDispose.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<template>
<Icon name="trash-can-outline" @click="deleteQuestion" />
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import Icon from '/@/components/UI/Icon.vue'
export default defineComponent({
name: 'QuestionDispose',
components: {
Icon
},
props: {
questionarray: {
type: Array,
required: true
},
index: {
type: Number,
required: true
}
},
emits: {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
delete: (index: number) => true
},
setup(props, context) {
const deleteQuestion = () => {
const isTrash = confirm('この質問を削除しますか?')
if (isTrash) {
context.emit('delete', props.index)
}
}
return { deleteQuestion }
}
})
</script>

<style lang="scss" module></style>
Loading

0 comments on commit 4302ddf

Please sign in to comment.