Dc3e4 new matrix field (#484)
* fix password reset bug * wip: matrix input * wip: matrix input * wip: matrix input * Fixed matric input component logic * matrix input cleanup * fix lint errors * table border and radius * cleanup, linting * fix component methos * wip matrix input * matrix condition for contains and not contain * patch matrix input condition logic * linting * refactor and cleanup * fix syntax error * Polished the matrix input * Fix linting --------- Co-authored-by: Julien Nahum <julien@nahum.net>
This commit is contained in:
@@ -187,6 +187,11 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<MatrixFieldOptions
|
||||
:model-value="field"
|
||||
@update:model-value="field = $event"
|
||||
/>
|
||||
|
||||
<!-- Text Options -->
|
||||
<div
|
||||
v-if="field.type === 'text' && displayBasedOnAdvanced"
|
||||
@@ -290,7 +295,6 @@
|
||||
Advanced options for your select/multiselect fields.
|
||||
</p>
|
||||
<text-area-input
|
||||
v-model="optionsText"
|
||||
:name="field.id + '_options_text'"
|
||||
class="mt-3"
|
||||
label="Set selection options"
|
||||
@@ -423,6 +427,15 @@
|
||||
label="Pre-filled value"
|
||||
:multiple="field.type === 'multi_select'"
|
||||
/>
|
||||
<template v-else-if="field.type === 'matrix'">
|
||||
<MatrixInput
|
||||
:form="field"
|
||||
:rows="field.rows"
|
||||
:columns="field.columns"
|
||||
name="prefill"
|
||||
label="Pre-filled value"
|
||||
/>
|
||||
</template>
|
||||
<date-input
|
||||
v-else-if="field.type === 'date' && field.prefill_today !== true"
|
||||
name="prefill"
|
||||
@@ -594,7 +607,7 @@
|
||||
:field="field"
|
||||
/>
|
||||
|
||||
<custom-field-validation
|
||||
<custom-field-validation
|
||||
class="py-2 px-4 border-b pb-16"
|
||||
:form="form"
|
||||
:field="field"
|
||||
@@ -608,12 +621,13 @@ import countryCodes from '~/data/country_codes.json'
|
||||
import CountryFlag from 'vue-country-flag-next'
|
||||
import FormBlockLogicEditor from '../../components/form-logic-components/FormBlockLogicEditor.vue'
|
||||
import CustomFieldValidation from '../../components/CustomFieldValidation.vue'
|
||||
import MatrixFieldOptions from './MatrixFieldOptions.vue'
|
||||
import { format } from 'date-fns'
|
||||
import { default as _has } from 'lodash/has'
|
||||
|
||||
export default {
|
||||
name: 'FieldOptions',
|
||||
components: { CountryFlag, FormBlockLogicEditor, CustomFieldValidation },
|
||||
components: { CountryFlag, FormBlockLogicEditor, CustomFieldValidation, MatrixFieldOptions },
|
||||
props: {
|
||||
field: {
|
||||
type: Object,
|
||||
@@ -682,12 +696,6 @@ export default {
|
||||
}
|
||||
return true
|
||||
},
|
||||
optionsText() {
|
||||
if (!this.field[this.field.type]) return ''
|
||||
return this.field[this.field.type].options.map(option => {
|
||||
return option.name
|
||||
}).join('\n')
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
@@ -868,6 +876,13 @@ export default {
|
||||
date: {
|
||||
date_format: this.dateFormatOptions[0].value,
|
||||
time_format: this.timeFormatOptions[0].value
|
||||
},
|
||||
matrix: {
|
||||
rows:['Row 1'],
|
||||
columns: [1 ,2 ,3],
|
||||
selection_data:{
|
||||
'Row 1': null
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.field.type in defaultFieldValues) {
|
||||
@@ -877,6 +892,9 @@ export default {
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
updateMatrixField(newField) {
|
||||
this.field = newField
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="localField.type === 'matrix'"
|
||||
class="border-b py-2 px-4"
|
||||
>
|
||||
<h3 class="font-semibold block text-lg">
|
||||
Matrix
|
||||
</h3>
|
||||
<p class="text-gray-400 mb-3 text-xs">
|
||||
Advanced options for matrix.
|
||||
</p>
|
||||
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div class="">
|
||||
<div
|
||||
v-for="(row, i) in localField.rows"
|
||||
:key="i"
|
||||
class="flex items-center space-x-2"
|
||||
>
|
||||
<text-input
|
||||
v-model="localField.rows[i]"
|
||||
name="rows"
|
||||
wrapper-class="mb-1"
|
||||
@update:model-value="updateField"
|
||||
/>
|
||||
<button @click="removeMatrixRow(i)">
|
||||
<Icon
|
||||
name="heroicons:trash"
|
||||
class="text-gray-300 w-4 h-4 mb-2"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<UButton
|
||||
size="xs"
|
||||
color="gray"
|
||||
icon="i-heroicons-plus"
|
||||
@click="addMatrixRow"
|
||||
>
|
||||
Add row
|
||||
</UButton>
|
||||
</div>
|
||||
<div class="">
|
||||
<div
|
||||
v-for="(column, i) in localField.columns"
|
||||
:key="i"
|
||||
class="flex items-center space-x-2"
|
||||
>
|
||||
<text-input
|
||||
v-model="localField.columns[i]"
|
||||
wrapper-class="mb-1"
|
||||
@update:model-value="updateField"
|
||||
/>
|
||||
<button @click="removeMatrixColumn(i)">
|
||||
<Icon
|
||||
name="heroicons:trash"
|
||||
class="text-gray-300 w-4 h-4 mb-2"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<UButton
|
||||
size="xs"
|
||||
color="gray"
|
||||
icon="i-heroicons-plus"
|
||||
@click="addMatrixColumn"
|
||||
>
|
||||
Add column
|
||||
</UButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch, computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const localField = ref({ ...props.modelValue })
|
||||
|
||||
watch(() => props.modelValue, (newField) => {
|
||||
localField.value = { ...newField }
|
||||
}, { deep: true })
|
||||
|
||||
const selectionData = computed(() => {
|
||||
return Object.fromEntries(localField.value.rows?.map(row => [row, '']))
|
||||
})
|
||||
|
||||
function updateField() {
|
||||
emit('update:modelValue', { ...localField.value })
|
||||
}
|
||||
|
||||
function addMatrixRow() {
|
||||
localField.value.rows.push(generateUniqueLabel(localField.value.rows, 'Row'))
|
||||
localField.value.selection_data = selectionData.value
|
||||
updateField()
|
||||
}
|
||||
|
||||
function removeMatrixRow(index) {
|
||||
localField.value.rows.splice(index, 1)
|
||||
localField.value.selection_data = selectionData.value
|
||||
updateField()
|
||||
}
|
||||
|
||||
function addMatrixColumn() {
|
||||
localField.value.columns.push(generateUniqueLabel(localField.value.columns, null))
|
||||
localField.value.selection_data = selectionData.value
|
||||
updateField()
|
||||
}
|
||||
|
||||
function removeMatrixColumn(index) {
|
||||
localField.value.columns.splice(index, 1)
|
||||
localField.value.selection_data = selectionData.value
|
||||
updateField()
|
||||
}
|
||||
|
||||
function generateUniqueLabel(array, prefix = null) {
|
||||
let uniqueNumber = 1 // Start checking from 1
|
||||
let label = prefix ? `${prefix} ${uniqueNumber}` : uniqueNumber
|
||||
while (array.includes(label)) {
|
||||
uniqueNumber++ // Increment if the number is found in the array
|
||||
label = prefix ? `${prefix} ${uniqueNumber}` : uniqueNumber
|
||||
}
|
||||
return label // Return the first unique number found
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<p class="font-semibold">Prefilled values</p>
|
||||
<select-input
|
||||
v-for="row in matrixData"
|
||||
:key="row.label"
|
||||
name="prefill"
|
||||
class="mt-3"
|
||||
:options="row.options"
|
||||
:label="row.label"
|
||||
v-model="selection[row.label]"
|
||||
@update:model-value="onSelection"
|
||||
/>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'MatrixPrefilledValues',
|
||||
props: {
|
||||
field: {
|
||||
type: Object,
|
||||
required: false
|
||||
},
|
||||
form: {
|
||||
type: Object,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selection: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
matrixData() {
|
||||
const options = this.field.columns || []
|
||||
return (this.field.row || []).map(row => {
|
||||
return {
|
||||
label: row,
|
||||
options: options?.map(option => ({ name: option, value: option }))
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.selection = this.field.prefill ?? this.field.selection_data ?? {}
|
||||
},
|
||||
methods: {
|
||||
onSelection() {
|
||||
this.field.prefill = this.selection
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user