@webitel/ui-sdk 3.1.59 → 3.1.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ui-sdk.common.js +15 -15
- package/dist/ui-sdk.common.js.map +1 -1
- package/dist/ui-sdk.css +1 -1
- package/dist/ui-sdk.umd.js +15 -15
- package/dist/ui-sdk.umd.js.map +1 -1
- package/dist/ui-sdk.umd.min.js +1 -1
- package/dist/ui-sdk.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/molecules/wt-input/wt-input.vue +1 -1
- package/src/mixins/validationMixin/validationMixin.js +12 -12
- package/src/modules/AuditForm/components/audit-form-question-read-wrapper.vue +3 -3
- package/src/modules/AuditForm/components/audit-form-question-write-wrapper.vue +6 -5
- package/src/modules/AuditForm/components/audit-form-question.vue +25 -16
- package/src/modules/AuditForm/components/audit-form.vue +13 -3
- package/src/modules/AuditForm/components/questions/options/__tests__/audit-form-question-options-write-row.spec.js +24 -0
- package/src/modules/AuditForm/components/questions/{__tests__ → options/__tests__}/audit-form-question-options.spec.js +2 -3
- package/src/modules/AuditForm/components/questions/options/audit-form-question-options-write-row.vue +83 -0
- package/src/modules/AuditForm/components/questions/{audit-form-question-options.vue → options/audit-form-question-options.vue} +13 -40
- package/src/modules/AuditForm/components/questions/{audit-form-question-score.vue → score/audit-form-question-score.vue} +40 -4
- package/src/modules/AuditForm/schemas/AuditFormQuestionSchema.js +3 -3
- /package/src/modules/AuditForm/components/questions/{__tests__ → score/__tests__}/audit-form-question-score.spec.js +0 -0
package/package.json
CHANGED
|
@@ -19,21 +19,21 @@ export default {
|
|
|
19
19
|
validationText() {
|
|
20
20
|
let validationText = '';
|
|
21
21
|
if (this.isValidation && this.invalid) {
|
|
22
|
-
if (this.v.required
|
|
23
|
-
else if (this.v.numeric
|
|
24
|
-
else if (this.v.email
|
|
25
|
-
else if (this.v.gatewayHostValidator
|
|
26
|
-
else if (this.v.ipValidator
|
|
27
|
-
else if (this.v.macValidator
|
|
28
|
-
else if (this.v.minValue
|
|
29
|
-
else if (this.v.maxValue
|
|
30
|
-
else if (this.v.sipAccountValidator
|
|
31
|
-
else if (this.v.minLength
|
|
32
|
-
else if (this.v.url
|
|
22
|
+
if (this.v.required?.$invalid) validationText = this.$t('validation.required');
|
|
23
|
+
else if (this.v.numeric?.$invalid) validationText = this.$t('validation.numeric');
|
|
24
|
+
else if (this.v.email?.$invalid) validationText = this.$t('validation.email');
|
|
25
|
+
else if (this.v.gatewayHostValidator?.$invalid) validationText = this.$t('validation.gatewayHostValidator');
|
|
26
|
+
else if (this.v.ipValidator?.$invalid) validationText = this.$t('validation.ipValidator');
|
|
27
|
+
else if (this.v.macValidator?.$invalid) validationText = this.$t('validation.macValidator');
|
|
28
|
+
else if (this.v.minValue?.$invalid) validationText = `${this.$t('validation.minValue')} ${this.v.minValue.$params.min}`;
|
|
29
|
+
else if (this.v.maxValue?.$invalid) validationText = `${this.$t('validation.maxValue')} ${this.v.maxValue.$params.max}`;
|
|
30
|
+
else if (this.v.sipAccountValidator?.$invalid) validationText = this.$t('validation.sipAccountValidator');
|
|
31
|
+
else if (this.v.minLength?.$invalid) validationText = `${this.$t('validation.minLength')} ${this.v.minLength.$params.min}`;
|
|
32
|
+
else if (this.v.url?.$invalid) validationText = `${this.$t('validation.url')}`;
|
|
33
33
|
}
|
|
34
34
|
// eslint-disable-next-line no-restricted-syntax
|
|
35
35
|
for (const { name, text } of this.customValidators) {
|
|
36
|
-
if (this.v[name]
|
|
36
|
+
if (this.v[name]?.$invalid) validationText = text;
|
|
37
37
|
}
|
|
38
38
|
return validationText;
|
|
39
39
|
},
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
<script setup>
|
|
38
38
|
import { computed } from 'vue';
|
|
39
39
|
import { EngineAuditQuestionType } from 'webitel-sdk';
|
|
40
|
-
import AuditFormQuestionOptions from './questions/audit-form-question-options.vue';
|
|
41
|
-
import AuditFormQuestionScore from './questions/audit-form-question-score.vue';
|
|
40
|
+
import AuditFormQuestionOptions from './questions/options/audit-form-question-options.vue';
|
|
41
|
+
import AuditFormQuestionScore from './questions/score/audit-form-question-score.vue';
|
|
42
42
|
import WtIcon from '../../../components/atoms/wt-icon/wt-icon.vue';
|
|
43
43
|
|
|
44
44
|
const props = defineProps({
|
|
@@ -47,7 +47,7 @@ const props = defineProps({
|
|
|
47
47
|
required: true,
|
|
48
48
|
},
|
|
49
49
|
result: {
|
|
50
|
-
type: Object,
|
|
50
|
+
type: [Object, null],
|
|
51
51
|
required: true,
|
|
52
52
|
},
|
|
53
53
|
disableDragging: {
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<wt-switcher
|
|
5
5
|
:value="question.required"
|
|
6
6
|
:label="$t('reusable.required')"
|
|
7
|
+
:disabled="first"
|
|
7
8
|
@change="updateQuestion({ path: 'required', value: $event })"
|
|
8
9
|
></wt-switcher>
|
|
9
10
|
<div class="audit-form-question-write-header__actions">
|
|
@@ -20,7 +21,7 @@
|
|
|
20
21
|
<template v-slot:activator>
|
|
21
22
|
<wt-icon-btn
|
|
22
23
|
icon="bucket"
|
|
23
|
-
:disabled="
|
|
24
|
+
:disabled="first"
|
|
24
25
|
@click="emit('delete')"
|
|
25
26
|
></wt-icon-btn>
|
|
26
27
|
</template>
|
|
@@ -68,8 +69,8 @@ import WtIconBtn from '../../../components/molecules/wt-icon-btn/wt-icon-btn.vue
|
|
|
68
69
|
import WtInput from '../../../components/molecules/wt-input/wt-input.vue';
|
|
69
70
|
import WtSelect from '../../../components/molecules/wt-select/wt-select.vue';
|
|
70
71
|
|
|
71
|
-
import AuditFormQuestionOptions from './questions/audit-form-question-options.vue';
|
|
72
|
-
import AuditFormQuestionScore from './questions/audit-form-question-score.vue';
|
|
72
|
+
import AuditFormQuestionOptions from './questions/options/audit-form-question-options.vue';
|
|
73
|
+
import AuditFormQuestionScore from './questions/score/audit-form-question-score.vue';
|
|
73
74
|
|
|
74
75
|
import { generateQuestionScoreSchema } from '../schemas/AuditFormQuestionScoreSchema';
|
|
75
76
|
import { generateQuestionOptionsSchema } from '../schemas/AuditFormQuestionOptionsSchema';
|
|
@@ -79,9 +80,9 @@ const props = defineProps({
|
|
|
79
80
|
type: Object,
|
|
80
81
|
required: true,
|
|
81
82
|
},
|
|
82
|
-
|
|
83
|
+
first: {
|
|
83
84
|
type: Boolean,
|
|
84
|
-
default:
|
|
85
|
+
default: false,
|
|
85
86
|
},
|
|
86
87
|
v: {
|
|
87
88
|
type: Object,
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<component
|
|
3
|
-
|
|
3
|
+
:is="component"
|
|
4
|
+
v-clickaway="saveQuestion"
|
|
4
5
|
:class="[
|
|
5
6
|
`audit-form-question--mode-${mode}`
|
|
6
7
|
]"
|
|
7
|
-
|
|
8
|
-
:
|
|
8
|
+
:disable-dragging="mode === 'fill'"
|
|
9
|
+
:first="first"
|
|
9
10
|
:question="question"
|
|
11
|
+
:readonly="readonly"
|
|
10
12
|
:result="result"
|
|
11
13
|
:v="v$"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
:readonly="readonly"
|
|
14
|
+
class="audit-form-question"
|
|
15
|
+
@activate="activateQuestion"
|
|
15
16
|
@copy="emits('copy')"
|
|
16
17
|
@delete="emits('delete')"
|
|
17
|
-
@activate="activateQuestion"
|
|
18
18
|
@change:question="emits('update:question', $event)"
|
|
19
19
|
@change:result="emits('update:result', $event)"
|
|
20
20
|
></component>
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
<script setup>
|
|
24
24
|
import { useVuelidate } from '@vuelidate/core';
|
|
25
25
|
import { required } from '@vuelidate/validators';
|
|
26
|
-
import { computed, ref, toRefs } from 'vue';
|
|
26
|
+
import { computed, onMounted, ref, toRefs } from 'vue';
|
|
27
27
|
import vClickaway from '../../../directives/clickaway/clickaway';
|
|
28
|
-
import QuestionWrite from './audit-form-question-write-wrapper.vue';
|
|
29
28
|
import QuestionRead from './audit-form-question-read-wrapper.vue';
|
|
29
|
+
import QuestionWrite from './audit-form-question-write-wrapper.vue';
|
|
30
30
|
|
|
31
31
|
const props = defineProps({
|
|
32
32
|
question: {
|
|
@@ -39,9 +39,9 @@ const props = defineProps({
|
|
|
39
39
|
mode: {
|
|
40
40
|
type: String,
|
|
41
41
|
},
|
|
42
|
-
|
|
42
|
+
first: {
|
|
43
43
|
type: Boolean,
|
|
44
|
-
default:
|
|
44
|
+
default: false,
|
|
45
45
|
},
|
|
46
46
|
readonly: {
|
|
47
47
|
type: Boolean,
|
|
@@ -63,17 +63,20 @@ const QuestionState = {
|
|
|
63
63
|
|
|
64
64
|
const state = ref(QuestionState.SAVED);
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
// is needed for useVuelidate, because props.question/props.result isn't reactive
|
|
67
|
+
const { question, result } = toRefs(props);
|
|
67
68
|
|
|
68
|
-
// validate only "create" mode
|
|
69
69
|
const v$ = useVuelidate(computed(() => (
|
|
70
70
|
(props.mode === 'create')
|
|
71
71
|
? {
|
|
72
72
|
question: {
|
|
73
73
|
question: { required },
|
|
74
74
|
},
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
} : {
|
|
76
|
+
result: {
|
|
77
|
+
required: (value) => (question.value.required ? !!value : true),
|
|
78
|
+
},
|
|
79
|
+
})), { question, result }, { $autoDirty: true });
|
|
77
80
|
|
|
78
81
|
const component = computed(() => {
|
|
79
82
|
if (props.readonly) return QuestionRead;
|
|
@@ -92,13 +95,19 @@ function activateQuestion() {
|
|
|
92
95
|
if (props.mode !== 'create') return;
|
|
93
96
|
state.value = QuestionState.EDIT;
|
|
94
97
|
}
|
|
98
|
+
|
|
99
|
+
// initialize validations
|
|
100
|
+
onMounted(() => {
|
|
101
|
+
v$.value.$touch();
|
|
102
|
+
activateQuestion();
|
|
103
|
+
});
|
|
95
104
|
</script>
|
|
96
105
|
|
|
97
106
|
<style lang="scss" scoped>
|
|
98
107
|
.audit-form-question {
|
|
99
108
|
padding: var(--spacing-sm);
|
|
100
|
-
background: var(--main-color);
|
|
101
109
|
border-radius: var(--border-radius);
|
|
110
|
+
background: var(--main-color);
|
|
102
111
|
box-shadow: var(--elevation-1);
|
|
103
112
|
|
|
104
113
|
&--mode-create.audit-form-question-read {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
:question="question"
|
|
12
12
|
:result="(result && result[key]) ? result[key] : null"
|
|
13
13
|
:mode="mode"
|
|
14
|
-
:
|
|
14
|
+
:first="key === 0"
|
|
15
15
|
:readonly="readonly"
|
|
16
16
|
@copy="copyQuestion({ question, key })"
|
|
17
17
|
@delete="deleteQuestion({ question, key})"
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
<script setup>
|
|
33
33
|
import cloneDeep from 'lodash/cloneDeep';
|
|
34
34
|
import {
|
|
35
|
-
watch, watchEffect, ref, computed,
|
|
35
|
+
watch, watchEffect, ref, computed, onMounted,
|
|
36
36
|
} from 'vue';
|
|
37
37
|
import { useVuelidate } from '@vuelidate/core';
|
|
38
38
|
import { useDestroyableSortable } from '../composables/useDestroyableSortable';
|
|
@@ -115,6 +115,12 @@ function initResult() {
|
|
|
115
115
|
emit('update:result', result);
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
function initQuestions() {
|
|
119
|
+
if (props.mode === 'create' && !props.questions.length) {
|
|
120
|
+
addQuestion({ question: generateQuestionSchema({ required: true }) });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
118
124
|
const sortableWrapper = ref(null);
|
|
119
125
|
|
|
120
126
|
const { reloadSortable } = useDestroyableSortable(sortableWrapper, {
|
|
@@ -126,8 +132,12 @@ const { reloadSortable } = useDestroyableSortable(sortableWrapper, {
|
|
|
126
132
|
},
|
|
127
133
|
});
|
|
128
134
|
|
|
129
|
-
watch(v$, () => emit('update:validation', v$));
|
|
135
|
+
watch(v$, () => emit('update:validation', { invalid: isInvalidForm, v$ }));
|
|
130
136
|
watchEffect(initResult);
|
|
137
|
+
|
|
138
|
+
onMounted(() => {
|
|
139
|
+
initQuestions();
|
|
140
|
+
});
|
|
131
141
|
</script>
|
|
132
142
|
|
|
133
143
|
<style lang="scss" scoped>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { shallowMount, mount } from '@vue/test-utils';
|
|
2
|
+
import AuditFormQuestionOptionsWriteRow from '../audit-form-question-options-write-row.vue';
|
|
3
|
+
|
|
4
|
+
describe('AuditFormQuestionOptionsWriteRow', () => {
|
|
5
|
+
it('renders a component', () => {
|
|
6
|
+
const wrapper = shallowMount(AuditFormQuestionOptionsWriteRow, {
|
|
7
|
+
props: {
|
|
8
|
+
option: {},
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
expect(wrapper.isVisible()).toBe(true);
|
|
12
|
+
});
|
|
13
|
+
it('emits "delete" event at "delete" icon-btn click', () => {
|
|
14
|
+
const wrapper = mount(AuditFormQuestionOptionsWriteRow, {
|
|
15
|
+
props: {
|
|
16
|
+
option: {},
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
const deleteBtn = wrapper.findComponent({ name: 'wt-icon-btn' });
|
|
20
|
+
expect(deleteBtn.props().icon).toBe('bucket');
|
|
21
|
+
deleteBtn.vm.$emit('click');
|
|
22
|
+
expect(wrapper.emitted().delete).toBeTruthy();
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -27,9 +27,8 @@ describe('AuditFormQuestionOptions', () => {
|
|
|
27
27
|
mode: 'write',
|
|
28
28
|
},
|
|
29
29
|
});
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
deleteBtn.vm.$emit('click');
|
|
30
|
+
const writeRow = wrapper.findComponent({ name: 'audit-form-question-options-write-row' });
|
|
31
|
+
writeRow.vm.$emit('delete');
|
|
33
32
|
expect(wrapper.emitted()['change:question'][0][0].options.length).toBe(0);
|
|
34
33
|
});
|
|
35
34
|
it('emits result change with selected radio option score', () => {
|
package/src/modules/AuditForm/components/questions/options/audit-form-question-options-write-row.vue
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="audit-form-question-options-write-row">
|
|
3
|
+
<wt-input
|
|
4
|
+
:label="$t('webitelUI.auditForm.option', 1)"
|
|
5
|
+
:value="option.name"
|
|
6
|
+
:v="v$.option.name"
|
|
7
|
+
@input="emit('update:option', { name: $event, score: option.score })"
|
|
8
|
+
></wt-input>
|
|
9
|
+
<wt-input
|
|
10
|
+
:label="$t('webitelUI.auditForm.score', 1)"
|
|
11
|
+
:value="option.score"
|
|
12
|
+
:v="v$.option.score"
|
|
13
|
+
type="number"
|
|
14
|
+
@input="emit('update:option', { name: option.name, score: $event })"
|
|
15
|
+
></wt-input>
|
|
16
|
+
<wt-tooltip>
|
|
17
|
+
<template v-slot:activator>
|
|
18
|
+
<wt-icon-btn
|
|
19
|
+
:disabled="first"
|
|
20
|
+
icon="bucket"
|
|
21
|
+
@click="emit('delete')"
|
|
22
|
+
></wt-icon-btn>
|
|
23
|
+
</template>
|
|
24
|
+
{{ $t('reusable.delete') }}
|
|
25
|
+
</wt-tooltip>
|
|
26
|
+
</div>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<script setup>
|
|
30
|
+
import { useVuelidate } from '@vuelidate/core';
|
|
31
|
+
import { required, minValue, maxValue } from '@vuelidate/validators';
|
|
32
|
+
import { computed, onMounted, toRefs } from 'vue';
|
|
33
|
+
import WtTooltip from '../../../../../components/atoms/wt-tooltip/wt-tooltip.vue';
|
|
34
|
+
import WtIconBtn from '../../../../../components/molecules/wt-icon-btn/wt-icon-btn.vue';
|
|
35
|
+
import WtInput from '../../../../../components/molecules/wt-input/wt-input.vue';
|
|
36
|
+
|
|
37
|
+
const props = defineProps({
|
|
38
|
+
option: {
|
|
39
|
+
type: Object,
|
|
40
|
+
required: true,
|
|
41
|
+
},
|
|
42
|
+
first: {
|
|
43
|
+
type: Boolean,
|
|
44
|
+
default: false,
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const emit = defineEmits([
|
|
49
|
+
'change:option',
|
|
50
|
+
'delete',
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
// is needed for useVuelidate, because props.question/props.result isn't reactive
|
|
54
|
+
const { option } = toRefs(props);
|
|
55
|
+
|
|
56
|
+
const v$ = useVuelidate(
|
|
57
|
+
computed(() => (
|
|
58
|
+
{
|
|
59
|
+
option: {
|
|
60
|
+
name: { required },
|
|
61
|
+
score: {
|
|
62
|
+
required,
|
|
63
|
+
minValue: minValue(0),
|
|
64
|
+
maxValue: maxValue(10),
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
})),
|
|
68
|
+
{ option },
|
|
69
|
+
{ $autoDirty: true },
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
// init validation
|
|
73
|
+
onMounted(() => v$.value.$touch());
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
<style lang="scss" scoped>
|
|
77
|
+
.audit-form-question-options-write-row {
|
|
78
|
+
display: grid;
|
|
79
|
+
align-items: center;
|
|
80
|
+
grid-template-columns: 3fr 1fr 24px;
|
|
81
|
+
gap: var(--spacing-sm);
|
|
82
|
+
}
|
|
83
|
+
</style>
|
|
@@ -4,32 +4,14 @@
|
|
|
4
4
|
v-if="mode === 'write'"
|
|
5
5
|
class="audit-form-question-options-write"
|
|
6
6
|
>
|
|
7
|
-
<
|
|
8
|
-
v-for="(
|
|
7
|
+
<options-write-row
|
|
8
|
+
v-for="(option, key) of question.options"
|
|
9
9
|
:key="key"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@input="updateQuestion({ path: `options[${key}].name`, value: $event })"
|
|
16
|
-
></wt-input>
|
|
17
|
-
<wt-input
|
|
18
|
-
:value="score"
|
|
19
|
-
:label="$t('webitelUI.auditForm.score', 1)"
|
|
20
|
-
type="number"
|
|
21
|
-
@input="updateQuestion({ path: `options[${key}].score`, value: $event })"
|
|
22
|
-
></wt-input>
|
|
23
|
-
<wt-tooltip>
|
|
24
|
-
<template v-slot:activator>
|
|
25
|
-
<wt-icon-btn
|
|
26
|
-
icon="bucket"
|
|
27
|
-
@click="deleteQuestionOption({ key })"
|
|
28
|
-
></wt-icon-btn>
|
|
29
|
-
</template>
|
|
30
|
-
{{ $t('reusable.delete') }}
|
|
31
|
-
</wt-tooltip>
|
|
32
|
-
</div>
|
|
10
|
+
:option="option"
|
|
11
|
+
:first="key === 0"
|
|
12
|
+
@update:option="updateQuestion({ path: `options[${key}]`, value: $event })"
|
|
13
|
+
@delete="deleteQuestionOption({ key })"
|
|
14
|
+
></options-write-row>
|
|
33
15
|
<wt-button
|
|
34
16
|
class="audit-form-question-options-write__add-button"
|
|
35
17
|
@click="addQuestionOption"
|
|
@@ -44,8 +26,8 @@
|
|
|
44
26
|
v-for="({ name, score }) of question.options"
|
|
45
27
|
:key="score"
|
|
46
28
|
:label="name"
|
|
47
|
-
:value="score"
|
|
48
29
|
:selected="result ? result.score : result"
|
|
30
|
+
:value="score"
|
|
49
31
|
@input="emit('change:result', { score })"
|
|
50
32
|
></wt-radio>
|
|
51
33
|
</div>
|
|
@@ -54,13 +36,11 @@
|
|
|
54
36
|
</template>
|
|
55
37
|
|
|
56
38
|
<script setup>
|
|
57
|
-
import
|
|
58
|
-
import
|
|
59
|
-
import
|
|
60
|
-
import
|
|
61
|
-
import
|
|
62
|
-
import WtRadio from '../../../../components/molecules/wt-radio/wt-radio.vue';
|
|
63
|
-
import { generateOption } from '../../schemas/AuditFormQuestionOptionsSchema';
|
|
39
|
+
import OptionsWriteRow from './audit-form-question-options-write-row.vue';
|
|
40
|
+
import WtButton from '../../../../../components/atoms/wt-button/wt-button.vue';
|
|
41
|
+
import WtRadio from '../../../../../components/molecules/wt-radio/wt-radio.vue';
|
|
42
|
+
import updateObject from '../../../../../scripts/updateObject';
|
|
43
|
+
import { generateOption } from '../../../schemas/AuditFormQuestionOptionsSchema';
|
|
64
44
|
|
|
65
45
|
const props = defineProps({
|
|
66
46
|
question: {
|
|
@@ -109,13 +89,6 @@ function deleteQuestionOption({ key }) {
|
|
|
109
89
|
}
|
|
110
90
|
}
|
|
111
91
|
|
|
112
|
-
.audit-form-question-options-write-row {
|
|
113
|
-
display: grid;
|
|
114
|
-
grid-template-columns: 3fr 1fr 24px;
|
|
115
|
-
gap: var(--spacing-sm);
|
|
116
|
-
align-items: center;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
92
|
.audit-form-question-options-read {
|
|
120
93
|
display: flex;
|
|
121
94
|
flex-direction: column;
|
|
@@ -6,12 +6,20 @@
|
|
|
6
6
|
>
|
|
7
7
|
<wt-input
|
|
8
8
|
:value="question.min"
|
|
9
|
+
:v="v$.question.min"
|
|
10
|
+
:number-min="0"
|
|
11
|
+
:number-max="19"
|
|
9
12
|
type="number"
|
|
13
|
+
required
|
|
10
14
|
@input="updateQuestion({ path: 'min', value: $event })"
|
|
11
15
|
></wt-input>
|
|
12
16
|
<wt-input
|
|
13
17
|
:value="question.max"
|
|
18
|
+
:v="v$.question.max"
|
|
19
|
+
:number-min="1"
|
|
20
|
+
:number-max="20"
|
|
14
21
|
type="number"
|
|
22
|
+
required
|
|
15
23
|
@input="updateQuestion({ path: 'max', value: $event })"
|
|
16
24
|
></wt-input>
|
|
17
25
|
</div>
|
|
@@ -32,10 +40,12 @@
|
|
|
32
40
|
</template>
|
|
33
41
|
|
|
34
42
|
<script setup>
|
|
35
|
-
import {
|
|
36
|
-
import
|
|
37
|
-
import
|
|
38
|
-
import
|
|
43
|
+
import { useVuelidate } from '@vuelidate/core';
|
|
44
|
+
import { maxValue, minValue, required } from '@vuelidate/validators';
|
|
45
|
+
import { computed, onMounted, toRefs } from 'vue';
|
|
46
|
+
import updateObject from '../../../../../scripts/updateObject';
|
|
47
|
+
import WtRadio from '../../../../../components/molecules/wt-radio/wt-radio.vue';
|
|
48
|
+
import WtInput from '../../../../../components/molecules/wt-input/wt-input.vue';
|
|
39
49
|
|
|
40
50
|
const props = defineProps({
|
|
41
51
|
question: {
|
|
@@ -57,6 +67,29 @@ const emit = defineEmits([
|
|
|
57
67
|
'change:result',
|
|
58
68
|
]);
|
|
59
69
|
|
|
70
|
+
// is needed for useVuelidate, because props.question/props.result isn't reactive
|
|
71
|
+
const { question } = toRefs(props);
|
|
72
|
+
|
|
73
|
+
const v$ = useVuelidate(
|
|
74
|
+
computed(() => (
|
|
75
|
+
{
|
|
76
|
+
question: {
|
|
77
|
+
min: {
|
|
78
|
+
minValue: minValue(0),
|
|
79
|
+
maxValue: maxValue(9),
|
|
80
|
+
required,
|
|
81
|
+
},
|
|
82
|
+
max: {
|
|
83
|
+
minValue: minValue(1),
|
|
84
|
+
maxValue: maxValue(10),
|
|
85
|
+
required,
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
})),
|
|
89
|
+
{ question },
|
|
90
|
+
{ $autoDirty: true },
|
|
91
|
+
);
|
|
92
|
+
|
|
60
93
|
const scoreRange = computed(() => {
|
|
61
94
|
if (props.question.min > props.question.max) return [];
|
|
62
95
|
const result = [];
|
|
@@ -71,6 +104,9 @@ const scoreRange = computed(() => {
|
|
|
71
104
|
function updateQuestion({ path, value }) {
|
|
72
105
|
emit('change:question', updateObject({ obj: props.question, path, value }));
|
|
73
106
|
}
|
|
107
|
+
|
|
108
|
+
// init validation
|
|
109
|
+
onMounted(() => v$.value.$touch());
|
|
74
110
|
</script>
|
|
75
111
|
|
|
76
112
|
<style lang="scss" scoped>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { generateQuestionScoreSchema } from './AuditFormQuestionScoreSchema';
|
|
2
2
|
|
|
3
3
|
// eslint-disable-next-line import/prefer-default-export
|
|
4
|
-
export const generateQuestionSchema = () => ({
|
|
5
|
-
required
|
|
6
|
-
question: '
|
|
4
|
+
export const generateQuestionSchema = ({ required = false } = {}) => ({
|
|
5
|
+
required,
|
|
6
|
+
question: '',
|
|
7
7
|
...generateQuestionScoreSchema(),
|
|
8
8
|
});
|
|
File without changes
|