2023-12-09 15:47:03 +01:00
|
|
|
<template>
|
2024-04-15 19:39:03 +02:00
|
|
|
<div
|
|
|
|
|
v-if="!isFieldHidden"
|
|
|
|
|
:id="'block-' + field.id"
|
2024-09-23 20:02:38 +02:00
|
|
|
ref="form-block"
|
2024-05-22 14:41:48 +02:00
|
|
|
class="px-2"
|
2024-05-13 14:47:59 +02:00
|
|
|
:class="[
|
|
|
|
|
getFieldWidthClasses(field),
|
|
|
|
|
{
|
2024-09-23 20:02:38 +02:00
|
|
|
'group/nffield hover:bg-gray-100/50 relative hover:z-10 transition-colors hover:border-gray-200 dark:hover:!bg-gray-900 border-dashed border border-transparent box-border dark:hover:border-blue-900 rounded-md': adminPreview,
|
|
|
|
|
'cursor-pointer':workingFormStore.showEditFieldSidebar && adminPreview,
|
2024-05-22 14:36:42 +02:00
|
|
|
'bg-blue-50 hover:!bg-blue-50 dark:bg-gray-800 rounded-md': beingEdited,
|
2024-05-13 14:47:59 +02:00
|
|
|
}]"
|
2024-09-23 20:02:38 +02:00
|
|
|
@click="setFieldAsSelected"
|
2024-04-15 19:39:03 +02:00
|
|
|
>
|
2024-05-13 14:47:59 +02:00
|
|
|
<div
|
|
|
|
|
class="-m-[1px] w-full max-w-full mx-auto"
|
|
|
|
|
:class="{'relative transition-colors':adminPreview}"
|
|
|
|
|
>
|
2024-04-15 19:39:03 +02:00
|
|
|
<div
|
|
|
|
|
v-if="adminPreview"
|
2025-03-04 05:21:30 +01:00
|
|
|
class="absolute translate-y-full lg:translate-y-0 -bottom-1 left-1/2 -translate-x-1/2 lg:-translate-x-full lg:-left-1 lg:top-1 lg:bottom-0 hidden group-hover/nffield:block z-50"
|
2024-04-15 19:39:03 +02:00
|
|
|
>
|
|
|
|
|
<div
|
2025-03-04 05:21:30 +01:00
|
|
|
class="flex lg:flex-col bg-white !bg-white dark:!bg-white border rounded-md shadow-sm z-50 p-[1px] relative"
|
2024-04-15 19:39:03 +02:00
|
|
|
>
|
|
|
|
|
<div
|
2025-03-04 05:21:30 +01:00
|
|
|
class="p-1 hover:!text-blue-500 dark:hover:!text-blue-500 hover:bg-blue-50 cursor-pointer !text-gray-500 dark:!text-gray-500 flex items-center justify-center rounded-md"
|
2024-04-15 19:39:03 +02:00
|
|
|
role="button"
|
|
|
|
|
@click.prevent="openAddFieldSidebar"
|
|
|
|
|
>
|
Add regex matching filters to open_filters.json (#722)
* Add regex matching filters to open_filters.json
- Introduce new regex-based filters: matches_regex and does_not_match_regex
- Add support for string-based regex matching in both API and client filter configurations
- Update filter schemas to include new regex filter options with expected string type
* Add barcode comparators and regex filters to open_filters.json and validatePropertiesLogic.js
- Introduce new barcode comparators: equals, does_not_equal, contains, does_not_contain, starts_with, ends_with, is_empty, is_not_empty, matches_regex, does_not_match_regex, content_length_equals, content_length_does_not_equal, content_length_greater_than, content_length_greater_than_or_equal_to, content_length_less_than, content_length_less_than_or_equal_to.
- Add regex matching filters: matches_regex and does_not_match_regex to open_filters.json.
- Remove console log statements from validatePropertiesLogic.js and FormPropertyLogicRule.js for cleaner code.
This update enhances the filtering capabilities and improves the validation logic by removing unnecessary debug outputs.
* Refactor Vue Components for Improved Readability and Consistency
- Update CameraUpload.vue to enhance formatting and maintain consistent indentation for better readability.
- Modify OpenFormField.vue to improve tooltip component formatting, ensuring consistent styling across the application.
- Refactor FormSecurityAccess.vue to enhance the layout of the conditional rendering for captcha providers.
- Adjust RegisterForm.vue to improve the formatting of the terms and conditions section, ensuring consistent indentation and readability.
These changes aim to enhance code maintainability and visual consistency across the components, contributing to a cleaner codebase.
---------
Co-authored-by: Julien Nahum <julien@nahum.net>
2025-03-15 06:55:42 +01:00
|
|
|
<UTooltip
|
|
|
|
|
text="Add new field"
|
|
|
|
|
:popper="{ placement: 'right' }"
|
|
|
|
|
class="z-[100]"
|
|
|
|
|
>
|
2025-03-04 05:21:30 +01:00
|
|
|
<Icon
|
|
|
|
|
name="i-heroicons-plus-circle-20-solid"
|
|
|
|
|
class="w-5 h-5 !text-gray-500 dark:!text-gray-500 hover:!text-blue-500 dark:hover:!text-blue-500"
|
|
|
|
|
/>
|
|
|
|
|
</UTooltip>
|
2023-12-09 15:47:03 +01:00
|
|
|
</div>
|
2024-04-15 19:39:03 +02:00
|
|
|
<div
|
2025-03-04 05:21:30 +01:00
|
|
|
class="p-1 hover:!text-blue-500 dark:hover:!text-blue-500 hover:bg-blue-50 cursor-pointer flex items-center justify-center text-center !text-gray-500 dark:!text-gray-500 rounded-md"
|
2024-04-15 19:39:03 +02:00
|
|
|
role="button"
|
|
|
|
|
@click.prevent="editFieldOptions"
|
|
|
|
|
>
|
Add regex matching filters to open_filters.json (#722)
* Add regex matching filters to open_filters.json
- Introduce new regex-based filters: matches_regex and does_not_match_regex
- Add support for string-based regex matching in both API and client filter configurations
- Update filter schemas to include new regex filter options with expected string type
* Add barcode comparators and regex filters to open_filters.json and validatePropertiesLogic.js
- Introduce new barcode comparators: equals, does_not_equal, contains, does_not_contain, starts_with, ends_with, is_empty, is_not_empty, matches_regex, does_not_match_regex, content_length_equals, content_length_does_not_equal, content_length_greater_than, content_length_greater_than_or_equal_to, content_length_less_than, content_length_less_than_or_equal_to.
- Add regex matching filters: matches_regex and does_not_match_regex to open_filters.json.
- Remove console log statements from validatePropertiesLogic.js and FormPropertyLogicRule.js for cleaner code.
This update enhances the filtering capabilities and improves the validation logic by removing unnecessary debug outputs.
* Refactor Vue Components for Improved Readability and Consistency
- Update CameraUpload.vue to enhance formatting and maintain consistent indentation for better readability.
- Modify OpenFormField.vue to improve tooltip component formatting, ensuring consistent styling across the application.
- Refactor FormSecurityAccess.vue to enhance the layout of the conditional rendering for captcha providers.
- Adjust RegisterForm.vue to improve the formatting of the terms and conditions section, ensuring consistent indentation and readability.
These changes aim to enhance code maintainability and visual consistency across the components, contributing to a cleaner codebase.
---------
Co-authored-by: Julien Nahum <julien@nahum.net>
2025-03-15 06:55:42 +01:00
|
|
|
<UTooltip
|
|
|
|
|
text="Edit field settings"
|
|
|
|
|
:popper="{ placement: 'right' }"
|
|
|
|
|
class="z-[100]"
|
|
|
|
|
>
|
2025-03-04 05:21:30 +01:00
|
|
|
<Icon
|
|
|
|
|
name="heroicons:cog-8-tooth-20-solid"
|
|
|
|
|
class="w-5 h-5 !text-gray-500 dark:!text-gray-500 hover:!text-blue-500 dark:hover:!text-blue-500"
|
|
|
|
|
/>
|
|
|
|
|
</UTooltip>
|
2023-12-09 15:47:03 +01:00
|
|
|
</div>
|
2024-09-23 20:02:38 +02:00
|
|
|
<div
|
2025-03-04 05:21:30 +01:00
|
|
|
class="p-1 hover:!text-red-600 dark:hover:!text-red-600 hover:bg-red-50 cursor-pointer flex items-center justify-center text-center !text-red-500 dark:!text-red-500 rounded-md"
|
2024-09-23 20:02:38 +02:00
|
|
|
role="button"
|
|
|
|
|
@click.prevent="removeField"
|
|
|
|
|
>
|
Add regex matching filters to open_filters.json (#722)
* Add regex matching filters to open_filters.json
- Introduce new regex-based filters: matches_regex and does_not_match_regex
- Add support for string-based regex matching in both API and client filter configurations
- Update filter schemas to include new regex filter options with expected string type
* Add barcode comparators and regex filters to open_filters.json and validatePropertiesLogic.js
- Introduce new barcode comparators: equals, does_not_equal, contains, does_not_contain, starts_with, ends_with, is_empty, is_not_empty, matches_regex, does_not_match_regex, content_length_equals, content_length_does_not_equal, content_length_greater_than, content_length_greater_than_or_equal_to, content_length_less_than, content_length_less_than_or_equal_to.
- Add regex matching filters: matches_regex and does_not_match_regex to open_filters.json.
- Remove console log statements from validatePropertiesLogic.js and FormPropertyLogicRule.js for cleaner code.
This update enhances the filtering capabilities and improves the validation logic by removing unnecessary debug outputs.
* Refactor Vue Components for Improved Readability and Consistency
- Update CameraUpload.vue to enhance formatting and maintain consistent indentation for better readability.
- Modify OpenFormField.vue to improve tooltip component formatting, ensuring consistent styling across the application.
- Refactor FormSecurityAccess.vue to enhance the layout of the conditional rendering for captcha providers.
- Adjust RegisterForm.vue to improve the formatting of the terms and conditions section, ensuring consistent indentation and readability.
These changes aim to enhance code maintainability and visual consistency across the components, contributing to a cleaner codebase.
---------
Co-authored-by: Julien Nahum <julien@nahum.net>
2025-03-15 06:55:42 +01:00
|
|
|
<UTooltip
|
|
|
|
|
text="Delete field"
|
|
|
|
|
:popper="{ placement: 'right' }"
|
|
|
|
|
class="z-[100]"
|
|
|
|
|
>
|
2025-03-04 05:21:30 +01:00
|
|
|
<Icon
|
|
|
|
|
name="heroicons:trash-20-solid"
|
|
|
|
|
class="w-5 h-5 !text-red-500 dark:!text-red-500 hover:!text-red-600 dark:hover:!text-red-600"
|
|
|
|
|
/>
|
|
|
|
|
</UTooltip>
|
2024-09-23 20:02:38 +02:00
|
|
|
</div>
|
2023-12-09 15:47:03 +01:00
|
|
|
</div>
|
|
|
|
|
</div>
|
2024-04-15 19:39:03 +02:00
|
|
|
<component
|
|
|
|
|
:is="getFieldComponents"
|
|
|
|
|
v-if="getFieldComponents"
|
|
|
|
|
v-bind="inputProperties(field)"
|
|
|
|
|
:required="isFieldRequired"
|
|
|
|
|
:disabled="isFieldDisabled ? true : null"
|
|
|
|
|
/>
|
2023-12-09 15:47:03 +01:00
|
|
|
<template v-else>
|
2024-04-15 19:39:03 +02:00
|
|
|
<div
|
|
|
|
|
v-if="field.type === 'nf-text' && field.content"
|
|
|
|
|
:id="field.id"
|
|
|
|
|
:key="field.id"
|
2024-10-23 10:34:51 +02:00
|
|
|
class="nf-text w-full my-1.5"
|
2024-04-15 19:39:03 +02:00
|
|
|
:class="[getFieldAlignClasses(field)]"
|
|
|
|
|
v-html="field.content"
|
|
|
|
|
/>
|
|
|
|
|
<div
|
|
|
|
|
v-if="field.type === 'nf-code' && field.content"
|
|
|
|
|
:id="field.id"
|
|
|
|
|
:key="field.id"
|
2024-10-23 10:34:51 +02:00
|
|
|
class="nf-code w-full px-2 my-1.5"
|
2024-04-15 19:39:03 +02:00
|
|
|
v-html="field.content"
|
|
|
|
|
/>
|
|
|
|
|
<div
|
|
|
|
|
v-if="field.type === 'nf-divider'"
|
|
|
|
|
:id="field.id"
|
|
|
|
|
:key="field.id"
|
|
|
|
|
class="border-b my-4 w-full mx-2"
|
|
|
|
|
/>
|
|
|
|
|
<div
|
|
|
|
|
v-if="field.type === 'nf-image' && (field.image_block || !isPublicFormPage)"
|
|
|
|
|
:id="field.id"
|
|
|
|
|
:key="field.id"
|
|
|
|
|
class="my-4 w-full px-2"
|
|
|
|
|
:class="[getFieldAlignClasses(field)]"
|
2024-10-23 10:34:51 +02:00
|
|
|
@dblclick="editFieldOptions"
|
2024-04-15 19:39:03 +02:00
|
|
|
>
|
|
|
|
|
<div
|
|
|
|
|
v-if="!field.image_block"
|
2024-09-23 20:02:38 +02:00
|
|
|
class="p-4 border border-dashed text-center"
|
2024-04-15 19:39:03 +02:00
|
|
|
>
|
2024-09-23 20:02:38 +02:00
|
|
|
<a
|
|
|
|
|
href="#"
|
|
|
|
|
class="text-blue-800 dark:text-blue-200"
|
|
|
|
|
@click.prevent="editFieldOptions"
|
|
|
|
|
>Open block settings to upload image.</a>
|
2023-12-09 15:47:03 +01:00
|
|
|
</div>
|
2024-04-15 19:39:03 +02:00
|
|
|
<img
|
|
|
|
|
v-else
|
|
|
|
|
:alt="field.name"
|
|
|
|
|
:src="field.image_block"
|
2024-12-17 17:10:31 +01:00
|
|
|
class="max-w-full inline-block"
|
2024-07-17 14:22:54 +02:00
|
|
|
:class="theme.default.borderRadius"
|
2024-04-15 19:39:03 +02:00
|
|
|
>
|
2023-12-09 15:47:03 +01:00
|
|
|
</div>
|
|
|
|
|
</template>
|
2024-08-23 15:28:21 +02:00
|
|
|
<div
|
|
|
|
|
class="hidden group-hover/nffield:flex translate-x-full absolute right-0 top-0 h-full w-5 flex-col justify-center pl-1 pt-3"
|
|
|
|
|
>
|
|
|
|
|
<div
|
2024-10-23 10:34:51 +02:00
|
|
|
class="flex items-center bg-gray-100 dark:bg-gray-800 border rounded-md h-12 text-gray-500 dark:text-gray-400 dark:border-gray-500 cursor-grab handle min-h-[40px]"
|
2024-08-23 15:28:21 +02:00
|
|
|
>
|
2024-05-13 14:47:59 +02:00
|
|
|
<Icon
|
|
|
|
|
name="clarity:drag-handle-line"
|
|
|
|
|
class="h-6 w-6 -ml-1 block shrink-0"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-12-09 15:47:03 +01:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
2024-05-13 14:47:59 +02:00
|
|
|
import {computed} from 'vue'
|
2023-12-18 10:35:00 +01:00
|
|
|
import FormLogicPropertyResolver from "~/lib/forms/FormLogicPropertyResolver.js"
|
2024-07-26 11:54:15 +02:00
|
|
|
import CachedDefaultTheme from "~/lib/forms/themes/CachedDefaultTheme.js"
|
2024-05-13 14:47:59 +02:00
|
|
|
import {default as _has} from 'lodash/has'
|
2023-12-09 15:47:03 +01:00
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
name: 'OpenFormField',
|
|
|
|
|
components: {},
|
|
|
|
|
props: {
|
|
|
|
|
form: {
|
|
|
|
|
type: Object,
|
|
|
|
|
required: true
|
|
|
|
|
},
|
|
|
|
|
dataForm: {
|
|
|
|
|
type: Object,
|
|
|
|
|
required: true
|
|
|
|
|
},
|
|
|
|
|
dataFormValue: {
|
|
|
|
|
type: Object,
|
|
|
|
|
required: true
|
|
|
|
|
},
|
|
|
|
|
theme: {
|
2024-07-26 11:54:15 +02:00
|
|
|
type: Object, default: () => {
|
|
|
|
|
const theme = inject("theme", null)
|
|
|
|
|
if (theme) {
|
|
|
|
|
return theme.value
|
|
|
|
|
}
|
|
|
|
|
return CachedDefaultTheme.getInstance()
|
|
|
|
|
}
|
2023-12-09 15:47:03 +01:00
|
|
|
},
|
|
|
|
|
showHidden: {
|
|
|
|
|
type: Boolean,
|
|
|
|
|
default: false
|
|
|
|
|
},
|
2024-04-15 15:19:37 +02:00
|
|
|
darkMode: {
|
|
|
|
|
type: Boolean,
|
|
|
|
|
default: false
|
|
|
|
|
},
|
2023-12-09 15:47:03 +01:00
|
|
|
field: {
|
|
|
|
|
type: Object,
|
|
|
|
|
required: true
|
|
|
|
|
},
|
2024-05-13 14:47:59 +02:00
|
|
|
adminPreview: {type: Boolean, default: false} // If used in FormEditorPreview
|
2023-12-09 15:47:03 +01:00
|
|
|
},
|
|
|
|
|
|
2025-01-27 18:24:27 +01:00
|
|
|
setup() {
|
2023-12-09 15:47:03 +01:00
|
|
|
const workingFormStore = useWorkingFormStore()
|
|
|
|
|
return {
|
|
|
|
|
workingFormStore,
|
2024-01-22 14:28:22 +01:00
|
|
|
currentWorkspace: computed(() => useWorkspacesStore().getCurrent),
|
2023-12-09 15:47:03 +01:00
|
|
|
selectedFieldIndex: computed(() => workingFormStore.selectedFieldIndex),
|
|
|
|
|
showEditFieldSidebar: computed(() => workingFormStore.showEditFieldSidebar)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
computed: {
|
|
|
|
|
/**
|
|
|
|
|
* Get the right input component for the field/options combination
|
|
|
|
|
*/
|
2024-03-19 15:27:21 +01:00
|
|
|
getFieldComponents() {
|
2023-12-09 15:47:03 +01:00
|
|
|
const field = this.field
|
|
|
|
|
if (field.type === 'text' && field.multi_lines) {
|
|
|
|
|
return 'TextAreaInput'
|
|
|
|
|
}
|
|
|
|
|
if (field.type === 'url' && field.file_upload) {
|
|
|
|
|
return 'FileInput'
|
|
|
|
|
}
|
|
|
|
|
if (['select', 'multi_select'].includes(field.type) && field.without_dropdown) {
|
|
|
|
|
return 'FlatSelectInput'
|
|
|
|
|
}
|
|
|
|
|
if (field.type === 'checkbox' && field.use_toggle_switch) {
|
|
|
|
|
return 'ToggleSwitchInput'
|
|
|
|
|
}
|
|
|
|
|
if (field.type === 'signature') {
|
|
|
|
|
return 'SignatureInput'
|
|
|
|
|
}
|
|
|
|
|
if (field.type === 'phone_number' && !field.use_simple_text_input) {
|
|
|
|
|
return 'PhoneInput'
|
|
|
|
|
}
|
2023-12-24 20:19:59 +01:00
|
|
|
return {
|
|
|
|
|
text: 'TextInput',
|
2024-11-28 16:12:24 +01:00
|
|
|
rich_text: 'RichTextAreaInput',
|
2023-12-24 20:19:59 +01:00
|
|
|
number: 'TextInput',
|
2024-03-19 15:27:21 +01:00
|
|
|
rating: 'RatingInput',
|
|
|
|
|
scale: 'ScaleInput',
|
|
|
|
|
slider: 'SliderInput',
|
2023-12-24 20:19:59 +01:00
|
|
|
select: 'SelectInput',
|
|
|
|
|
multi_select: 'SelectInput',
|
|
|
|
|
date: 'DateInput',
|
|
|
|
|
files: 'FileInput',
|
|
|
|
|
checkbox: 'CheckboxInput',
|
|
|
|
|
url: 'TextInput',
|
|
|
|
|
email: 'TextInput',
|
2024-08-23 15:28:21 +02:00
|
|
|
phone_number: 'TextInput',
|
2025-01-03 16:07:58 +01:00
|
|
|
matrix: 'MatrixInput',
|
|
|
|
|
barcode: 'BarcodeInput'
|
2023-12-24 20:19:59 +01:00
|
|
|
}[field.type]
|
2023-12-09 15:47:03 +01:00
|
|
|
},
|
2024-03-19 15:27:21 +01:00
|
|
|
isPublicFormPage() {
|
2024-01-16 12:58:41 +01:00
|
|
|
return this.$route.name === 'forms-slug'
|
2023-12-09 15:47:03 +01:00
|
|
|
},
|
2024-03-19 15:27:21 +01:00
|
|
|
isFieldHidden() {
|
2023-12-09 15:47:03 +01:00
|
|
|
return !this.showHidden && this.shouldBeHidden
|
|
|
|
|
},
|
2024-03-19 15:27:21 +01:00
|
|
|
shouldBeHidden() {
|
2023-12-09 15:47:03 +01:00
|
|
|
return (new FormLogicPropertyResolver(this.field, this.dataFormValue)).isHidden()
|
|
|
|
|
},
|
2024-03-19 15:27:21 +01:00
|
|
|
isFieldRequired() {
|
2023-12-09 15:47:03 +01:00
|
|
|
return (new FormLogicPropertyResolver(this.field, this.dataFormValue)).isRequired()
|
|
|
|
|
},
|
2024-03-19 15:27:21 +01:00
|
|
|
isFieldDisabled() {
|
2023-12-09 15:47:03 +01:00
|
|
|
return (new FormLogicPropertyResolver(this.field, this.dataFormValue)).isDisabled()
|
|
|
|
|
},
|
2024-03-19 15:27:21 +01:00
|
|
|
beingEdited() {
|
2023-12-09 15:47:03 +01:00
|
|
|
return this.adminPreview && this.showEditFieldSidebar && this.form.properties.findIndex((item) => {
|
|
|
|
|
return item.id === this.field.id
|
|
|
|
|
}) === this.selectedFieldIndex
|
|
|
|
|
},
|
2024-03-19 15:27:21 +01:00
|
|
|
selectionFieldsOptions() {
|
2023-12-09 15:47:03 +01:00
|
|
|
// For auto update hidden options
|
|
|
|
|
let fieldsOptions = []
|
|
|
|
|
|
|
|
|
|
if (['select', 'multi_select', 'status'].includes(this.field.type)) {
|
|
|
|
|
fieldsOptions = [...this.field[this.field.type].options]
|
|
|
|
|
if (this.field.hidden_options && this.field.hidden_options.length > 0) {
|
|
|
|
|
fieldsOptions = fieldsOptions.filter((option) => {
|
|
|
|
|
return this.field.hidden_options.indexOf(option.id) < 0
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return fieldsOptions
|
|
|
|
|
},
|
2024-03-19 15:27:21 +01:00
|
|
|
fieldSideBarOpened() {
|
2023-12-09 15:47:03 +01:00
|
|
|
return this.adminPreview && (this.form && this.selectedFieldIndex !== null) ? (this.form.properties[this.selectedFieldIndex] && this.showEditFieldSidebar) : false
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
watch: {},
|
|
|
|
|
|
2024-03-19 15:27:21 +01:00
|
|
|
mounted() {
|
2023-12-09 15:47:03 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
methods: {
|
2024-03-19 15:27:21 +01:00
|
|
|
editFieldOptions() {
|
2024-09-23 20:02:38 +02:00
|
|
|
if (!this.adminPreview) return
|
|
|
|
|
this.workingFormStore.openSettingsForField(this.field)
|
|
|
|
|
},
|
|
|
|
|
setFieldAsSelected () {
|
|
|
|
|
if (!this.adminPreview || !this.workingFormStore.showEditFieldSidebar) return
|
2023-12-09 15:47:03 +01:00
|
|
|
this.workingFormStore.openSettingsForField(this.field)
|
|
|
|
|
},
|
2024-03-19 15:27:21 +01:00
|
|
|
openAddFieldSidebar() {
|
2024-09-23 20:02:38 +02:00
|
|
|
if (!this.adminPreview) return
|
2023-12-09 15:47:03 +01:00
|
|
|
this.workingFormStore.openAddFieldSidebar(this.field)
|
|
|
|
|
},
|
2024-09-23 20:02:38 +02:00
|
|
|
removeField () {
|
|
|
|
|
if (!this.adminPreview) return
|
|
|
|
|
this.workingFormStore.removeField(this.field)
|
|
|
|
|
},
|
2024-03-19 15:27:21 +01:00
|
|
|
getFieldWidthClasses(field) {
|
2024-05-22 09:38:22 +02:00
|
|
|
if (!field.width || field.width === 'full') return 'col-span-full'
|
2023-12-09 15:47:03 +01:00
|
|
|
else if (field.width === '1/2') {
|
2024-05-22 14:36:42 +02:00
|
|
|
return 'sm:col-span-6 col-span-full'
|
2023-12-09 15:47:03 +01:00
|
|
|
} else if (field.width === '1/3') {
|
2024-05-22 14:36:42 +02:00
|
|
|
return 'sm:col-span-4 col-span-full'
|
2023-12-09 15:47:03 +01:00
|
|
|
} else if (field.width === '2/3') {
|
2024-05-22 14:36:42 +02:00
|
|
|
return 'sm:col-span-8 col-span-full'
|
2023-12-09 15:47:03 +01:00
|
|
|
} else if (field.width === '1/4') {
|
2024-05-22 14:36:42 +02:00
|
|
|
return 'sm:col-span-3 col-span-full'
|
2023-12-09 15:47:03 +01:00
|
|
|
} else if (field.width === '3/4') {
|
2024-05-22 14:36:42 +02:00
|
|
|
return 'sm:col-span-9 col-span-full'
|
2023-12-09 15:47:03 +01:00
|
|
|
}
|
|
|
|
|
},
|
2024-03-19 15:27:21 +01:00
|
|
|
getFieldAlignClasses(field) {
|
2023-12-09 15:47:03 +01:00
|
|
|
if (!field.align || field.align === 'left') return 'text-left'
|
|
|
|
|
else if (field.align === 'right') {
|
|
|
|
|
return 'text-right'
|
|
|
|
|
} else if (field.align === 'center') {
|
|
|
|
|
return 'text-center'
|
|
|
|
|
} else if (field.align === 'justify') {
|
|
|
|
|
return 'text-justify'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
/**
|
|
|
|
|
* Get the right input component options for the field/options
|
|
|
|
|
*/
|
2024-03-19 15:27:21 +01:00
|
|
|
inputProperties(field) {
|
2023-12-09 15:47:03 +01:00
|
|
|
const inputProperties = {
|
|
|
|
|
key: field.id,
|
|
|
|
|
name: field.id,
|
|
|
|
|
form: this.dataForm,
|
|
|
|
|
label: (field.hide_field_name) ? null : field.name + ((this.shouldBeHidden) ? ' (Hidden Field)' : ''),
|
|
|
|
|
color: this.form.color,
|
|
|
|
|
placeholder: field.placeholder,
|
|
|
|
|
help: field.help,
|
|
|
|
|
helpPosition: (field.help_position) ? field.help_position : 'below_input',
|
|
|
|
|
uppercaseLabels: this.form.uppercase_labels == 1 || this.form.uppercase_labels == true,
|
|
|
|
|
theme: this.theme,
|
2024-11-20 17:06:11 +01:00
|
|
|
maxCharLimit: (field.max_char_limit) ? parseInt(field.max_char_limit) : null,
|
2024-04-15 15:09:19 +02:00
|
|
|
showCharLimit: field.show_char_limit || false,
|
2024-12-04 18:32:14 +01:00
|
|
|
isDark: this.darkMode,
|
|
|
|
|
locale: (this.form?.language) ? this.form.language : 'en'
|
2023-12-09 15:47:03 +01:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 15:28:21 +02:00
|
|
|
if (field.type === 'matrix') {
|
|
|
|
|
inputProperties.rows = field.rows
|
|
|
|
|
inputProperties.columns = field.columns
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-03 16:07:58 +01:00
|
|
|
if (field.type === 'barcode') {
|
|
|
|
|
inputProperties.decoders = field.decoders
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-23 20:02:38 +02:00
|
|
|
if (['select','multi_select'].includes(field.type) && !this.isFieldRequired) {
|
|
|
|
|
inputProperties.clearable = true
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-09 15:47:03 +01:00
|
|
|
if (['select', 'multi_select'].includes(field.type)) {
|
2024-04-03 11:49:33 +02:00
|
|
|
inputProperties.options = (_has(field, field.type))
|
2023-12-09 15:47:03 +01:00
|
|
|
? field[field.type].options.map(option => {
|
|
|
|
|
return {
|
|
|
|
|
name: option.name,
|
|
|
|
|
value: option.name
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
: []
|
|
|
|
|
inputProperties.multiple = (field.type === 'multi_select')
|
|
|
|
|
inputProperties.allowCreation = (field.allow_creation === true)
|
|
|
|
|
inputProperties.searchable = (inputProperties.options.length > 4)
|
|
|
|
|
} else if (field.type === 'date') {
|
2024-04-15 15:09:19 +02:00
|
|
|
inputProperties.dateFormat = field.date_format
|
2024-07-15 23:31:04 +02:00
|
|
|
inputProperties.timeFormat = field.time_format
|
2023-12-09 15:47:03 +01:00
|
|
|
if (field.with_time) {
|
|
|
|
|
inputProperties.withTime = true
|
2024-04-15 15:09:19 +02:00
|
|
|
}
|
|
|
|
|
if (field.date_range) {
|
2023-12-09 15:47:03 +01:00
|
|
|
inputProperties.dateRange = true
|
|
|
|
|
}
|
|
|
|
|
if (field.disable_past_dates) {
|
|
|
|
|
inputProperties.disablePastDates = true
|
|
|
|
|
} else if (field.disable_future_dates) {
|
|
|
|
|
inputProperties.disableFutureDates = true
|
|
|
|
|
}
|
|
|
|
|
} else if (field.type === 'files' || (field.type === 'url' && field.file_upload)) {
|
|
|
|
|
inputProperties.multiple = (field.multiple !== undefined && field.multiple)
|
2024-03-25 11:00:00 +01:00
|
|
|
inputProperties.cameraUpload = (field.camera_upload !== undefined && field.camera_upload)
|
2024-03-22 12:10:18 +01:00
|
|
|
let maxFileSize = (this.form?.workspace && this.form?.workspace.max_file_size) ? this.form?.workspace?.max_file_size : 10
|
|
|
|
|
if (field?.max_file_size > 0) {
|
|
|
|
|
maxFileSize = Math.min(field.max_file_size, maxFileSize)
|
|
|
|
|
}
|
|
|
|
|
inputProperties.mbLimit = maxFileSize
|
2023-12-09 15:47:03 +01:00
|
|
|
inputProperties.accept = (this.form.is_pro && field.allowed_file_types) ? field.allowed_file_types : ''
|
2024-03-19 15:27:21 +01:00
|
|
|
} else if (field.type === 'rating') {
|
|
|
|
|
inputProperties.numberOfStars = parseInt(field.rating_max_value) ?? 5
|
|
|
|
|
} else if (field.type === 'scale') {
|
2024-06-10 13:23:18 +02:00
|
|
|
inputProperties.minScale = parseFloat(field.scale_min_value) ?? 1
|
|
|
|
|
inputProperties.maxScale = parseFloat(field.scale_max_value) ?? 5
|
2024-05-24 10:34:47 +02:00
|
|
|
inputProperties.stepScale = parseFloat(field.scale_step_value) ?? 1
|
2024-03-19 15:27:21 +01:00
|
|
|
} else if (field.type === 'slider') {
|
2024-01-29 12:57:40 +01:00
|
|
|
inputProperties.minSlider = parseInt(field.slider_min_value) ?? 0
|
|
|
|
|
inputProperties.maxSlider = parseInt(field.slider_max_value) ?? 50
|
|
|
|
|
inputProperties.stepSlider = parseInt(field.slider_step_value) ?? 5
|
2023-12-09 15:47:03 +01:00
|
|
|
} else if (field.type === 'number' || (field.type === 'phone_number' && field.use_simple_text_input)) {
|
2024-04-15 19:39:03 +02:00
|
|
|
inputProperties.pattern = '/d*'
|
2023-12-09 15:47:03 +01:00
|
|
|
} else if (field.type === 'phone_number' && !field.use_simple_text_input) {
|
|
|
|
|
inputProperties.unavailableCountries = field.unavailable_countries ?? []
|
2024-07-17 13:21:54 +02:00
|
|
|
} else if (field.type === 'text' && field.secret_input) {
|
|
|
|
|
inputProperties.nativeType = 'password'
|
2023-12-09 15:47:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return inputProperties
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang='scss' scoped>
|
|
|
|
|
.nf-text {
|
|
|
|
|
ol {
|
|
|
|
|
@apply list-decimal list-inside;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ul {
|
|
|
|
|
@apply list-disc list-inside;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|